hyperframes 0.7.103 → 0.7.105

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -50,7 +50,7 @@ var VERSION;
50
50
  var init_version = __esm({
51
51
  "src/version.ts"() {
52
52
  "use strict";
53
- VERSION = true ? "0.7.103" : "0.0.0-dev";
53
+ VERSION = true ? "0.7.105" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -4819,7 +4819,7 @@ var require_util = __commonJS({
4819
4819
  return url;
4820
4820
  }
4821
4821
  exports.urlGenerate = urlGenerate;
4822
- function normalize(aPath) {
4822
+ function normalize3(aPath) {
4823
4823
  var path2 = aPath;
4824
4824
  var url = urlParse(aPath);
4825
4825
  if (url) {
@@ -4856,8 +4856,8 @@ var require_util = __commonJS({
4856
4856
  }
4857
4857
  return path2;
4858
4858
  }
4859
- exports.normalize = normalize;
4860
- function join138(aRoot, aPath) {
4859
+ exports.normalize = normalize3;
4860
+ function join140(aRoot, aPath) {
4861
4861
  if (aRoot === "") {
4862
4862
  aRoot = ".";
4863
4863
  }
@@ -4882,14 +4882,14 @@ var require_util = __commonJS({
4882
4882
  aRootUrl.host = aPath;
4883
4883
  return urlGenerate(aRootUrl);
4884
4884
  }
4885
- var joined = aPath.charAt(0) === "/" ? aPath : normalize(aRoot.replace(/\/+$/, "") + "/" + aPath);
4885
+ var joined = aPath.charAt(0) === "/" ? aPath : normalize3(aRoot.replace(/\/+$/, "") + "/" + aPath);
4886
4886
  if (aRootUrl) {
4887
4887
  aRootUrl.path = joined;
4888
4888
  return urlGenerate(aRootUrl);
4889
4889
  }
4890
4890
  return joined;
4891
4891
  }
4892
- exports.join = join138;
4892
+ exports.join = join140;
4893
4893
  exports.isAbsolute = function(aPath) {
4894
4894
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
4895
4895
  };
@@ -5062,9 +5062,9 @@ var require_util = __commonJS({
5062
5062
  parsed.path = parsed.path.substring(0, index + 1);
5063
5063
  }
5064
5064
  }
5065
- sourceURL = join138(urlGenerate(parsed), sourceURL);
5065
+ sourceURL = join140(urlGenerate(parsed), sourceURL);
5066
5066
  }
5067
- return normalize(sourceURL);
5067
+ return normalize3(sourceURL);
5068
5068
  }
5069
5069
  exports.computeSourceURL = computeSourceURL;
5070
5070
  }
@@ -6815,7 +6815,7 @@ var require_esprima2 = __commonJS({
6815
6815
  return parse9(code, parsingOptions, delegate);
6816
6816
  }
6817
6817
  exports2.parseScript = parseScript2;
6818
- function tokenize(code, options, delegate) {
6818
+ function tokenize2(code, options, delegate) {
6819
6819
  var tokenizer2 = new tokenizer_1.Tokenizer(code, options);
6820
6820
  var tokens;
6821
6821
  tokens = [];
@@ -6838,7 +6838,7 @@ var require_esprima2 = __commonJS({
6838
6838
  }
6839
6839
  return tokens;
6840
6840
  }
6841
- exports2.tokenize = tokenize;
6841
+ exports2.tokenize = tokenize2;
6842
6842
  var syntax_1 = __webpack_require__(2);
6843
6843
  exports2.Syntax = syntax_1.Syntax;
6844
6844
  exports2.version = "4.0.1";
@@ -13003,7 +13003,7 @@ var require_options = __commonJS({
13003
13003
  tokens: true
13004
13004
  };
13005
13005
  var hasOwn4 = defaults.hasOwnProperty;
13006
- function normalize(opts) {
13006
+ function normalize3(opts) {
13007
13007
  var options = opts || defaults;
13008
13008
  function get(key2) {
13009
13009
  return hasOwn4.call(options, key2) ? options[key2] : defaults[key2];
@@ -13030,7 +13030,7 @@ var require_options = __commonJS({
13030
13030
  tokens: !!get("tokens")
13031
13031
  };
13032
13032
  }
13033
- exports.normalize = normalize;
13033
+ exports.normalize = normalize3;
13034
13034
  }
13035
13035
  });
13036
13036
 
@@ -21731,7 +21731,7 @@ var require_lib = __commonJS({
21731
21731
  }
21732
21732
  var skipWhiteSpace2 = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
21733
21733
  var skipWhiteSpaceInLine = /(?:[^\S\n\r\u2028\u2029]|\/\/.*|\/\*.*?\*\/)*/g;
21734
- function isWhitespace3(code2) {
21734
+ function isWhitespace4(code2) {
21735
21735
  switch (code2) {
21736
21736
  case 9:
21737
21737
  case 11:
@@ -23238,7 +23238,7 @@ var require_lib = __commonJS({
23238
23238
  }
23239
23239
  break;
23240
23240
  default:
23241
- if (isWhitespace3(ch)) {
23241
+ if (isWhitespace4(ch)) {
23242
23242
  ++this.state.pos;
23243
23243
  } else if (ch === 45 && !this.inModule && this.optionFlags & 8192) {
23244
23244
  const pos = this.state.pos;
@@ -40807,7 +40807,7 @@ function formatAttributes(attributes2, opts) {
40807
40807
  var _a4;
40808
40808
  if (!attributes2)
40809
40809
  return;
40810
- const encode2 = ((_a4 = opts.encodeEntities) !== null && _a4 !== void 0 ? _a4 : opts.decodeEntities) === false ? replaceQuotes : opts.xmlMode || opts.encodeEntities !== "utf8" ? encodeXML : escapeAttribute;
40810
+ const encode3 = ((_a4 = opts.encodeEntities) !== null && _a4 !== void 0 ? _a4 : opts.decodeEntities) === false ? replaceQuotes : opts.xmlMode || opts.encodeEntities !== "utf8" ? encodeXML : escapeAttribute;
40811
40811
  return Object.keys(attributes2).map((key2) => {
40812
40812
  var _a5, _b;
40813
40813
  const value = (_a5 = attributes2[key2]) !== null && _a5 !== void 0 ? _a5 : "";
@@ -40817,7 +40817,7 @@ function formatAttributes(attributes2, opts) {
40817
40817
  if (!opts.emptyAttrs && !opts.xmlMode && value === "") {
40818
40818
  return key2;
40819
40819
  }
40820
- return `${key2}="${encode2(value)}"`;
40820
+ return `${key2}="${encode3(value)}"`;
40821
40821
  }).join(" ");
40822
40822
  }
40823
40823
  function render(node, options = {}) {
@@ -62930,7 +62930,10 @@ function passthroughFields(parsed) {
62930
62930
  skillsUpdateAvailable: parsed.skillsUpdateAvailable,
62931
62931
  skillsOutdatedCount: parsed.skillsOutdatedCount,
62932
62932
  skillsMissingCount: parsed.skillsMissingCount,
62933
- skillsRemovedCount: parsed.skillsRemovedCount
62933
+ skillsRemovedCount: parsed.skillsRemovedCount,
62934
+ // Consent, so it survives the run that recorded it. Undefined stays
62935
+ // undefined on purpose: it means never asked, which is not the same as no.
62936
+ localEmbeddingEnabled: parsed.localEmbeddingEnabled
62934
62937
  };
62935
62938
  }
62936
62939
  function guardedFields(parsed) {
@@ -63465,6 +63468,12 @@ function resolveDefaultDrawElement(args) {
63465
63468
  if (!isDrawElementPlatform(args.platform) || args.browserGpuMode === "software") return false;
63466
63469
  return args.workerEncode;
63467
63470
  }
63471
+ function explainDrawElementDisabled(args) {
63472
+ if (!isDrawElementPlatform(args.platform)) return "unsupported_platform";
63473
+ if (args.browserGpuMode === "software") return "software_gpu";
63474
+ if (!args.workerEncode) return "worker_encode_off";
63475
+ return "disabled";
63476
+ }
63468
63477
  function resolveConfig(overrides) {
63469
63478
  const env = (key2) => process.env[key2];
63470
63479
  const envNum = (key2, fallback) => {
@@ -74478,7 +74487,7 @@ var require_tokenize = __commonJS({
74478
74487
  var _b;
74479
74488
  Object.defineProperty(exports, "__esModule", { value: true });
74480
74489
  exports.FIELDS = void 0;
74481
- exports.default = tokenize;
74490
+ exports.default = tokenize2;
74482
74491
  var t2 = __importStar2(require_tokenTypes());
74483
74492
  var unescapable = (_a4 = {}, _a4[t2.tab] = true, _a4[t2.newline] = true, _a4[t2.cr] = true, _a4[t2.feed] = true, _a4);
74484
74493
  var wordDelimiters = (_b = {}, _b[t2.space] = true, _b[t2.tab] = true, _b[t2.newline] = true, _b[t2.cr] = true, _b[t2.feed] = true, _b[t2.ampersand] = true, _b[t2.asterisk] = true, _b[t2.bang] = true, _b[t2.comma] = true, _b[t2.colon] = true, _b[t2.semicolon] = true, _b[t2.openParenthesis] = true, _b[t2.closeParenthesis] = true, _b[t2.openSquare] = true, _b[t2.closeSquare] = true, _b[t2.singleQuote] = true, _b[t2.doubleQuote] = true, _b[t2.plus] = true, _b[t2.pipe] = true, _b[t2.tilde] = true, _b[t2.greaterThan] = true, _b[t2.equals] = true, _b[t2.dollar] = true, _b[t2.caret] = true, _b[t2.slash] = true, _b);
@@ -74531,7 +74540,7 @@ var require_tokenize = __commonJS({
74531
74540
  START_POS: 5,
74532
74541
  END_POS: 6
74533
74542
  };
74534
- function tokenize(input2) {
74543
+ function tokenize2(input2) {
74535
74544
  var tokens = [];
74536
74545
  var css = input2.css.valueOf();
74537
74546
  var length = css.length;
@@ -90278,6 +90287,7 @@ __export(src_exports, {
90278
90287
  encodeFramesChunkedConcat: () => encodeFramesChunkedConcat,
90279
90288
  encodeFramesFromDir: () => encodeFramesFromDir,
90280
90289
  executeParallelCapture: () => executeParallelCapture,
90290
+ explainDrawElementDisabled: () => explainDrawElementDisabled,
90281
90291
  extractAllVideoFrames: () => extractAllVideoFrames,
90282
90292
  extractAudioMetadata: () => extractAudioMetadata,
90283
90293
  extractFinalVideoFrameTimestamp: () => extractFinalVideoFrameTimestamp,
@@ -94442,49 +94452,88 @@ var init_ffmpeg = __esm({
94442
94452
  });
94443
94453
 
94444
94454
  // src/utils/download.ts
94455
+ import { randomUUID as randomUUID6 } from "crypto";
94445
94456
  import { createWriteStream as createWriteStream2, renameSync as renameSync4, unlinkSync as unlinkSync2 } from "fs";
94446
94457
  import { get as httpsGet } from "https";
94458
+ import { Transform as Transform2 } from "stream";
94447
94459
  import { pipeline as pipeline2 } from "stream/promises";
94460
+ function redirectTarget(location, from) {
94461
+ return new URL(location, from).toString();
94462
+ }
94448
94463
  function removePartialFile(path2) {
94449
94464
  try {
94450
94465
  unlinkSync2(path2);
94451
94466
  } catch {
94452
94467
  }
94453
94468
  }
94469
+ function enforceByteLimit(maxBytes) {
94470
+ let received = 0;
94471
+ return new Transform2({
94472
+ transform(chunk, _encoding, callback) {
94473
+ received += chunk.byteLength;
94474
+ callback(
94475
+ received > maxBytes ? new Error(`Download exceeded ${maxBytes} bytes`) : null,
94476
+ chunk
94477
+ );
94478
+ }
94479
+ });
94480
+ }
94454
94481
  function downloadFile(url, dest, options = {}) {
94455
- const tmp = `${dest}.tmp`;
94482
+ const tmp = `${dest}.${process.pid}.${randomUUID6()}.tmp`;
94456
94483
  const timeoutMs = options.timeoutMs ?? DEFAULT_DOWNLOAD_TIMEOUT_MS;
94484
+ const maxBytes = options.maxBytes;
94457
94485
  return new Promise((resolve77, reject) => {
94458
- const follow = (u) => {
94486
+ const follow = (u, hops = 0) => {
94459
94487
  let activeResponse;
94460
94488
  let responsePipelineStarted = false;
94461
94489
  let requestError;
94462
- const request = httpsGet(u, (res) => {
94463
- activeResponse = res;
94464
- if (res.statusCode === 301 || res.statusCode === 302) {
94465
- const location = res.headers.location;
94466
- if (location) {
94490
+ let request;
94491
+ try {
94492
+ request = httpsGet(u, (res) => {
94493
+ activeResponse = res;
94494
+ if (res.statusCode && REDIRECT_CODES.has(res.statusCode)) {
94495
+ const location = res.headers.location;
94496
+ if (location) {
94497
+ if (hops >= MAX_REDIRECTS2) {
94498
+ res.resume();
94499
+ removePartialFile(tmp);
94500
+ reject(
94501
+ new Error(`Download failed: more than ${MAX_REDIRECTS2} redirects from ${url}`)
94502
+ );
94503
+ return;
94504
+ }
94505
+ res.resume();
94506
+ try {
94507
+ follow(redirectTarget(location, u), hops + 1);
94508
+ } catch (error) {
94509
+ removePartialFile(tmp);
94510
+ reject(error);
94511
+ }
94512
+ return;
94513
+ }
94514
+ }
94515
+ if (res.statusCode !== 200) {
94467
94516
  res.resume();
94468
- follow(location);
94517
+ removePartialFile(tmp);
94518
+ reject(new Error(`Download failed: HTTP ${res.statusCode}`));
94469
94519
  return;
94470
94520
  }
94471
- }
94472
- if (res.statusCode !== 200) {
94473
- res.resume();
94474
- removePartialFile(tmp);
94475
- reject(new Error(`Download failed: HTTP ${res.statusCode}`));
94476
- return;
94477
- }
94478
- const file = createWriteStream2(tmp);
94479
- responsePipelineStarted = true;
94480
- pipeline2(res, file).then(() => {
94481
- renameSync4(tmp, dest);
94482
- resolve77();
94483
- }).catch((err) => {
94484
- removePartialFile(tmp);
94485
- reject(requestError ?? err);
94521
+ const file = createWriteStream2(tmp);
94522
+ responsePipelineStarted = true;
94523
+ const transfer = maxBytes === void 0 ? pipeline2(res, file) : pipeline2(res, enforceByteLimit(maxBytes), file);
94524
+ transfer.then(() => {
94525
+ renameSync4(tmp, dest);
94526
+ resolve77();
94527
+ }).catch((err) => {
94528
+ removePartialFile(tmp);
94529
+ reject(requestError ?? err);
94530
+ });
94486
94531
  });
94487
- });
94532
+ } catch (error) {
94533
+ removePartialFile(tmp);
94534
+ reject(error);
94535
+ return;
94536
+ }
94488
94537
  request.setTimeout(timeoutMs, () => {
94489
94538
  request.destroy(new Error(`Download timed out after ${timeoutMs}ms`));
94490
94539
  });
@@ -94501,11 +94550,13 @@ function downloadFile(url, dest, options = {}) {
94501
94550
  follow(url);
94502
94551
  });
94503
94552
  }
94504
- var DEFAULT_DOWNLOAD_TIMEOUT_MS;
94553
+ var DEFAULT_DOWNLOAD_TIMEOUT_MS, REDIRECT_CODES, MAX_REDIRECTS2;
94505
94554
  var init_download = __esm({
94506
94555
  "src/utils/download.ts"() {
94507
94556
  "use strict";
94508
94557
  DEFAULT_DOWNLOAD_TIMEOUT_MS = 3e4;
94558
+ REDIRECT_CODES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
94559
+ MAX_REDIRECTS2 = 10;
94509
94560
  }
94510
94561
  });
94511
94562
 
@@ -94714,7 +94765,7 @@ import { execFileSync as execFileSync5 } from "child_process";
94714
94765
  import { existsSync as existsSync25, readFileSync as readFileSync14, mkdirSync as mkdirSync12, unlinkSync as unlinkSync3 } from "fs";
94715
94766
  import { join as join21, extname as extname5 } from "path";
94716
94767
  import { tmpdir as tmpdir3 } from "os";
94717
- import { randomUUID as randomUUID6 } from "crypto";
94768
+ import { randomUUID as randomUUID7 } from "crypto";
94718
94769
  function detectLanguage(whisperPath, modelPath2, wavPath) {
94719
94770
  try {
94720
94771
  const output = execFileSync5(whisperPath, ["--model", modelPath2, "--detect-language", wavPath], {
@@ -94856,7 +94907,7 @@ function isVideoFile(filePath) {
94856
94907
  return VIDEO_EXTENSIONS.has(extname5(filePath).toLowerCase());
94857
94908
  }
94858
94909
  function tempWavPath() {
94859
- return join21(tmpdir3(), `hyperframes-audio-${process.pid}-${randomUUID6()}.wav`);
94910
+ return join21(tmpdir3(), `hyperframes-audio-${process.pid}-${randomUUID7()}.wav`);
94860
94911
  }
94861
94912
  function extractAudio(videoPath) {
94862
94913
  const ffmpegPath = findFFmpeg();
@@ -97313,8 +97364,8 @@ function detectHyperframesServer(port, normalizedProjectDir, expectedServerBuild
97313
97364
  if (json.isHyperframes !== true) {
97314
97365
  return resolveResult({ type: "not-hyperframes" });
97315
97366
  }
97316
- const normalize = (p2) => resolve14(p2).replace(/\\/g, "/").toLowerCase();
97317
- if (normalize(json.projectDir) === normalizedProjectDir) {
97367
+ const normalize3 = (p2) => resolve14(p2).replace(/\\/g, "/").toLowerCase();
97368
+ if (normalize3(json.projectDir) === normalizedProjectDir) {
97318
97369
  if (expectedServerBuildSignature !== null && json.serverBuildSignature !== expectedServerBuildSignature) {
97319
97370
  return resolveResult({ type: "mismatch", projectName: json.projectName });
97320
97371
  }
@@ -98075,6 +98126,7 @@ function shouldWatchProjectFile(filename) {
98075
98126
  }
98076
98127
  function createProjectWatcher(projectDir) {
98077
98128
  const listeners = /* @__PURE__ */ new Set();
98129
+ const pendingPaths = /* @__PURE__ */ new Set();
98078
98130
  let debounceTimer = null;
98079
98131
  let watcher = null;
98080
98132
  try {
@@ -98082,10 +98134,16 @@ function createProjectWatcher(projectDir) {
98082
98134
  if (!filename) return;
98083
98135
  const relativePath = filename.toString();
98084
98136
  if (!shouldWatchProjectFile(relativePath)) return;
98137
+ pendingPaths.add(relativePath);
98085
98138
  if (debounceTimer) clearTimeout(debounceTimer);
98086
98139
  debounceTimer = setTimeout(() => {
98087
- for (const fn of listeners) {
98088
- fn(relativePath);
98140
+ const changedPaths = [...pendingPaths];
98141
+ pendingPaths.clear();
98142
+ debounceTimer = null;
98143
+ for (const changedPath of changedPaths) {
98144
+ for (const fn of listeners) {
98145
+ fn(changedPath);
98146
+ }
98089
98147
  }
98090
98148
  }, DEBOUNCE_MS);
98091
98149
  });
@@ -98104,6 +98162,7 @@ function createProjectWatcher(projectDir) {
98104
98162
  },
98105
98163
  close() {
98106
98164
  if (debounceTimer) clearTimeout(debounceTimer);
98165
+ pendingPaths.clear();
98107
98166
  watcher?.close();
98108
98167
  listeners.clear();
98109
98168
  }
@@ -99464,7 +99523,7 @@ var init_chunk_6H3V3WGJ = __esm({
99464
99523
 
99465
99524
  // ../studio-server/dist/chunk-ZPI6QXJH.js
99466
99525
  import { spawn as spawn8 } from "child_process";
99467
- import { createHash as createHash7, randomUUID as randomUUID7 } from "crypto";
99526
+ import { createHash as createHash7, randomUUID as randomUUID8 } from "crypto";
99468
99527
  import {
99469
99528
  existsSync as existsSync210,
99470
99529
  mkdirSync as mkdirSync15,
@@ -99788,7 +99847,7 @@ async function transcodeToCache(absoluteSourcePath, cachePath2, variant) {
99788
99847
  if (existsSync210(cachePath2)) return cachePath2;
99789
99848
  const cacheDir = dirname14(cachePath2);
99790
99849
  mkdirSync15(cacheDir, { recursive: true });
99791
- const tempPath = join29(cacheDir, `.tmp-${randomUUID7()}-${basename4(cachePath2)}`);
99850
+ const tempPath = join29(cacheDir, `.tmp-${randomUUID8()}-${basename4(cachePath2)}`);
99792
99851
  try {
99793
99852
  await runFfmpeg2(absoluteSourcePath, tempPath, variant);
99794
99853
  renameSync6(tempPath, cachePath2);
@@ -106705,7 +106764,7 @@ import { basename as basename5, join as join42 } from "path";
106705
106764
  import { mkdirSync as mkdirSync22, readdirSync as readdirSync32, readFileSync as readFileSync32, unlinkSync as unlinkSync5, writeFileSync as writeFileSync32 } from "fs";
106706
106765
  import { Buffer as Buffer2 } from "buffer";
106707
106766
  import { join as join52, relative as relative22 } from "path";
106708
- import { createHash as createHash22, randomUUID as randomUUID8 } from "crypto";
106767
+ import { createHash as createHash22, randomUUID as randomUUID9 } from "crypto";
106709
106768
  import { existsSync as existsSync37, readFileSync as readFileSync42, realpathSync as realpathSync6 } from "fs";
106710
106769
  import { randomUUID as randomUUID22 } from "crypto";
106711
106770
  import { dirname as dirname15, relative as relative32, resolve as resolve24, sep as sep7 } from "path";
@@ -107168,7 +107227,7 @@ function fileContentVersion(content) {
107168
107227
  }
107169
107228
  function createWriteToken(requestToken) {
107170
107229
  const token = requestToken?.trim();
107171
- return token && token.length <= 200 ? token : randomUUID8();
107230
+ return token && token.length <= 200 ? token : randomUUID9();
107172
107231
  }
107173
107232
  function recordFileWriteReceipt(absPath, receipt) {
107174
107233
  const now = Date.now();
@@ -107178,12 +107237,13 @@ function recordFileWriteReceipt(absPath, receipt) {
107178
107237
  current2.push({ ...receipt, recordedAt: now });
107179
107238
  receipts.set(absPath, current2);
107180
107239
  }
107181
- function consumeFileWriteReceipt(absPath) {
107240
+ function consumeFileWriteReceipt(absPath, expectedVersion) {
107182
107241
  const now = Date.now();
107183
107242
  const current2 = (receipts.get(absPath) ?? []).filter(
107184
107243
  (entry) => now - entry.recordedAt < RECEIPT_TTL_MS
107185
107244
  );
107186
- const receipt = current2.shift() ?? null;
107245
+ const receiptIndex = current2.findIndex((entry) => entry.version === expectedVersion);
107246
+ const receipt = receiptIndex === -1 ? null : current2.splice(receiptIndex, 1)[0] ?? null;
107187
107247
  if (current2.length > 0) receipts.set(absPath, current2);
107188
107248
  else receipts.delete(absPath);
107189
107249
  if (!receipt) return null;
@@ -107524,19 +107584,44 @@ function commitElementPatchBatches(projectDir, batches, writeFile4 = writeFileSy
107524
107584
  }
107525
107585
  return { durable: true, files };
107526
107586
  }
107587
+ function commitElementPatchBatchesWithReceipts(c3, projectDir, batches) {
107588
+ const result = commitElementPatchBatches(projectDir, batches);
107589
+ if ("error" in result || !result.durable) return result;
107590
+ for (const file of result.files) {
107591
+ if (!file.changed) continue;
107592
+ const absPath = resolveWithinProject(projectDir, file.sourceFile);
107593
+ if (!absPath) throw new Error(`Committed element patch escaped project: ${file.sourceFile}`);
107594
+ recordMutationReceipt(c3, file.sourceFile, absPath, file.after);
107595
+ }
107596
+ return result;
107597
+ }
107598
+ function recordMutationReceipt(c3, filePath, absPath, html) {
107599
+ const version2 = fileContentVersion(html);
107600
+ const writeToken = createWriteToken(c3.req.header("X-Hyperframes-Write-Token"));
107601
+ recordFileWriteReceipt(absPath, { path: filePath, version: version2, writeToken });
107602
+ return { version: version2, writeToken };
107603
+ }
107604
+ function writeFileWithReceipt(c3, filePath, absPath, html) {
107605
+ writeFileSync42(absPath, html, "utf-8");
107606
+ return recordMutationReceipt(c3, filePath, absPath, html);
107607
+ }
107608
+ function writeMutationResult(c3, projectDir, filePath, absPath, html) {
107609
+ const backup = snapshotBeforeWrite(projectDir, absPath);
107610
+ if (backup.error) console.warn(`Failed to create backup for ${filePath}: ${backup.error}`);
107611
+ const { version: version2 } = writeFileWithReceipt(c3, filePath, absPath, html);
107612
+ return { backupPath: backupPathForResponse(projectDir, backup.backupPath), version: version2 };
107613
+ }
107527
107614
  function writeIfChanged(c3, projectDir, filePath, absPath, original, next) {
107528
107615
  if (next === original) {
107529
107616
  return c3.json({ ok: true, changed: false, content: original, path: filePath });
107530
107617
  }
107531
- const backup = snapshotBeforeWrite(projectDir, absPath);
107532
- if (backup.error) console.warn(`Failed to create backup for ${filePath}: ${backup.error}`);
107533
- writeFileSync42(absPath, next, "utf-8");
107618
+ const { backupPath } = writeMutationResult(c3, projectDir, filePath, absPath, next);
107534
107619
  return c3.json({
107535
107620
  ok: true,
107536
107621
  changed: true,
107537
107622
  content: next,
107538
107623
  path: filePath,
107539
- backupPath: backupPathForResponse(projectDir, backup.backupPath)
107624
+ backupPath
107540
107625
  });
107541
107626
  }
107542
107627
  function rejectUnsafeMutationValues(c3, unsafeFields) {
@@ -107904,10 +107989,13 @@ async function applyGsapMutations(c3, res, mutations) {
107904
107989
  return c3.json({ error: "file changed during GSAP mutation", conflict: true }, 409);
107905
107990
  }
107906
107991
  if (changed) {
107907
- const backup = snapshotBeforeWrite(res.project.dir, res.absPath);
107908
- if (backup.error) console.warn(`Failed to create backup for ${res.filePath}: ${backup.error}`);
107909
- backupPath = backupPathForResponse(res.project.dir, backup.backupPath);
107910
- writeFileSync42(res.absPath, newHtml, "utf-8");
107992
+ backupPath = writeMutationResult(
107993
+ c3,
107994
+ res.project.dir,
107995
+ res.filePath,
107996
+ res.absPath,
107997
+ newHtml
107998
+ ).backupPath;
107911
107999
  }
107912
108000
  const responsePayload = {
107913
108001
  ok: true,
@@ -108864,10 +108952,12 @@ function registerFileRoutes(api, adapter2) {
108864
108952
  }
108865
108953
  const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);
108866
108954
  if (backup.error) return c3.json({ error: `backup failed: ${backup.error}` }, 500);
108867
- writeFileSync42(ctx.absPath, insertion.html, "utf-8");
108868
- const version2 = fileContentVersion(insertion.html);
108869
- const writeToken = createWriteToken(c3.req.header("X-Hyperframes-Write-Token"));
108870
- recordFileWriteReceipt(ctx.absPath, { path: ctx.filePath, version: version2, writeToken });
108955
+ const { version: version2, writeToken } = writeFileWithReceipt(
108956
+ c3,
108957
+ ctx.filePath,
108958
+ ctx.absPath,
108959
+ insertion.html
108960
+ );
108871
108961
  c3.header("ETag", version2);
108872
108962
  return c3.json({
108873
108963
  ok: true,
@@ -109065,10 +109155,13 @@ function registerFileRoutes(api, adapter2) {
109065
109155
  version: version22
109066
109156
  });
109067
109157
  }
109068
- const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);
109069
- if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);
109070
- writeFileSync42(ctx.absPath, result.html, "utf-8");
109071
- const version2 = fileContentVersion(result.html);
109158
+ const { version: version2, backupPath } = writeMutationResult(
109159
+ c3,
109160
+ ctx.project.dir,
109161
+ ctx.filePath,
109162
+ ctx.absPath,
109163
+ result.html
109164
+ );
109072
109165
  c3.header("ETag", version2);
109073
109166
  return c3.json({
109074
109167
  ok: true,
@@ -109077,7 +109170,7 @@ function registerFileRoutes(api, adapter2) {
109077
109170
  newId: result.newId,
109078
109171
  path: ctx.filePath,
109079
109172
  version: version2,
109080
- backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath)
109173
+ backupPath
109081
109174
  });
109082
109175
  });
109083
109176
  api.post("/projects/:id/file-mutations/patch-element/*", async (c3) => {
@@ -109112,16 +109205,20 @@ function registerFileRoutes(api, adapter2) {
109112
109205
  path: ctx.filePath
109113
109206
  });
109114
109207
  }
109115
- const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);
109116
- if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);
109117
- writeFileSync42(ctx.absPath, patched, "utf-8");
109208
+ const { backupPath } = writeMutationResult(
109209
+ c3,
109210
+ ctx.project.dir,
109211
+ ctx.filePath,
109212
+ ctx.absPath,
109213
+ patched
109214
+ );
109118
109215
  return c3.json({
109119
109216
  ok: true,
109120
109217
  changed: true,
109121
109218
  matched,
109122
109219
  content: patched,
109123
109220
  path: ctx.filePath,
109124
- backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath)
109221
+ backupPath
109125
109222
  });
109126
109223
  });
109127
109224
  api.post("/projects/:id/file-mutations/patch-element-batches", async (c3) => {
@@ -109133,7 +109230,7 @@ function registerFileRoutes(api, adapter2) {
109133
109230
  }
109134
109231
  const unsafeFields = findUnsafeElementPatchBatchValues(body.batches);
109135
109232
  if (unsafeFields.length > 0) return rejectUnsafeMutationValues(c3, unsafeFields);
109136
- const result = commitElementPatchBatches(project.dir, body.batches);
109233
+ const result = commitElementPatchBatchesWithReceipts(c3, project.dir, body.batches);
109137
109234
  if ("error" in result) {
109138
109235
  return elementPatchBatchCommitErrorResponse(c3, result.error, result.sourceFile);
109139
109236
  }
@@ -109151,7 +109248,7 @@ function registerFileRoutes(api, adapter2) {
109151
109248
  if (unsafeFields.length > 0) {
109152
109249
  return rejectUnsafeMutationValues(c3, unsafeFields);
109153
109250
  }
109154
- const result = commitElementPatchBatches(ctx.project.dir, [batch]);
109251
+ const result = commitElementPatchBatchesWithReceipts(c3, ctx.project.dir, [batch]);
109155
109252
  if ("error" in result) {
109156
109253
  return elementPatchBatchCommitErrorResponse(c3, result.error, result.sourceFile);
109157
109254
  }
@@ -109207,16 +109304,20 @@ function registerFileRoutes(api, adapter2) {
109207
109304
  result.error === "grouped elements must share a single parent" ? 422 : 400
109208
109305
  );
109209
109306
  }
109210
- const backup = snapshotBeforeWrite(ctx.project.dir, ctx.absPath);
109211
- if (backup.error) console.warn(`Failed to create backup for ${ctx.filePath}: ${backup.error}`);
109212
- writeFileSync42(ctx.absPath, result.html, "utf-8");
109307
+ const { backupPath } = writeMutationResult(
109308
+ c3,
109309
+ ctx.project.dir,
109310
+ ctx.filePath,
109311
+ ctx.absPath,
109312
+ result.html
109313
+ );
109213
109314
  return c3.json({
109214
109315
  ok: true,
109215
109316
  changed: true,
109216
109317
  groupId: result.groupId,
109217
109318
  content: result.html,
109218
109319
  path: ctx.filePath,
109219
- backupPath: backupPathForResponse(ctx.project.dir, backup.backupPath)
109320
+ backupPath
109220
109321
  });
109221
109322
  });
109222
109323
  api.post("/projects/:id/file-mutations/unwrap-elements/*", async (c3) => {
@@ -125332,7 +125433,7 @@ import {
125332
125433
  import { tmpdir as tmpdir8 } from "os";
125333
125434
  import { join as join60, dirname as dirname25, resolve as resolve33 } from "path";
125334
125435
  import { totalmem as totalmem2 } from "os";
125335
- import { randomUUID as randomUUID9 } from "crypto";
125436
+ import { randomUUID as randomUUID10 } from "crypto";
125336
125437
  import { fileURLToPath as fileURLToPath5 } from "url";
125337
125438
  function sampleDirectoryBytes(dir) {
125338
125439
  let total = 0;
@@ -125504,6 +125605,18 @@ function buildMissingFrameRetryBatches(ranges, maxWorkers, workDir, attempt, ran
125504
125605
  }
125505
125606
  return batches;
125506
125607
  }
125608
+ function resolveObservedCaptureMode(forceScreenshot, platform10 = process.platform) {
125609
+ return forceScreenshot || platform10 !== "linux" ? "screenshot" : "beginframe";
125610
+ }
125611
+ function createCaptureObservabilityUpdater(observability, platform10 = process.platform) {
125612
+ return (patch) => {
125613
+ Object.assign(observability, patch);
125614
+ observability.captureMode = resolveObservedCaptureMode(
125615
+ Boolean(observability.forceScreenshot),
125616
+ platform10
125617
+ );
125618
+ };
125619
+ }
125507
125620
  function getNextRetryWorkerCount(currentWorkers) {
125508
125621
  return Math.max(1, Math.floor(currentWorkers / 2));
125509
125622
  }
@@ -125691,7 +125804,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
125691
125804
  }
125692
125805
  function createRenderJob(config) {
125693
125806
  return {
125694
- id: randomUUID9(),
125807
+ id: randomUUID10(),
125695
125808
  config: {
125696
125809
  ...config,
125697
125810
  fps: toFps(config.fps),
@@ -125975,7 +126088,7 @@ async function executeRenderPipeline(input2) {
125975
126088
  const chunkedEncodeSize = cfg.chunkSizeFrames;
125976
126089
  const captureObservability = {
125977
126090
  forceScreenshot: Boolean(cfg.forceScreenshot),
125978
- captureMode: cfg.forceScreenshot ? "screenshot" : "beginframe",
126091
+ captureMode: resolveObservedCaptureMode(Boolean(cfg.forceScreenshot)),
125979
126092
  browserGpuMode: cfg.browserGpuMode,
125980
126093
  protocolTimeoutMs: cfg.protocolTimeout,
125981
126094
  pageNavigationTimeoutMs: cfg.pageNavigationTimeout,
@@ -125983,10 +126096,7 @@ async function executeRenderPipeline(input2) {
125983
126096
  };
125984
126097
  let extractionObservability;
125985
126098
  let compositionHash;
125986
- const updateCaptureObservability = (patch) => {
125987
- Object.assign(captureObservability, patch);
125988
- captureObservability.captureMode = captureObservability.forceScreenshot ? "screenshot" : "beginframe";
125989
- };
126099
+ const updateCaptureObservability = createCaptureObservabilityUpdater(captureObservability);
125990
126100
  const captureAttempts = [];
125991
126101
  const dedupPerfs = [];
125992
126102
  const layeredCaptureWarnings = [];
@@ -126109,7 +126219,11 @@ async function executeRenderPipeline(input2) {
126109
126219
  perfStages.compileOnlyMs = compileResult.compileOnlyMs;
126110
126220
  let captureForceScreenshot = compileResult.forceScreenshot;
126111
126221
  const deCompileGate = compileResult.deCompileGate;
126112
- let deClampReason;
126222
+ let deClampReason = cfg.useDrawElement ? void 0 : explainDrawElementDisabled({
126223
+ platform: process.platform,
126224
+ browserGpuMode: cfg.browserGpuMode,
126225
+ workerEncode: cfg.enableDrawElementWorkerEncode
126226
+ });
126113
126227
  let deWorkerInversion;
126114
126228
  let deParallelStreamForced = false;
126115
126229
  let captureParallelStreamForced = false;
@@ -126617,7 +126731,7 @@ async function executeRenderPipeline(input2) {
126617
126731
  });
126618
126732
  if (captureParallelStreamEligible) {
126619
126733
  captureParallelStreamForced = true;
126620
- const captureParallelStream = process.platform === "linux" && !captureForceScreenshot ? "beginframe" : "screenshot";
126734
+ const captureParallelStream = resolveObservedCaptureMode(captureForceScreenshot);
126621
126735
  log2.info(
126622
126736
  `[Render] Parallel ${captureParallelStream} capture will stream to the encoder (interleaved, ${workerCount} workers) instead of the disk path. Set HF_CAPTURE_PARALLEL_STREAM=false to disable.`
126623
126737
  );
@@ -132975,7 +133089,13 @@ function createStudioServer(options) {
132975
133089
  app.get("/api/events", (c3) => {
132976
133090
  return streamSSE4(c3, async (stream) => {
132977
133091
  const listener = (path2) => {
132978
- const receipt = consumeFileWriteReceipt(resolve38(projectDir, path2));
133092
+ const absPath = resolve38(projectDir, path2);
133093
+ let version2 = null;
133094
+ try {
133095
+ version2 = fileContentVersion(readFileSync40(absPath, "utf-8"));
133096
+ } catch {
133097
+ }
133098
+ const receipt = version2 ? consumeFileWriteReceipt(absPath, version2) : null;
132979
133099
  stream.writeSSE({ event: "file-change", data: JSON.stringify(receipt ?? { path: path2 }) }).catch(() => {
132980
133100
  });
132981
133101
  };
@@ -135260,24 +135380,583 @@ var init_add = __esm({
135260
135380
  }
135261
135381
  });
135262
135382
 
135383
+ // src/registry/localSearch.ts
135384
+ function tokenize(text2) {
135385
+ const words = text2.toLowerCase().match(/[a-z]+/g) ?? [];
135386
+ return words.filter((word) => word.length > 2 && !STOP.has(word));
135387
+ }
135388
+ function rankByWords(query2, items, textOf) {
135389
+ const want = new Set(tokenize(query2));
135390
+ if (want.size === 0) return items.map((item) => ({ item, score: 0 }));
135391
+ return items.map((item) => {
135392
+ const have = new Set(tokenize(textOf(item)));
135393
+ let shared = 0;
135394
+ for (const token of want) if (have.has(token)) shared += 1;
135395
+ return { item, score: shared / (Math.sqrt(have.size) || 1) };
135396
+ }).sort((a, b2) => b2.score - a.score || nameOf(b2.item).localeCompare(nameOf(a.item)));
135397
+ }
135398
+ function searchByWords(query2, items, textOf) {
135399
+ return rankByWords(query2, items, textOf).filter((scored) => scored.score > 0).map((scored) => scored.item);
135400
+ }
135401
+ function nameOf(item) {
135402
+ const named = item;
135403
+ return typeof named?.name === "string" ? named.name : "";
135404
+ }
135405
+ var STOP;
135406
+ var init_localSearch = __esm({
135407
+ "src/registry/localSearch.ts"() {
135408
+ "use strict";
135409
+ STOP = new Set(
135410
+ "the a an and or of to in on at is are be it its for with that this as by from into one two must not no all over under across while when where which who whom whose they them their we our you your he she his her but if then than so such can may might will would should each other another same both few more most some any every".split(" ")
135411
+ );
135412
+ }
135413
+ });
135414
+
135415
+ // src/registry/localModel.ts
135416
+ import { createHash as createHash18 } from "crypto";
135417
+ import { existsSync as existsSync71, mkdirSync as mkdirSync39, readFileSync as readFileSync44, unlinkSync as unlinkSync8 } from "fs";
135418
+ import { homedir as homedir15 } from "os";
135419
+ import { join as join81 } from "path";
135420
+ function localModelConsent() {
135421
+ return readConfig().localEmbeddingEnabled;
135422
+ }
135423
+ function recordLocalModelConsent(enabled) {
135424
+ writeConfig({ ...readConfig(), localEmbeddingEnabled: enabled });
135425
+ }
135426
+ function localModelPath() {
135427
+ return join81(MODELS_DIR3, `${LOCAL_MODEL_ID}.onnx`);
135428
+ }
135429
+ function localTokenizerPath() {
135430
+ return join81(MODELS_DIR3, `${LOCAL_MODEL_ID}.tokenizer.json`);
135431
+ }
135432
+ function modelFileIsValid(file) {
135433
+ const path2 = file.dest();
135434
+ if (!existsSync71(path2)) return false;
135435
+ try {
135436
+ return createHash18("sha256").update(readFileSync44(path2)).digest("hex") === file.sha256;
135437
+ } catch {
135438
+ return false;
135439
+ }
135440
+ }
135441
+ function isLocalModelReady() {
135442
+ return LOCAL_MODEL_ARTIFACTS.every(modelFileIsValid);
135443
+ }
135444
+ function localModelStatus() {
135445
+ const consent = localModelConsent();
135446
+ if (consent === false) return { status: "declined" };
135447
+ if (isLocalModelReady()) return { status: "ready" };
135448
+ if (consent === void 0) return { status: "not-asked" };
135449
+ return { status: "unavailable", reason: "model not downloaded yet" };
135450
+ }
135451
+ async function ensureLocalModel() {
135452
+ if (isLocalModelReady()) return true;
135453
+ try {
135454
+ mkdirSync39(MODELS_DIR3, { recursive: true });
135455
+ for (const file of LOCAL_MODEL_ARTIFACTS) {
135456
+ if (modelFileIsValid(file)) continue;
135457
+ const dest = file.dest();
135458
+ await downloadFile(file.url, dest, { maxBytes: file.bytes });
135459
+ if (!modelFileIsValid(file)) {
135460
+ unlinkSync8(dest);
135461
+ return false;
135462
+ }
135463
+ }
135464
+ return isLocalModelReady();
135465
+ } catch {
135466
+ return false;
135467
+ }
135468
+ }
135469
+ function nonInteractiveConsentMessage() {
135470
+ return `On-device search needs a one-time ${LOCAL_MODEL_SIZE_MB} MB download that stays on this machine. Nothing is sent anywhere. Ask the person you are working for, and pass --on-device --yes once they agree.`;
135471
+ }
135472
+ function downloadOfferMessage(matchCount) {
135473
+ const found = matchCount === void 0 ? "Use on-device meaning search." : matchCount === 0 ? "No matches from word search." : `Only ${matchCount} match${matchCount === 1 ? "" : "es"} from word search.`;
135474
+ return `${found} Download a ${LOCAL_MODEL_SIZE_MB} MB search model for better offline results? It stays on your machine and nothing is sent.`;
135475
+ }
135476
+ var LOCAL_MODEL_ID, LOCAL_MODEL_DIMENSIONS, LOCAL_MODEL_SIZE_MB, QUERY_INSTRUCTION, MODELS_DIR3, MODEL_REPO, LOCAL_MODEL_REVISION, LOCAL_MODEL_ARTIFACTS;
135477
+ var init_localModel = __esm({
135478
+ "src/registry/localModel.ts"() {
135479
+ "use strict";
135480
+ init_download();
135481
+ init_config();
135482
+ LOCAL_MODEL_ID = "bge-small-en-v1.5";
135483
+ LOCAL_MODEL_DIMENSIONS = 384;
135484
+ LOCAL_MODEL_SIZE_MB = 33;
135485
+ QUERY_INSTRUCTION = "Represent this sentence for searching relevant passages: ";
135486
+ MODELS_DIR3 = join81(homedir15(), ".hyperframes", "models");
135487
+ MODEL_REPO = "Xenova/bge-small-en-v1.5";
135488
+ LOCAL_MODEL_REVISION = "ea104dacec62c0de699686887e3f920caeb4f3e3";
135489
+ LOCAL_MODEL_ARTIFACTS = [
135490
+ {
135491
+ url: `https://huggingface.co/${MODEL_REPO}/resolve/${LOCAL_MODEL_REVISION}/onnx/model_quantized.onnx`,
135492
+ dest: () => localModelPath(),
135493
+ bytes: 34014426,
135494
+ sha256: "6c9c6101a956d62dfb5e7190c538226c0c5bb9cb27b651234b6df063ee7dbfe4"
135495
+ },
135496
+ {
135497
+ url: `https://huggingface.co/${MODEL_REPO}/resolve/${LOCAL_MODEL_REVISION}/tokenizer.json`,
135498
+ dest: () => localTokenizerPath(),
135499
+ bytes: 711396,
135500
+ sha256: "d241a60d5e8f04cc1b2b3e9ef7a4921b27bf526d9f6050ab90f9267a1f9e5c66"
135501
+ }
135502
+ ];
135503
+ }
135504
+ });
135505
+
135506
+ // src/registry/wordpiece.ts
135507
+ function configFromTokenizerJson(raw) {
135508
+ const parsed = JSON.parse(raw);
135509
+ const model = parsed.model;
135510
+ if (!model?.vocab) throw new Error("tokenizer.json has no WordPiece vocab");
135511
+ return {
135512
+ vocab: model.vocab,
135513
+ unkToken: model.unk_token ?? "[UNK]",
135514
+ continuingSubwordPrefix: model.continuing_subword_prefix ?? "##",
135515
+ maxInputCharsPerWord: model.max_input_chars_per_word ?? 100,
135516
+ clsToken: "[CLS]",
135517
+ sepToken: "[SEP]"
135518
+ };
135519
+ }
135520
+ function normalize(text2) {
135521
+ let out = "";
135522
+ for (const char of text2) {
135523
+ const code = char.codePointAt(0);
135524
+ if (code === 0 || code === 65533) continue;
135525
+ if (isControl(char, code)) continue;
135526
+ if (isWhitespace3(char, code)) {
135527
+ out += " ";
135528
+ continue;
135529
+ }
135530
+ out += isChinese(code) ? ` ${char} ` : char;
135531
+ }
135532
+ return out.toLowerCase().normalize("NFD").replace(new RegExp("\\p{Mn}", "gu"), "");
135533
+ }
135534
+ function preTokenize(normalized2) {
135535
+ const words = [];
135536
+ for (const chunk of normalized2.split(/\s+/)) {
135537
+ if (!chunk) continue;
135538
+ let current2 = "";
135539
+ for (const char of chunk) {
135540
+ if (isPunctuation(char)) {
135541
+ if (current2) words.push(current2);
135542
+ words.push(char);
135543
+ current2 = "";
135544
+ } else {
135545
+ current2 += char;
135546
+ }
135547
+ }
135548
+ if (current2) words.push(current2);
135549
+ }
135550
+ return words;
135551
+ }
135552
+ function wordPiece(word, config) {
135553
+ if ([...word].length > config.maxInputCharsPerWord) return [config.unkToken];
135554
+ const pieces = [];
135555
+ let start = 0;
135556
+ while (start < word.length) {
135557
+ let end = word.length;
135558
+ let match = null;
135559
+ while (start < end) {
135560
+ const candidate = start === 0 ? word.slice(start, end) : config.continuingSubwordPrefix + word.slice(start, end);
135561
+ if (candidate in config.vocab) {
135562
+ match = candidate;
135563
+ break;
135564
+ }
135565
+ end -= 1;
135566
+ }
135567
+ if (match === null) return [config.unkToken];
135568
+ pieces.push(match);
135569
+ start = end;
135570
+ }
135571
+ return pieces;
135572
+ }
135573
+ function encode2(text2, config) {
135574
+ const tokens = [config.clsToken];
135575
+ for (const word of preTokenize(normalize(text2))) tokens.push(...wordPiece(word, config));
135576
+ tokens.push(config.sepToken);
135577
+ const unk = config.vocab[config.unkToken];
135578
+ const ids = tokens.map((token) => config.vocab[token] ?? unk);
135579
+ return {
135580
+ ids,
135581
+ attentionMask: ids.map(() => 1),
135582
+ tokenTypeIds: ids.map(() => 0)
135583
+ };
135584
+ }
135585
+ function isControl(char, code) {
135586
+ if (char === " " || char === "\n" || char === "\r") return false;
135587
+ return code < 32 || code === 127 || new RegExp("\\p{Cc}|\\p{Cf}", "u").test(char);
135588
+ }
135589
+ function isWhitespace3(char, code) {
135590
+ return char === " " || char === " " || char === "\n" || char === "\r" || code === 11 || code === 12 || new RegExp("\\p{Zs}", "u").test(char);
135591
+ }
135592
+ function isPunctuation(char) {
135593
+ const code = char.codePointAt(0);
135594
+ const asciiSymbol = code >= 33 && code <= 47 || code >= 58 && code <= 64 || code >= 91 && code <= 96 || code >= 123 && code <= 126;
135595
+ return asciiSymbol || new RegExp("\\p{P}", "u").test(char);
135596
+ }
135597
+ function isChinese(code) {
135598
+ return code >= 19968 && code <= 40959 || code >= 13312 && code <= 19903 || code >= 131072 && code <= 173791 || code >= 173824 && code <= 177983 || code >= 177984 && code <= 178207 || code >= 178208 && code <= 183983 || code >= 63744 && code <= 64255 || code >= 194560 && code <= 195103;
135599
+ }
135600
+ var init_wordpiece = __esm({
135601
+ "src/registry/wordpiece.ts"() {
135602
+ "use strict";
135603
+ }
135604
+ });
135605
+
135606
+ // src/registry/localEmbedder.ts
135607
+ import { readFileSync as readFileSync45 } from "fs";
135608
+ async function localRuntimeAvailable() {
135609
+ try {
135610
+ await import("onnxruntime-node");
135611
+ return true;
135612
+ } catch {
135613
+ return false;
135614
+ }
135615
+ }
135616
+ async function loadLocalEmbedder() {
135617
+ const ort = await import("onnxruntime-node");
135618
+ const config = configFromTokenizerJson(readFileSync45(localTokenizerPath(), "utf-8"));
135619
+ const session = await ort.InferenceSession.create(localModelPath());
135620
+ return {
135621
+ async embed(texts, options) {
135622
+ if (texts.length === 0) return [];
135623
+ const prefix = options?.isQuery ? QUERY_INSTRUCTION : "";
135624
+ const encodings = texts.map((text2) => truncate(encode2(prefix + text2, config)));
135625
+ const width = Math.max(...encodings.map((e3) => e3.ids.length));
135626
+ const batch = encodings.length;
135627
+ const ids = new BigInt64Array(batch * width);
135628
+ const mask = new BigInt64Array(batch * width);
135629
+ const types5 = new BigInt64Array(batch * width);
135630
+ encodings.forEach((encoding, row) => {
135631
+ encoding.ids.forEach((id, column) => {
135632
+ const at4 = row * width + column;
135633
+ ids[at4] = BigInt(id);
135634
+ mask[at4] = 1n;
135635
+ types5[at4] = 0n;
135636
+ });
135637
+ });
135638
+ const dims = [batch, width];
135639
+ const output = await session.run({
135640
+ input_ids: new ort.Tensor("int64", ids, dims),
135641
+ attention_mask: new ort.Tensor("int64", mask, dims),
135642
+ token_type_ids: new ort.Tensor("int64", types5, dims)
135643
+ });
135644
+ const hidden = output["last_hidden_state"];
135645
+ if (!hidden) throw new Error("model returned no last_hidden_state");
135646
+ const data2 = hidden.data;
135647
+ const hiddenSize = hidden.dims[2];
135648
+ if (hiddenSize !== LOCAL_MODEL_DIMENSIONS) {
135649
+ throw new Error(
135650
+ `model produced ${hiddenSize} dimensions, expected ${LOCAL_MODEL_DIMENSIONS}`
135651
+ );
135652
+ }
135653
+ return encodings.map((_, row) => {
135654
+ const start = row * width * hiddenSize;
135655
+ return normalize2(Array.from(data2.subarray(start, start + hiddenSize)));
135656
+ });
135657
+ }
135658
+ };
135659
+ }
135660
+ function truncate(encoding) {
135661
+ if (encoding.ids.length <= MAX_TOKENS) return encoding;
135662
+ const ids = [
135663
+ ...encoding.ids.slice(0, MAX_TOKENS - 1),
135664
+ encoding.ids[encoding.ids.length - 1]
135665
+ ];
135666
+ return { ids, attentionMask: ids.map(() => 1), tokenTypeIds: ids.map(() => 0) };
135667
+ }
135668
+ function normalize2(vector) {
135669
+ const norm = Math.sqrt(vector.reduce((sum, value) => sum + value * value, 0));
135670
+ return norm === 0 ? vector : vector.map((value) => value / norm);
135671
+ }
135672
+ function cosine(a, b2) {
135673
+ let sum = 0;
135674
+ for (let i2 = 0; i2 < a.length; i2 += 1) sum += a[i2] * b2[i2];
135675
+ return sum;
135676
+ }
135677
+ var MAX_TOKENS;
135678
+ var init_localEmbedder = __esm({
135679
+ "src/registry/localEmbedder.ts"() {
135680
+ "use strict";
135681
+ init_localModel();
135682
+ init_wordpiece();
135683
+ MAX_TOKENS = 512;
135684
+ }
135685
+ });
135686
+
135687
+ // src/registry/localSemantic.ts
135688
+ import { existsSync as existsSync73, mkdirSync as mkdirSync40, readFileSync as readFileSync46, writeFileSync as writeFileSync28 } from "fs";
135689
+ import { homedir as homedir16 } from "os";
135690
+ import { join as join83 } from "path";
135691
+ function localVectorDirectory() {
135692
+ return process.env["HYPERFRAMES_CATALOG_ARTIFACT_DIR"] ?? join83(homedir16(), ".hyperframes", "catalog");
135693
+ }
135694
+ function vectorPairAgrees(fetched) {
135695
+ const meta = fetched.find(([file]) => file === "local-vectors.json")?.[1];
135696
+ const bin = fetched.find(([file]) => file === "local-vectors.bin")?.[1];
135697
+ if (!meta || !bin) return false;
135698
+ try {
135699
+ const parsed = JSON.parse(meta.toString("utf-8"));
135700
+ if (parsed.dimensions !== LOCAL_MODEL_DIMENSIONS) return false;
135701
+ return bin.byteLength === (parsed.names?.length ?? -1) * LOCAL_MODEL_DIMENSIONS * 4;
135702
+ } catch {
135703
+ return false;
135704
+ }
135705
+ }
135706
+ function vectorRevisionAgrees(fetched, expectedRevision) {
135707
+ if (expectedRevision === void 0) return true;
135708
+ const meta = fetched.find(([file]) => file === "local-vectors.json")?.[1];
135709
+ if (!meta) return false;
135710
+ try {
135711
+ const parsed = JSON.parse(meta.toString("utf-8"));
135712
+ return parsed.revision === expectedRevision;
135713
+ } catch {
135714
+ return false;
135715
+ }
135716
+ }
135717
+ async function fetchLocalVectors(registryBaseUrl, options = {}) {
135718
+ const directory = options.directory ?? localVectorDirectory();
135719
+ const base2 = registryBaseUrl.replace(/\/+$/, "");
135720
+ try {
135721
+ mkdirSync40(directory, { recursive: true, mode: 448 });
135722
+ const fetched = [];
135723
+ for (const file of ["local-vectors.json", "local-vectors.bin"]) {
135724
+ const response = await fetch(`${base2}/catalog-artifact/${file}`, {
135725
+ signal: AbortSignal.timeout(CATALOG_ARTIFACT_TIMEOUT_MS)
135726
+ });
135727
+ if (!response.ok) return false;
135728
+ fetched.push([file, Buffer.from(await response.arrayBuffer())]);
135729
+ }
135730
+ if (!vectorPairAgrees(fetched) || !vectorRevisionAgrees(fetched, options.expectedRevision)) {
135731
+ return false;
135732
+ }
135733
+ for (const [file, bytes] of fetched) {
135734
+ writeFileSync28(join83(directory, file), bytes, { mode: 384 });
135735
+ }
135736
+ return hasLocalVectors(directory);
135737
+ } catch {
135738
+ return false;
135739
+ }
135740
+ }
135741
+ function hasLocalVectors(directory = localVectorDirectory()) {
135742
+ return existsSync73(join83(directory, "local-vectors.bin")) && existsSync73(join83(directory, "local-vectors.json"));
135743
+ }
135744
+ function loadLocalVectors(directory = localVectorDirectory()) {
135745
+ const meta = JSON.parse(
135746
+ readFileSync46(join83(directory, "local-vectors.json"), "utf-8")
135747
+ );
135748
+ const buffer = readFileSync46(join83(directory, "local-vectors.bin"));
135749
+ const vectors = new Float32Array(buffer.buffer, buffer.byteOffset, buffer.byteLength / 4);
135750
+ const expected = meta.names.length * meta.dimensions;
135751
+ if (vectors.length !== expected) {
135752
+ throw new Error(`local vectors hold ${vectors.length} floats, expected ${expected}`);
135753
+ }
135754
+ if (meta.dimensions !== LOCAL_MODEL_DIMENSIONS) {
135755
+ throw new Error(
135756
+ `local vectors are ${meta.dimensions}-dimension, model produces ${LOCAL_MODEL_DIMENSIONS}`
135757
+ );
135758
+ }
135759
+ return { names: meta.names, dimensions: meta.dimensions, vectors };
135760
+ }
135761
+ function localVectorNames(directory = localVectorDirectory()) {
135762
+ if (!hasLocalVectors(directory)) return [];
135763
+ try {
135764
+ const meta = JSON.parse(readFileSync46(join83(directory, "local-vectors.json"), "utf-8"));
135765
+ return meta.names ?? [];
135766
+ } catch {
135767
+ return [];
135768
+ }
135769
+ }
135770
+ function cachedLocalVectorRevision(directory = localVectorDirectory()) {
135771
+ if (!hasLocalVectors(directory)) return void 0;
135772
+ try {
135773
+ const meta = JSON.parse(readFileSync46(join83(directory, "local-vectors.json"), "utf-8"));
135774
+ return typeof meta.revision === "string" ? meta.revision : void 0;
135775
+ } catch {
135776
+ return void 0;
135777
+ }
135778
+ }
135779
+ async function localSemanticRanking(query2, directory = localVectorDirectory()) {
135780
+ if (!isLocalModelReady() || !hasLocalVectors(directory)) return null;
135781
+ const set = loadLocalVectors(directory);
135782
+ const embedder = await loadLocalEmbedder();
135783
+ const [queryVector] = await embedder.embed([query2], { isQuery: true });
135784
+ if (!queryVector) return null;
135785
+ const scored = set.names.map((name, row) => {
135786
+ const start = row * set.dimensions;
135787
+ return {
135788
+ name,
135789
+ score: cosine(queryVector, Array.from(set.vectors.subarray(start, start + set.dimensions)))
135790
+ };
135791
+ });
135792
+ scored.sort((a, b2) => b2.score - a.score || b2.name.localeCompare(a.name));
135793
+ return scored;
135794
+ }
135795
+ var CATALOG_ARTIFACT_TIMEOUT_MS;
135796
+ var init_localSemantic = __esm({
135797
+ "src/registry/localSemantic.ts"() {
135798
+ "use strict";
135799
+ init_localEmbedder();
135800
+ init_localModel();
135801
+ CATALOG_ARTIFACT_TIMEOUT_MS = 3e4;
135802
+ }
135803
+ });
135804
+
135263
135805
  // src/commands/catalog.ts
135264
135806
  var catalog_exports = {};
135265
135807
  __export(catalog_exports, {
135808
+ countUnindexed: () => countUnindexed,
135266
135809
  default: () => catalog_default,
135267
- examples: () => examples5
135810
+ examples: () => examples5,
135811
+ pickByName: () => pickByName
135268
135812
  });
135269
135813
  import { resolve as resolve43 } from "path";
135814
+ async function prepareOnDeviceTier(opts) {
135815
+ const warnings = [];
135816
+ const warn = (message) => {
135817
+ warnings.push(message);
135818
+ console.error(message);
135819
+ };
135820
+ const status = opts.status;
135821
+ if (!opts.assumedYes && status.status === "declined") {
135822
+ warn(
135823
+ "on-device search skipped: the model download was previously declined. Re-run with --yes to consent."
135824
+ );
135825
+ return warnings;
135826
+ }
135827
+ if (!opts.assumedYes && status.status === "not-asked" && !opts.canPrompt) {
135828
+ warn(nonInteractiveConsentMessage());
135829
+ return warnings;
135830
+ }
135831
+ if (!opts.assumedYes && status.status === "not-asked") {
135832
+ const answer = await ue({
135833
+ message: downloadOfferMessage(),
135834
+ initialValue: true
135835
+ });
135836
+ if (q(answer) || answer !== true) {
135837
+ recordLocalModelConsent(false);
135838
+ warn("on-device search skipped: the download was declined.");
135839
+ return warnings;
135840
+ }
135841
+ }
135842
+ if (!await localRuntimeAvailable()) {
135843
+ warn(
135844
+ "on-device search needs the native ONNX runtime, which a single-file build cannot load. Install the CLI normally (npm i -g hyperframes) to use this tier."
135845
+ );
135846
+ return warnings;
135847
+ }
135848
+ if (status.status === "declined" || status.status === "not-asked") {
135849
+ recordLocalModelConsent(true);
135850
+ }
135851
+ const model = await ensureLocalModel();
135852
+ const revisionStale = opts.artifactRevision !== void 0 && cachedLocalVectorRevision() !== opts.artifactRevision;
135853
+ if (!hasLocalVectors() || revisionStale || countUnindexed(opts.registryNames, localVectorNames()) > 0) {
135854
+ await fetchLocalVectors(opts.registry, { expectedRevision: opts.artifactRevision });
135855
+ }
135856
+ const vectors = hasLocalVectors();
135857
+ if (!model || !vectors) {
135858
+ warn(
135859
+ `on-device search unavailable: ${!model ? "model" : "catalog vectors"} could not be fetched`
135860
+ );
135861
+ } else if (opts.artifactRevision !== void 0 && cachedLocalVectorRevision() !== opts.artifactRevision) {
135862
+ warn("on-device search is using the previous catalog vectors because the update failed");
135863
+ }
135864
+ return warnings;
135865
+ }
135866
+ function pickByName(items, names, registryNames) {
135867
+ const byName = new Map(items.map((item) => [item.name, item]));
135868
+ const ranked = names.map((name) => byName.get(name)).filter((item) => item !== void 0);
135869
+ return { ranked, missing: names.filter((name) => !registryNames.has(name)).length };
135870
+ }
135871
+ function countUnindexed(registryNames, indexedNames) {
135872
+ const indexed = new Set(indexedNames);
135873
+ let count = 0;
135874
+ for (const name of registryNames) {
135875
+ if (!indexed.has(name)) count += 1;
135876
+ }
135877
+ return count;
135878
+ }
135879
+ async function applySearch(items, query2, registryNames, status) {
135880
+ const warnings = [];
135881
+ if (status.status === "ready") {
135882
+ try {
135883
+ const ranking = await localSemanticRanking(query2);
135884
+ if (ranking) {
135885
+ const { ranked, missing } = pickByName(
135886
+ items,
135887
+ ranking.map((entry) => entry.name),
135888
+ registryNames
135889
+ );
135890
+ const best = ranked[0];
135891
+ if (best) {
135892
+ const scoreByName = new Map(ranking.map((entry) => [entry.name, entry.score]));
135893
+ return {
135894
+ items: ranked.slice(0, 25),
135895
+ localMode: "local-model",
135896
+ warnings,
135897
+ missing,
135898
+ unindexed: countUnindexed(registryNames, localVectorNames()),
135899
+ topScore: scoreByName.get(best.name) ?? null
135900
+ };
135901
+ }
135902
+ }
135903
+ } catch (error) {
135904
+ const warning = `on-device search did not run: ${error instanceof Error ? error.message : "unknown error"}`;
135905
+ warnings.push(warning);
135906
+ console.error(warning);
135907
+ }
135908
+ }
135909
+ const words = searchByWords(
135910
+ query2,
135911
+ items,
135912
+ (item) => `${item.name} ${item.title} ${item.description} ${(item.tags ?? []).join(" ")}`
135913
+ );
135914
+ return { items: words, localMode: "words", warnings, missing: 0, unindexed: 0, topScore: null };
135915
+ }
135916
+ function tierToken(searched) {
135917
+ return searched?.localMode === "local-model" ? "on-device" : "words";
135918
+ }
135919
+ function tierDetail(searched) {
135920
+ return searched?.localMode === "local-model" ? "on-device meaning search" : "local word match";
135921
+ }
135922
+ function reportLocalModelOption(json) {
135923
+ if (!json && process.stdout.isTTY) return;
135924
+ if (localModelStatus().status !== "not-asked") return;
135925
+ console.error(nonInteractiveConsentMessage());
135926
+ }
135927
+ async function offerLocalModel(matchCount, json, registryBaseUrl, artifactRevision) {
135928
+ if (json || !process.stdout.isTTY) return;
135929
+ if (localModelStatus().status !== "not-asked") return;
135930
+ const answer = await ue({
135931
+ message: downloadOfferMessage(matchCount),
135932
+ initialValue: true
135933
+ });
135934
+ if (q(answer)) return;
135935
+ recordLocalModelConsent(answer === true);
135936
+ if (answer !== true) return;
135937
+ const vectors = hasLocalVectors() || await fetchLocalVectors(registryBaseUrl, { expectedRevision: artifactRevision });
135938
+ console.log(
135939
+ c.dim(
135940
+ vectors ? " Run the search again to download the model and rank by meaning." : " Could not fetch the catalog vectors; offline ranking stays off until they are available."
135941
+ )
135942
+ );
135943
+ }
135270
135944
  var examples5, catalog_default;
135271
135945
  var init_catalog = __esm({
135272
135946
  "src/commands/catalog.ts"() {
135273
135947
  "use strict";
135274
- init_commandResult();
135275
135948
  init_dist();
135276
135949
  init_dist8();
135277
135950
  init_colors();
135278
135951
  init_resolver();
135952
+ init_remote();
135279
135953
  init_projectConfig();
135954
+ init_commandResult();
135280
135955
  init_add();
135956
+ init_localSearch();
135957
+ init_localModel();
135958
+ init_localEmbedder();
135959
+ init_localSemantic();
135281
135960
  examples5 = [
135282
135961
  ["List all blocks and components", "hyperframes catalog"],
135283
135962
  ["List blocks only", "hyperframes catalog --type block"],
@@ -135306,8 +135985,26 @@ var init_catalog = __esm({
135306
135985
  "human-friendly": {
135307
135986
  type: "boolean",
135308
135987
  description: "Interactive picker \u2014 select an item to install"
135988
+ },
135989
+ query: {
135990
+ type: "string",
135991
+ description: "Search by meaning when the on-device model is on, otherwise by name, title, description and tags"
135992
+ },
135993
+ yes: {
135994
+ type: "boolean",
135995
+ alias: "y",
135996
+ description: "Assume yes for prompts this run, including the on-device model download"
135997
+ },
135998
+ "on-device": {
135999
+ type: "boolean",
136000
+ // Consent for the model download is otherwise only reachable through a
136001
+ // prompt that fires on a TTY, which leaves every agent and CI run unable
136002
+ // to opt in at all.
136003
+ description: "Use on-device meaning search; pass --yes to approve a first non-interactive download"
135309
136004
  }
135310
136005
  },
136006
+ // one flag-parsing entry point feeding three output paths (json, interactive, table); splitting those is its own change
136007
+ // fallow-ignore-next-line complexity
135311
136008
  async run({ args }) {
135312
136009
  const json = args.json === true;
135313
136010
  const interactive = args["human-friendly"] === true;
@@ -135318,12 +136015,14 @@ var init_catalog = __esm({
135318
136015
  else if (args.type === "component") typeFilter = "hyperframes:component";
135319
136016
  else if (args.type) {
135320
136017
  console.error(`Invalid --type: "${args.type}". Use "block" or "component".`);
135321
- failCommand();
135322
- }
135323
- const entries2 = await listRegistryItems(typeFilter ? { type: typeFilter } : void 0, {
135324
- baseUrl: config.registry
135325
- });
135326
- const filtered = entries2.filter((e3) => e3.type !== "hyperframes:example");
136018
+ finishCommand(1);
136019
+ }
136020
+ const manifest = await fetchRegistryManifest(config.registry);
136021
+ const entries2 = manifest?.items ?? [];
136022
+ const artifactRevision = manifest?.catalogArtifact?.revision;
136023
+ const catalog = entries2.filter((e3) => e3.type !== "hyperframes:example");
136024
+ const registryNames = new Set(catalog.map((e3) => e3.name));
136025
+ const filtered = typeFilter ? catalog.filter((e3) => e3.type === typeFilter) : catalog;
135327
136026
  if (filtered.length === 0) {
135328
136027
  if (json) console.log("[]");
135329
136028
  else console.log("No items found in registry.");
@@ -135331,10 +136030,56 @@ var init_catalog = __esm({
135331
136030
  }
135332
136031
  const items = await loadAllItems(filtered, { baseUrl: config.registry });
135333
136032
  const tagFilter = args.tag?.toLowerCase();
135334
- const matching = tagFilter ? items.filter((item) => item.tags?.some((t2) => t2.toLowerCase() === tagFilter)) : items;
136033
+ const tagged = tagFilter ? items.filter((item) => item.tags?.some((t2) => t2.toLowerCase() === tagFilter)) : items;
136034
+ const query2 = typeof args.query === "string" ? args.query.trim() : "";
136035
+ const searchContext = query2 ? { status: localModelStatus() } : null;
136036
+ const routineUpdate = searchContext?.status.status === "unavailable" || searchContext?.status.status === "ready" && artifactRevision !== void 0 && cachedLocalVectorRevision() !== artifactRevision;
136037
+ const shouldPrepare = args["on-device"] === true || routineUpdate;
136038
+ let warnings = [];
136039
+ let effectiveStatus = searchContext?.status;
136040
+ if (searchContext && shouldPrepare) {
136041
+ warnings = await prepareOnDeviceTier({
136042
+ assumedYes: args.yes === true,
136043
+ artifactRevision,
136044
+ canPrompt: process.stdout.isTTY === true && !json,
136045
+ registry: config.registry,
136046
+ registryNames,
136047
+ status: searchContext.status
136048
+ });
136049
+ effectiveStatus = localModelStatus();
136050
+ }
136051
+ const searched = effectiveStatus ? await applySearch(tagged, query2, registryNames, effectiveStatus) : null;
136052
+ if (searched) warnings.push(...searched.warnings);
136053
+ const matching = searched ? searched.items : tagged;
135335
136054
  if (matching.length === 0) {
135336
- if (json) console.log("[]");
135337
- else console.log(`No items match tag "${args.tag}".`);
136055
+ if (json && query2) {
136056
+ console.log(
136057
+ JSON.stringify(
136058
+ {
136059
+ query: query2,
136060
+ tier: tierToken(searched),
136061
+ tier_detail: tierDetail(searched),
136062
+ dropped: searched?.missing ?? 0,
136063
+ unindexed: searched?.unindexed ?? 0,
136064
+ ...searched?.topScore != null ? { top_score: searched.topScore } : {},
136065
+ shown: 0,
136066
+ total: tagged.length,
136067
+ ...warnings.length ? { warnings } : {},
136068
+ results: []
136069
+ },
136070
+ null,
136071
+ 2
136072
+ )
136073
+ );
136074
+ } else if (json) console.log("[]");
136075
+ else {
136076
+ const criteria = [
136077
+ query2 ? `query "${query2}"` : null,
136078
+ args.tag ? `tag "${args.tag}"` : null
136079
+ ].filter(Boolean);
136080
+ console.log(`No items match ${criteria.join(" and ")}.`);
136081
+ }
136082
+ if (query2) await offerLocalModel(0, json, config.registry, artifactRevision);
135338
136083
  return;
135339
136084
  }
135340
136085
  if (json) {
@@ -135347,9 +136092,49 @@ var init_catalog = __esm({
135347
136092
  ..."dimensions" in item && item.dimensions ? { dimensions: item.dimensions } : {},
135348
136093
  ..."duration" in item && item.duration ? { duration: item.duration } : {}
135349
136094
  }));
135350
- console.log(JSON.stringify(output, null, 2));
136095
+ if (!query2) {
136096
+ console.log(JSON.stringify(output, null, 2));
136097
+ return;
136098
+ }
136099
+ console.log(
136100
+ JSON.stringify(
136101
+ {
136102
+ query: query2,
136103
+ tier: tierToken(searched),
136104
+ tier_detail: tierDetail(searched),
136105
+ dropped: searched?.missing ?? 0,
136106
+ unindexed: searched?.unindexed ?? 0,
136107
+ ...searched?.topScore != null ? { top_score: searched.topScore } : {},
136108
+ shown: output.length,
136109
+ total: tagged.length,
136110
+ ...warnings.length ? { warnings } : {},
136111
+ results: output
136112
+ },
136113
+ null,
136114
+ 2
136115
+ )
136116
+ );
135351
136117
  return;
135352
136118
  }
136119
+ if (searched) {
136120
+ const how = tierDetail(searched);
136121
+ const unshowable = searched.missing > 0 ? ` \xB7 ${searched.missing} ranked ${searched.missing === 1 ? "move" : "moves"} not in this registry` : "";
136122
+ console.log(c.dim(` ${matching.length} of ${tagged.length} moves \xB7 ${how}${unshowable}`));
136123
+ if (searched.unindexed > 0) {
136124
+ const remedy = args["on-device"] === true ? "The published index is behind this registry." : "Re-run with --on-device to refresh it.";
136125
+ console.log(
136126
+ c.warn(
136127
+ ` ${searched.unindexed} of ${registryNames.size} moves are missing from the on-device index, so meaning search cannot return them. ${remedy}`
136128
+ )
136129
+ );
136130
+ }
136131
+ if (searched.localMode === "words") {
136132
+ if (warnings.length === 0) {
136133
+ reportLocalModelOption(json);
136134
+ await offerLocalModel(matching.length, json, config.registry, artifactRevision);
136135
+ }
136136
+ }
136137
+ }
135353
136138
  if (interactive) {
135354
136139
  const options = matching.map((item) => ({
135355
136140
  value: item.name,
@@ -135416,7 +136201,7 @@ var init_mediaProxyPreview = __esm({
135416
136201
  });
135417
136202
 
135418
136203
  // src/utils/compositionServer.ts
135419
- import { createReadStream as createReadStream6, existsSync as existsSync71, statSync as statSync26 } from "fs";
136204
+ import { createReadStream as createReadStream6, existsSync as existsSync74, statSync as statSync26 } from "fs";
135420
136205
  import { resolve as resolve44, dirname as dirname35 } from "path";
135421
136206
  import { Readable as Readable3 } from "stream";
135422
136207
  import { fileURLToPath as fileURLToPath10 } from "url";
@@ -135431,7 +136216,7 @@ function resolveRuntimePath2() {
135431
136216
  // Monorepo dev: src/<dir>/ → src/ → cli/ → packages/ then into core/dist/
135432
136217
  resolve44(d2, "..", "..", "..", "core", "dist", "hyperframe.runtime.iife.js")
135433
136218
  ];
135434
- return candidates.find((p2) => existsSync71(p2)) ?? null;
136219
+ return candidates.find((p2) => existsSync74(p2)) ?? null;
135435
136220
  }
135436
136221
  function resolvePlayerPath() {
135437
136222
  const d2 = helperDir();
@@ -135440,7 +136225,7 @@ function resolvePlayerPath() {
135440
136225
  resolve44(d2, "hyperframes-player.global.js"),
135441
136226
  resolve44(d2, "..", "hyperframes-player.global.js")
135442
136227
  ];
135443
- return candidates.find((p2) => existsSync71(p2)) ?? null;
136228
+ return candidates.find((p2) => existsSync74(p2)) ?? null;
135444
136229
  }
135445
136230
  function resolveSlideshowPath() {
135446
136231
  const d2 = helperDir();
@@ -135449,7 +136234,7 @@ function resolveSlideshowPath() {
135449
136234
  resolve44(d2, "hyperframes-slideshow.global.js"),
135450
136235
  resolve44(d2, "..", "hyperframes-slideshow.global.js")
135451
136236
  ];
135452
- return candidates.find((p2) => existsSync71(p2)) ?? null;
136237
+ return candidates.find((p2) => existsSync74(p2)) ?? null;
135453
136238
  }
135454
136239
  function injectRuntime(html) {
135455
136240
  return injectTagsAtHeadStart(html, `<script src="/runtime.js"></script>`);
@@ -135577,7 +136362,7 @@ __export(play_exports, {
135577
136362
  examples: () => examples6,
135578
136363
  registerCompositionRoute: () => registerCompositionRoute
135579
136364
  });
135580
- import { existsSync as existsSync73, readFileSync as readFileSync44 } from "fs";
136365
+ import { existsSync as existsSync75, readFileSync as readFileSync47 } from "fs";
135581
136366
  import { resolve as resolve45 } from "path";
135582
136367
  async function registerCompositionRoute(app, project, autoProxy) {
135583
136368
  const { isSafePath: isSafePath2 } = await Promise.resolve().then(() => (init_studio_api(), studio_api_exports));
@@ -135585,9 +136370,9 @@ async function registerCompositionRoute(app, project, autoProxy) {
135585
136370
  const reqPath = ctx.req.path.replace("/composition/", "");
135586
136371
  const filePath = resolve45(project.dir, reqPath);
135587
136372
  if (!isSafePath2(project.dir, filePath)) return ctx.text("Forbidden", 403);
135588
- if (!existsSync73(filePath)) return ctx.text("Not found", 404);
136373
+ if (!existsSync75(filePath)) return ctx.text("Not found", 404);
135589
136374
  if (filePath.endsWith(".html")) {
135590
- let html = injectRuntime(readFileSync44(filePath, "utf-8"));
136375
+ let html = injectRuntime(readFileSync47(filePath, "utf-8"));
135591
136376
  if (autoProxy) {
135592
136377
  html = await injectMediaCodecMapIntoHtml(html, project.dir, [{ html, compSrcPath: reqPath }]);
135593
136378
  }
@@ -135768,13 +136553,13 @@ var init_play = __esm({
135768
136553
  const { createAdaptorServer } = await import("@hono/node-server");
135769
136554
  const app = new Hono6();
135770
136555
  app.get("/player.js", (ctx) => {
135771
- return ctx.body(readFileSync44(playerPath, "utf-8"), 200, {
136556
+ return ctx.body(readFileSync47(playerPath, "utf-8"), 200, {
135772
136557
  "Content-Type": "application/javascript",
135773
136558
  "Cache-Control": "no-cache"
135774
136559
  });
135775
136560
  });
135776
136561
  app.get("/runtime.js", (ctx) => {
135777
- return ctx.body(readFileSync44(runtimePath, "utf-8"), 200, {
136562
+ return ctx.body(readFileSync47(runtimePath, "utf-8"), 200, {
135778
136563
  "Content-Type": "application/javascript",
135779
136564
  "Cache-Control": "no-cache"
135780
136565
  });
@@ -135820,7 +136605,7 @@ __export(present_exports, {
135820
136605
  default: () => present_default,
135821
136606
  examples: () => examples7
135822
136607
  });
135823
- import { existsSync as existsSync74, readFileSync as readFileSync45 } from "fs";
136608
+ import { existsSync as existsSync76, readFileSync as readFileSync48 } from "fs";
135824
136609
  import { resolve as resolve46 } from "path";
135825
136610
  function buildPresentPage(projectName, islandJson) {
135826
136611
  return `<!doctype html>
@@ -136012,7 +136797,7 @@ var init_present = __esm({
136012
136797
  setCommandExitCode(1);
136013
136798
  return;
136014
136799
  }
136015
- const indexHtml = readFileSync45(project.indexPath, "utf-8");
136800
+ const indexHtml = readFileSync48(project.indexPath, "utf-8");
136016
136801
  const { slideshowIslandRegex: slideshowIslandRegex2 } = await Promise.resolve().then(() => (init_slideshow2(), slideshow_exports));
136017
136802
  const islandMatch = slideshowIslandRegex2("i").exec(indexHtml);
136018
136803
  if (!islandMatch?.[1]) {
@@ -136038,14 +136823,14 @@ var init_present = __esm({
136038
136823
  const app = new Hono6();
136039
136824
  app.get(
136040
136825
  "/player.js",
136041
- (ctx) => ctx.body(readFileSync45(playerPath, "utf-8"), 200, {
136826
+ (ctx) => ctx.body(readFileSync48(playerPath, "utf-8"), 200, {
136042
136827
  "Content-Type": "application/javascript",
136043
136828
  "Cache-Control": "no-cache"
136044
136829
  })
136045
136830
  );
136046
136831
  app.get(
136047
136832
  "/slideshow.js",
136048
- (ctx) => ctx.body(readFileSync45(slideshowPath, "utf-8"), 200, {
136833
+ (ctx) => ctx.body(readFileSync48(slideshowPath, "utf-8"), 200, {
136049
136834
  "Content-Type": "application/javascript",
136050
136835
  "Cache-Control": "no-cache"
136051
136836
  })
@@ -136054,9 +136839,9 @@ var init_present = __esm({
136054
136839
  const reqPath = ctx.req.path.replace("/composition/", "");
136055
136840
  const filePath = resolve46(project.dir, reqPath);
136056
136841
  if (!isSafePath2(project.dir, filePath)) return ctx.text("Forbidden", 403);
136057
- if (!existsSync74(filePath)) return ctx.text("Not found", 404);
136058
- if (filePath.endsWith(".html")) return ctx.html(readFileSync45(filePath, "utf-8"));
136059
- return ctx.body(readFileSync45(filePath), 200, { "Content-Type": assetContentType(filePath) });
136842
+ if (!existsSync76(filePath)) return ctx.text("Not found", 404);
136843
+ if (filePath.endsWith(".html")) return ctx.html(readFileSync48(filePath, "utf-8"));
136844
+ return ctx.body(readFileSync48(filePath), 200, { "Content-Type": assetContentType(filePath) });
136060
136845
  });
136061
136846
  app.get("/", (ctx) => ctx.html(buildPresentPage(project.name, islandJson)));
136062
136847
  ge(c.bold("hyperframes present"));
@@ -136300,15 +137085,15 @@ var init_client2 = __esm({
136300
137085
  });
136301
137086
 
136302
137087
  // src/auth/paths.ts
136303
- import { homedir as homedir15 } from "os";
136304
- import { join as join81 } from "path";
137088
+ import { homedir as homedir17 } from "os";
137089
+ import { join as join84 } from "path";
136305
137090
  function configDir() {
136306
137091
  const override = process.env["HEYGEN_CONFIG_DIR"];
136307
137092
  if (override && override.length > 0) return override;
136308
- return join81(homedir15(), ".heygen");
137093
+ return join84(homedir17(), ".heygen");
136309
137094
  }
136310
137095
  function credentialPath() {
136311
- return join81(configDir(), CREDENTIAL_FILENAME);
137096
+ return join84(configDir(), CREDENTIAL_FILENAME);
136312
137097
  }
136313
137098
  var CREDENTIAL_FILENAME;
136314
137099
  var init_paths2 = __esm({
@@ -136672,10 +137457,10 @@ var init_resolver2 = __esm({
136672
137457
  });
136673
137458
 
136674
137459
  // src/auth/pkce.ts
136675
- import { createHash as createHash18, randomBytes as randomBytes3 } from "crypto";
137460
+ import { createHash as createHash19, randomBytes as randomBytes3 } from "crypto";
136676
137461
  function generatePkcePair() {
136677
137462
  const verifier = base64UrlEncode(randomBytes3(VERIFIER_BYTES));
136678
- const challenge = base64UrlEncode(createHash18("sha256").update(verifier).digest());
137463
+ const challenge = base64UrlEncode(createHash19("sha256").update(verifier).digest());
136679
137464
  return { verifier, challenge, method: "S256" };
136680
137465
  }
136681
137466
  function generateState() {
@@ -137393,14 +138178,14 @@ var init_auth = __esm({
137393
138178
  });
137394
138179
 
137395
138180
  // src/utils/projectLink.ts
137396
- import { randomUUID as randomUUID10 } from "crypto";
137397
- import { existsSync as existsSync75, mkdirSync as mkdirSync39, readFileSync as readFileSync46, writeFileSync as writeFileSync28 } from "fs";
137398
- import { homedir as homedir16 } from "os";
137399
- import { join as join83, resolve as resolve47 } from "path";
138181
+ import { randomUUID as randomUUID11 } from "crypto";
138182
+ import { existsSync as existsSync77, mkdirSync as mkdirSync41, readFileSync as readFileSync49, writeFileSync as writeFileSync29 } from "fs";
138183
+ import { homedir as homedir18 } from "os";
138184
+ import { join as join85, resolve as resolve47 } from "path";
137400
138185
  function readJsonRecord(path2) {
137401
138186
  try {
137402
- if (!existsSync75(path2)) return null;
137403
- const parsed = JSON.parse(readFileSync46(path2, "utf-8"));
138187
+ if (!existsSync77(path2)) return null;
138188
+ const parsed = JSON.parse(readFileSync49(path2, "utf-8"));
137404
138189
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) return null;
137405
138190
  return parsed;
137406
138191
  } catch {
@@ -137425,8 +138210,8 @@ function readProjectLinks() {
137425
138210
  }
137426
138211
  function writeProjectLinks(links) {
137427
138212
  try {
137428
- mkdirSync39(CONFIG_DIR2, { recursive: true, mode: 448 });
137429
- writeFileSync28(PROJECTS_FILE, `${JSON.stringify(links, null, 2)}
138213
+ mkdirSync41(CONFIG_DIR2, { recursive: true, mode: 448 });
138214
+ writeFileSync29(PROJECTS_FILE, `${JSON.stringify(links, null, 2)}
137430
138215
  `, { mode: 384 });
137431
138216
  } catch {
137432
138217
  }
@@ -137444,13 +138229,13 @@ function ensureProjectId(absDir) {
137444
138229
  const path2 = resolve47(absDir);
137445
138230
  const existing = links[path2];
137446
138231
  if (existing) return existing.projectId;
137447
- const projectId = randomUUID10();
138232
+ const projectId = randomUUID11();
137448
138233
  links[path2] = { projectId, url: "" };
137449
138234
  writeProjectLinks(links);
137450
138235
  return projectId;
137451
138236
  }
137452
138237
  function teamProjectPath(projectDir) {
137453
- return join83(resolve47(projectDir), TEAM_PROJECT_DIR, TEAM_PROJECT_FILE);
138238
+ return join85(resolve47(projectDir), TEAM_PROJECT_DIR, TEAM_PROJECT_FILE);
137454
138239
  }
137455
138240
  function readTeamProject(projectDir) {
137456
138241
  const record = readJsonRecord(teamProjectPath(projectDir));
@@ -137464,8 +138249,8 @@ function writeTeamProject(projectDir, team) {
137464
138249
  projectId: team.projectId,
137465
138250
  ...team.spaceId ? { spaceId: team.spaceId } : {}
137466
138251
  };
137467
- mkdirSync39(join83(resolve47(projectDir), TEAM_PROJECT_DIR), { recursive: true });
137468
- writeFileSync28(file, `${JSON.stringify(body, null, 2)}
138252
+ mkdirSync41(join85(resolve47(projectDir), TEAM_PROJECT_DIR), { recursive: true });
138253
+ writeFileSync29(file, `${JSON.stringify(body, null, 2)}
137469
138254
  `);
137470
138255
  return file;
137471
138256
  }
@@ -137473,16 +138258,16 @@ var CONFIG_DIR2, PROJECTS_FILE, TEAM_PROJECT_DIR, TEAM_PROJECT_FILE;
137473
138258
  var init_projectLink = __esm({
137474
138259
  "src/utils/projectLink.ts"() {
137475
138260
  "use strict";
137476
- CONFIG_DIR2 = join83(homedir16(), ".hyperframes");
137477
- PROJECTS_FILE = join83(CONFIG_DIR2, "projects.json");
138261
+ CONFIG_DIR2 = join85(homedir18(), ".hyperframes");
138262
+ PROJECTS_FILE = join85(CONFIG_DIR2, "projects.json");
137478
138263
  TEAM_PROJECT_DIR = ".hyperframes";
137479
138264
  TEAM_PROJECT_FILE = "project.json";
137480
138265
  }
137481
138266
  });
137482
138267
 
137483
138268
  // src/utils/publishProject.ts
137484
- import { basename as basename14, dirname as dirname37, join as join84, posix as posix5, relative as relative18, resolve as resolve48 } from "path";
137485
- import { existsSync as existsSync76, readdirSync as readdirSync27, readFileSync as readFileSync47, statSync as statSync27 } from "fs";
138269
+ import { basename as basename14, dirname as dirname37, join as join86, posix as posix5, relative as relative18, resolve as resolve48 } from "path";
138270
+ import { existsSync as existsSync78, readdirSync as readdirSync27, readFileSync as readFileSync50, statSync as statSync27 } from "fs";
137486
138271
  import AdmZip from "adm-zip";
137487
138272
  import ignore2 from "ignore";
137488
138273
  function isRecord8(value) {
@@ -137644,16 +138429,16 @@ function shouldIgnoreSegment(segment) {
137644
138429
  }
137645
138430
  function createProjectIgnore(rootDir) {
137646
138431
  const matcher = ignore2().add(DEFAULT_PROJECT_IGNORE);
137647
- const ignorePath = join84(rootDir, HYPERFRAMES_IGNORE_FILE);
137648
- if (existsSync76(ignorePath)) {
137649
- matcher.add(readFileSync47(ignorePath, "utf-8"));
138432
+ const ignorePath = join86(rootDir, HYPERFRAMES_IGNORE_FILE);
138433
+ if (existsSync78(ignorePath)) {
138434
+ matcher.add(readFileSync50(ignorePath, "utf-8"));
137650
138435
  }
137651
138436
  return matcher;
137652
138437
  }
137653
138438
  function collectProjectFiles(rootDir, currentDir, paths, matcher) {
137654
138439
  for (const entry of readdirSync27(currentDir, { withFileTypes: true })) {
137655
138440
  if (shouldIgnoreSegment(entry.name)) continue;
137656
- const absolutePath = join84(currentDir, entry.name);
138441
+ const absolutePath = join86(currentDir, entry.name);
137657
138442
  const relativePath = relative18(rootDir, absolutePath).replaceAll("\\", "/");
137658
138443
  if (!relativePath) continue;
137659
138444
  if (entry.isDirectory()) {
@@ -137679,7 +138464,7 @@ function addExternalAsset(ctx, absPath) {
137679
138464
  while (ctx.usedArchivePaths.has(`${base2}_${i2}${ext}`)) i2++;
137680
138465
  archivePath = `${base2}_${i2}${ext}`;
137681
138466
  }
137682
- ctx.fileContents.set(archivePath, readFileSync47(absPath));
138467
+ ctx.fileContents.set(archivePath, readFileSync50(absPath));
137683
138468
  ctx.externalMap.set(absPath, archivePath);
137684
138469
  ctx.usedArchivePaths.add(archivePath);
137685
138470
  return archivePath;
@@ -137689,7 +138474,7 @@ function tryResolveExternal(ctx, rawPath, referrerAbsDir) {
137689
138474
  const absPath = resolve48(referrerAbsDir, rawPath);
137690
138475
  if (isPathInside(absPath, ctx.absProjectDir)) return null;
137691
138476
  try {
137692
- if (!existsSync76(absPath) || !statSync27(absPath).isFile()) return null;
138477
+ if (!existsSync78(absPath) || !statSync27(absPath).isFile()) return null;
137693
138478
  } catch {
137694
138479
  return null;
137695
138480
  }
@@ -137794,7 +138579,7 @@ function buildPublishFileMap(projectDir) {
137794
138579
  }
137795
138580
  const fileContents = /* @__PURE__ */ new Map();
137796
138581
  for (const filePath of filePaths) {
137797
- fileContents.set(filePath, readFileSync47(join84(absProjectDir, filePath)));
138582
+ fileContents.set(filePath, readFileSync50(join86(absProjectDir, filePath)));
137798
138583
  }
137799
138584
  localizeExternalAssets(absProjectDir, fileContents);
137800
138585
  return fileContents;
@@ -137980,7 +138765,7 @@ var init_publishProject = __esm({
137980
138765
  });
137981
138766
 
137982
138767
  // src/utils/publishProxyBake.ts
137983
- import { existsSync as existsSync77 } from "fs";
138768
+ import { existsSync as existsSync79 } from "fs";
137984
138769
  import { readFile as readFile4 } from "fs/promises";
137985
138770
  import { basename as basename15, dirname as dirname38, resolve as resolve49 } from "path";
137986
138771
  function emptyManifest() {
@@ -138038,7 +138823,7 @@ async function bakeMediaProxies(projectDir, fileContents) {
138038
138823
  const rootRelativeSrc = rewriteAssetPath(
138039
138824
  entryPath,
138040
138825
  cleaned,
138041
- (path2) => existsSync77(resolve49(absProjectDir, path2))
138826
+ (path2) => existsSync79(resolve49(absProjectDir, path2))
138042
138827
  );
138043
138828
  for (const candidate of resolveLocalAssetCandidates(absProjectDir, rootRelativeSrc)) {
138044
138829
  const archivePath = proxyByAbsolutePath.get(candidate);
@@ -138082,8 +138867,8 @@ __export(publish_exports, {
138082
138867
  examples: () => examples8,
138083
138868
  parseUpdateTarget: () => parseUpdateTarget
138084
138869
  });
138085
- import { join as join85, relative as relative19, resolve as resolve50 } from "path";
138086
- import { existsSync as existsSync78 } from "fs";
138870
+ import { join as join87, relative as relative19, resolve as resolve50 } from "path";
138871
+ import { existsSync as existsSync80 } from "fs";
138087
138872
  function parseUpdateTarget(value) {
138088
138873
  const trimmed = value.trim();
138089
138874
  const pathMatch = trimmed.match(/\/p\/([^/?#]+)/);
@@ -138153,8 +138938,8 @@ var init_publish = __esm({
138153
138938
  async run({ args }) {
138154
138939
  const rawArg = args.dir;
138155
138940
  const dir = resolve50(rawArg ?? ".");
138156
- const indexPath2 = join85(dir, "index.html");
138157
- if (existsSync78(indexPath2)) {
138941
+ const indexPath2 = join87(dir, "index.html");
138942
+ if (existsSync80(indexPath2)) {
138158
138943
  const lintResult = await lintProject(dir);
138159
138944
  if (lintResult.totalErrors > 0 || lintResult.totalWarnings > 0) {
138160
138945
  console.log();
@@ -138295,7 +139080,7 @@ var init_publish = __esm({
138295
139080
 
138296
139081
  // src/commands/render/plan.ts
138297
139082
  import { statSync as statSync28 } from "fs";
138298
- import { dirname as dirname39, join as join86, resolve as resolve51 } from "path";
139083
+ import { dirname as dirname39, join as join88, resolve as resolve51 } from "path";
138299
139084
  function formatFpsParseError(input2, reason) {
138300
139085
  switch (reason) {
138301
139086
  case "empty":
@@ -138465,8 +139250,8 @@ function createRenderPlan(args, now = /* @__PURE__ */ new Date()) {
138465
139250
  const rendersDir = resolve51("renders");
138466
139251
  const ext = FORMAT_EXT[format];
138467
139252
  const timestamp = formatRenderOutputTimestamp(now);
138468
- const batchOutputTemplate = args.output ? args.output : join86(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
138469
- const outputPath = args.output ? resolve51(args.output) : join86(rendersDir, `${project.name}_${timestamp}${ext}`);
139253
+ const batchOutputTemplate = args.output ? args.output : join88(rendersDir, `${project.name}_${timestamp}_{index}${ext}`);
139254
+ const outputPath = args.output ? resolve51(args.output) : join88(rendersDir, `${project.name}_${timestamp}${ext}`);
138470
139255
  const useDocker = args.docker ?? false;
138471
139256
  const useGpu = args.gpu ?? false;
138472
139257
  const browserGpuMode = resolveBrowserGpuForCli(useDocker, args["browser-gpu"]);
@@ -138597,7 +139382,7 @@ var init_plan2 = __esm({
138597
139382
 
138598
139383
  // src/commands/render/present.ts
138599
139384
  import { cpus as cpus4 } from "os";
138600
- import { readFileSync as readFileSync48 } from "fs";
139385
+ import { readFileSync as readFileSync51 } from "fs";
138601
139386
  async function presentRenderPlan(plan2) {
138602
139387
  await presentRenderWarnings(plan2);
138603
139388
  if (plan2.effectiveQuiet || plan2.batchPath) return;
@@ -138640,7 +139425,7 @@ function presentRenderSummary(plan2) {
138640
139425
  async function warnForSlideshow(plan2) {
138641
139426
  try {
138642
139427
  const { slideshowIslandRegex: slideshowIslandRegex2 } = await Promise.resolve().then(() => (init_slideshow2(), slideshow_exports));
138643
- if (!slideshowIslandRegex2("i").test(readFileSync48(plan2.renderTarget, "utf8"))) return;
139428
+ if (!slideshowIslandRegex2("i").test(readFileSync51(plan2.renderTarget, "utf8"))) return;
138644
139429
  console.log(
138645
139430
  c.warn("\u26A0") + " This composition carries a slideshow island \u2014 `render` captures only the first scene, so the MP4 will be truncated to slide 1. Use " + c.accent("hyperframes present") + " for the deck; a linear main-line MP4 export is not yet available."
138646
139431
  );
@@ -138657,9 +139442,9 @@ var init_present2 = __esm({
138657
139442
  });
138658
139443
 
138659
139444
  // src/utils/variables.ts
138660
- import { readFileSync as readFileSync49 } from "fs";
139445
+ import { readFileSync as readFileSync53 } from "fs";
138661
139446
  import { resolve as resolve52 } from "path";
138662
- function parseVariablesArg(inline, filePath, readFile5 = (p2) => readFileSync49(resolve52(p2), "utf8")) {
139447
+ function parseVariablesArg(inline, filePath, readFile5 = (p2) => readFileSync53(resolve52(p2), "utf8")) {
138663
139448
  if (inline != null && filePath != null) {
138664
139449
  return { ok: false, error: { kind: "conflict" } };
138665
139450
  }
@@ -138742,7 +139527,7 @@ function validateVariablesAgainstProject(indexPath2, values) {
138742
139527
  function loadProjectVariableSchema(indexPath2) {
138743
139528
  let html;
138744
139529
  try {
138745
- html = readFileSync49(indexPath2, "utf8");
139530
+ html = readFileSync53(indexPath2, "utf8");
138746
139531
  } catch {
138747
139532
  return [];
138748
139533
  }
@@ -138797,8 +139582,8 @@ __export(batchRender_exports, {
138797
139582
  resolveOutputTemplate: () => resolveOutputTemplate,
138798
139583
  runBatchRender: () => runBatchRender
138799
139584
  });
138800
- import { mkdirSync as mkdirSync40, readFileSync as readFileSync50, writeFileSync as writeFileSync29 } from "fs";
138801
- import { dirname as dirname40, join as join87, resolve as resolve53, sep as sep12 } from "path";
139585
+ import { mkdirSync as mkdirSync43, readFileSync as readFileSync54, writeFileSync as writeFileSync30 } from "fs";
139586
+ import { dirname as dirname40, join as join89, resolve as resolve53, sep as sep12 } from "path";
138802
139587
  function isRecord9(value) {
138803
139588
  return value !== null && typeof value === "object" && !Array.isArray(value);
138804
139589
  }
@@ -138923,7 +139708,7 @@ function reportBatchVariableIssues(row, index, schema, quiet, json) {
138923
139708
  }
138924
139709
  function prepareBatchRender(options) {
138925
139710
  const batchPath = resolve53(options.batchPath);
138926
- const read = options.readFile ?? ((path2) => readFileSync50(path2, "utf8"));
139711
+ const read = options.readFile ?? ((path2) => readFileSync54(path2, "utf8"));
138927
139712
  let raw;
138928
139713
  try {
138929
139714
  raw = read(batchPath);
@@ -138939,7 +139724,7 @@ function prepareBatchRender(options) {
138939
139724
  variables,
138940
139725
  outputPath: resolve53(resolveOutputTemplate(options.outputTemplate, variables, index))
138941
139726
  }));
138942
- const manifestPath2 = join87(
139727
+ const manifestPath2 = join89(
138943
139728
  commonOutputDirectory(rows.map((row) => row.outputPath)),
138944
139729
  "manifest.json"
138945
139730
  );
@@ -138987,8 +139772,8 @@ function summarizeManifest(manifest) {
138987
139772
  }
138988
139773
  function writeManifest(manifest) {
138989
139774
  summarizeManifest(manifest);
138990
- mkdirSync40(dirname40(manifest.manifestPath), { recursive: true });
138991
- writeFileSync29(manifest.manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
139775
+ mkdirSync43(dirname40(manifest.manifestPath), { recursive: true });
139776
+ writeFileSync30(manifest.manifestPath, JSON.stringify(manifest, null, 2) + "\n", "utf8");
138992
139777
  }
138993
139778
  async function renderBatchRow(row, manifest, options) {
138994
139779
  const manifestRow = manifest.rows[row.index];
@@ -139002,7 +139787,7 @@ async function renderBatchRow(row, manifest, options) {
139002
139787
  console.log(c.dim(`Batch row ${row.index}: ${row.outputPath}`));
139003
139788
  }
139004
139789
  try {
139005
- mkdirSync40(dirname40(row.outputPath), { recursive: true });
139790
+ mkdirSync43(dirname40(row.outputPath), { recursive: true });
139006
139791
  const result = await options.renderOne(row);
139007
139792
  manifestRow.status = "completed";
139008
139793
  manifestRow.durationMs = result.durationMs ?? null;
@@ -139119,13 +139904,13 @@ var init_batchRender = __esm({
139119
139904
  });
139120
139905
 
139121
139906
  // src/commands/render/execute.ts
139122
- import { mkdirSync as mkdirSync41, readFileSync as readFileSync51 } from "fs";
139907
+ import { mkdirSync as mkdirSync44, readFileSync as readFileSync55 } from "fs";
139123
139908
  function renderLintContinuationHint(strictErrors) {
139124
139909
  return strictErrors ? " Continuing render despite lint warnings. Use --strict-all to block warnings." : " Continuing render despite lint issues. Use --strict to block errors.";
139125
139910
  }
139126
139911
  async function executeRenderPlan(plan2, dependencies) {
139127
139912
  applyRenderEnvironment(plan2);
139128
- if (!plan2.batchPath) mkdirSync41(renderOutputDirectory(plan2), { recursive: true });
139913
+ if (!plan2.batchPath) mkdirSync44(renderOutputDirectory(plan2), { recursive: true });
139129
139914
  let batchModule;
139130
139915
  let preparedBatch;
139131
139916
  if (plan2.batchPath) {
@@ -139260,7 +140045,7 @@ async function runResolutionPreflight(plan2, checkResolution) {
139260
140045
  if (!plan2.outputResolution) return;
139261
140046
  let issue;
139262
140047
  try {
139263
- issue = await checkResolution(readFileSync51(plan2.renderTarget, "utf8"), plan2.outputResolution, {
140048
+ issue = await checkResolution(readFileSync55(plan2.renderTarget, "utf8"), plan2.outputResolution, {
139264
140049
  alphaRequested: plan2.format === "webm" || plan2.format === "mov" || plan2.format === "png-sequence",
139265
140050
  hdrRequested: plan2.hdrMode === "force-hdr",
139266
140051
  aspectAgnostic: plan2.outputResolutionAspectAgnostic
@@ -139659,7 +140444,7 @@ var init_dockerRunArgs = __esm({
139659
140444
 
139660
140445
  // src/browser/preflight.ts
139661
140446
  import { execFileSync as execFileSync10 } from "child_process";
139662
- import { existsSync as existsSync79 } from "fs";
140447
+ import { existsSync as existsSync81 } from "fs";
139663
140448
  import { platform as platform8 } from "os";
139664
140449
  function parseToolVersion(raw) {
139665
140450
  const m2 = raw.match(/(ffmpeg|ffprobe)\s+version\s+([\d][\d.\-\w]*)/i);
@@ -139667,7 +140452,7 @@ function parseToolVersion(raw) {
139667
140452
  }
139668
140453
  function configuredMissingDetail(envName) {
139669
140454
  const configured = process.env[envName]?.trim();
139670
- if (!configured || existsSync79(configured)) return void 0;
140455
+ if (!configured || existsSync81(configured)) return void 0;
139671
140456
  return `Configured path does not exist: ${envName}="${configured}"`;
139672
140457
  }
139673
140458
  function readToolVersion(binaryPath) {
@@ -139764,7 +140549,7 @@ function chromeSharedLibOutcome(executablePath, found) {
139764
140549
  }
139765
140550
  async function checkChrome(browserPath) {
139766
140551
  if (browserPath) {
139767
- if (existsSync79(browserPath)) {
140552
+ if (existsSync81(browserPath)) {
139768
140553
  return chromeSharedLibOutcome(browserPath, {
139769
140554
  name: "Chrome",
139770
140555
  ok: true,
@@ -139922,9 +140707,9 @@ __export(render_exports, {
139922
140707
  renderLocal: () => renderLocal,
139923
140708
  resolveBrowserGpuForCli: () => resolveBrowserGpuForCli
139924
140709
  });
139925
- import { mkdtempSync as mkdtempSync12, readdirSync as readdirSync28, readFileSync as readFileSync53, statSync as statSync29, writeFileSync as writeFileSync30, rmSync as rmSync27 } from "fs";
140710
+ import { mkdtempSync as mkdtempSync12, readdirSync as readdirSync28, readFileSync as readFileSync56, statSync as statSync29, writeFileSync as writeFileSync31, rmSync as rmSync27 } from "fs";
139926
140711
  import { freemem as freemem5, tmpdir as tmpdir12 } from "os";
139927
- import { resolve as resolve54, dirname as dirname41, join as join88, basename as basename16 } from "path";
140712
+ import { resolve as resolve54, dirname as dirname41, join as join90, basename as basename16 } from "path";
139928
140713
  import { execFileSync as execFileSync11, spawn as spawn15 } from "child_process";
139929
140714
  async function readCompositionDimensions(compositionHtml) {
139930
140715
  try {
@@ -139990,8 +140775,8 @@ function ensureDockerImage(version2, platform10, quiet) {
139990
140775
  }
139991
140776
  if (!quiet) console.log(c.dim(` Building Docker image: ${tag} (${platform10})...`));
139992
140777
  const dockerfilePath = resolveDockerfilePath();
139993
- const tmpDir = mkdtempSync12(join88(tmpdir12(), "hyperframes-docker-"));
139994
- writeFileSync30(join88(tmpDir, "Dockerfile"), readFileSync53(dockerfilePath));
140778
+ const tmpDir = mkdtempSync12(join90(tmpdir12(), "hyperframes-docker-"));
140779
+ writeFileSync31(join90(tmpDir, "Dockerfile"), readFileSync56(dockerfilePath));
139995
140780
  const targetArch = platform10 === "linux/arm64" ? "arm64" : "amd64";
139996
140781
  try {
139997
140782
  execFileSync11(
@@ -140617,7 +141402,7 @@ function printRenderComplete(outputPath, elapsedMs, quiet, outputDurationSeconds
140617
141402
  for (const entry of readdirSync28(outputPath, { withFileTypes: true })) {
140618
141403
  if (!entry.isFile()) continue;
140619
141404
  try {
140620
- total += statSync29(join88(outputPath, entry.name)).size;
141405
+ total += statSync29(join90(outputPath, entry.name)).size;
140621
141406
  } catch {
140622
141407
  }
140623
141408
  }
@@ -141029,7 +141814,7 @@ __export(staticProjectServer_exports, {
141029
141814
  serveStaticProjectHtml: () => serveStaticProjectHtml
141030
141815
  });
141031
141816
  import { createServer as createServer2 } from "http";
141032
- import { createReadStream as createReadStream7, existsSync as existsSync80, statSync as statSync30 } from "fs";
141817
+ import { createReadStream as createReadStream7, existsSync as existsSync83, statSync as statSync30 } from "fs";
141033
141818
  import { isAbsolute as isAbsolute14, relative as relative20, resolve as resolve55 } from "path";
141034
141819
  function serveFileWithRange(filePath, rangeHeader, res, contentType = getMimeType(filePath)) {
141035
141820
  const size = statSync30(filePath).size;
@@ -141133,7 +141918,7 @@ async function serveStaticProjectHtml(projectDir, html, bindErrorMessage = "Fail
141133
141918
  const filePath = resolve55(root, requestPath);
141134
141919
  const rel = relative20(root, filePath);
141135
141920
  if (rel.startsWith("..") || isAbsolute14(rel)) continue;
141136
- if (existsSync80(filePath)) {
141921
+ if (existsSync83(filePath)) {
141137
141922
  if (proxyRequest) {
141138
141923
  void serveProxyRequest(
141139
141924
  projectDir,
@@ -141597,8 +142382,8 @@ var init_motionAudit = __esm({
141597
142382
  });
141598
142383
 
141599
142384
  // src/utils/motionSpec.ts
141600
- import { existsSync as existsSync81, readFileSync as readFileSync54, readdirSync as readdirSync29 } from "fs";
141601
- import { basename as basename17, join as join89 } from "path";
142385
+ import { existsSync as existsSync84, readFileSync as readFileSync57, readdirSync as readdirSync29 } from "fs";
142386
+ import { basename as basename17, join as join91 } from "path";
141602
142387
  function isObject2(value) {
141603
142388
  return typeof value === "object" && value !== null && !Array.isArray(value);
141604
142389
  }
@@ -141640,11 +142425,11 @@ function parseMotionSpec(raw) {
141640
142425
  return { ok: true, spec };
141641
142426
  }
141642
142427
  function findMotionSpec(projectDir) {
141643
- if (!existsSync81(projectDir)) return null;
142428
+ if (!existsSync84(projectDir)) return null;
141644
142429
  const entries2 = readdirSync29(projectDir);
141645
142430
  const sidecars = entries2.filter((name) => name.endsWith(".motion.json")).sort();
141646
142431
  if (!sidecars[0]) return null;
141647
- if (sidecars.length === 1) return join89(projectDir, sidecars[0]);
142432
+ if (sidecars.length === 1) return join91(projectDir, sidecars[0]);
141648
142433
  const htmlBases = new Set(
141649
142434
  entries2.filter((name) => name.endsWith(".html")).map((name) => basename17(name, ".html"))
141650
142435
  );
@@ -141654,12 +142439,12 @@ function findMotionSpec(projectDir) {
141654
142439
  `ambiguous motion sidecars in ${projectDir}: ${matched.join(", ")} each match a composition \u2014 remove the sidecars you do not need, or use one composition per project`
141655
142440
  );
141656
142441
  }
141657
- return join89(projectDir, matched[0] ?? sidecars[0]);
142442
+ return join91(projectDir, matched[0] ?? sidecars[0]);
141658
142443
  }
141659
142444
  function readMotionSpec(path2) {
141660
142445
  let raw;
141661
142446
  try {
141662
- raw = JSON.parse(readFileSync54(path2, "utf-8"));
142447
+ raw = JSON.parse(readFileSync57(path2, "utf-8"));
141663
142448
  } catch (err) {
141664
142449
  return { ok: false, errors: [`could not read ${basename17(path2)}: ${err.message}`] };
141665
142450
  }
@@ -141712,8 +142497,8 @@ __export(layout_exports, {
141712
142497
  loadBrowserScript: () => loadBrowserScript,
141713
142498
  parseAt: () => parseAt
141714
142499
  });
141715
- import { existsSync as existsSync83, readFileSync as readFileSync55 } from "fs";
141716
- import { dirname as dirname42, join as join90 } from "path";
142500
+ import { existsSync as existsSync85, readFileSync as readFileSync58 } from "fs";
142501
+ import { dirname as dirname42, join as join93 } from "path";
141717
142502
  import { fileURLToPath as fileURLToPath11 } from "url";
141718
142503
  function buildMotionSampleTimes(duration) {
141719
142504
  if (!Number.isFinite(duration) || duration <= 0) return [];
@@ -141871,9 +142656,9 @@ async function runLayoutAudit(projectDir, opts) {
141871
142656
  }
141872
142657
  }
141873
142658
  function loadBrowserScript(name) {
141874
- const candidates = [join90(__dirname2, name), join90(__dirname2, "commands", name)];
142659
+ const candidates = [join93(__dirname2, name), join93(__dirname2, "commands", name)];
141875
142660
  for (const candidate of candidates) {
141876
- if (existsSync83(candidate)) return readFileSync55(candidate, "utf-8");
142661
+ if (existsSync85(candidate)) return readFileSync58(candidate, "utf-8");
141877
142662
  }
141878
142663
  throw new Error(`Missing browser script ${name}`);
141879
142664
  }
@@ -142270,9 +143055,9 @@ __export(validate_exports, {
142270
143055
  resolveNavigationTimeoutMs: () => resolveNavigationTimeoutMs,
142271
143056
  shouldIgnoreRequestFailure: () => shouldIgnoreRequestFailure
142272
143057
  });
142273
- import { existsSync as existsSync84, mkdtempSync as mkdtempSync13, readFileSync as readFileSync56, rmSync as rmSync28 } from "fs";
143058
+ import { existsSync as existsSync86, mkdtempSync as mkdtempSync13, readFileSync as readFileSync59, rmSync as rmSync28 } from "fs";
142274
143059
  import { tmpdir as tmpdir13 } from "os";
142275
- import { join as join91, dirname as dirname43 } from "path";
143060
+ import { join as join94, dirname as dirname43 } from "path";
142276
143061
  import { fileURLToPath as fileURLToPath12 } from "url";
142277
143062
  function resolveNavigationTimeoutMs(optTimeout) {
142278
143063
  return Math.max(NAV_TIMEOUT_FLOOR_MS, optTimeout ?? 0);
@@ -142421,11 +143206,11 @@ async function runContrastAudit(page) {
142421
143206
  }
142422
143207
  function loadContrastAuditScript() {
142423
143208
  const candidates = [
142424
- join91(__dirname3, "contrast-audit.browser.js"),
142425
- join91(__dirname3, "commands", "contrast-audit.browser.js")
143209
+ join94(__dirname3, "contrast-audit.browser.js"),
143210
+ join94(__dirname3, "commands", "contrast-audit.browser.js")
142426
143211
  ];
142427
143212
  for (const candidate of candidates) {
142428
- if (existsSync84(candidate)) return readFileSync56(candidate, "utf-8");
143213
+ if (existsSync86(candidate)) return readFileSync59(candidate, "utf-8");
142429
143214
  }
142430
143215
  throw new Error("Missing contrast audit browser script");
142431
143216
  }
@@ -142437,7 +143222,7 @@ async function localizeRemoteAssets(html) {
142437
143222
  try {
142438
143223
  const { loadProducer: loadProducer2 } = await Promise.resolve().then(() => (init_producer(), producer_exports));
142439
143224
  const { localizeRemoteMediaSources: localizeRemoteMediaSources2, localizeRemoteImageSources: localizeRemoteImageSources2, localizeRemoteFontFaces: localizeRemoteFontFaces2 } = await loadProducer2();
142440
- dir = mkdtempSync13(join91(tmpdir13(), "hf-validate-assets-"));
143225
+ dir = mkdtempSync13(join94(tmpdir13(), "hf-validate-assets-"));
142441
143226
  const assetDir = dir;
142442
143227
  const media = await localizeRemoteMediaSources2(html, assetDir);
142443
143228
  const images = await localizeRemoteImageSources2(media.html, assetDir);
@@ -142755,8 +143540,8 @@ __export(checkBrowser_exports, {
142755
143540
  preResolveHostileMediaProxies: () => preResolveHostileMediaProxies,
142756
143541
  runBrowserCheck: () => runBrowserCheck
142757
143542
  });
142758
- import { mkdirSync as mkdirSync43, writeFileSync as writeFileSync31 } from "fs";
142759
- import { join as join93, resolve as resolve56 } from "path";
143543
+ import { mkdirSync as mkdirSync45, writeFileSync as writeFileSync33 } from "fs";
143544
+ import { join as join95, resolve as resolve56 } from "path";
142760
143545
  async function preResolveHostileMediaProxies(projectDir, html, autoProxyOverride) {
142761
143546
  if (!resolveAutoProxy(projectDir, autoProxyOverride)) return;
142762
143547
  let codecMap;
@@ -142856,8 +143641,8 @@ async function captureFindingCrops(project, options, requests) {
142856
143641
  chromeBrowser = session.browser;
142857
143642
  const page = session.page;
142858
143643
  await waitForPreferredSeekTarget(page);
142859
- const snapshotDir = join93(project.dir, "snapshots");
142860
- mkdirSync43(snapshotDir, { recursive: true });
143644
+ const snapshotDir = join95(project.dir, "snapshots");
143645
+ mkdirSync45(snapshotDir, { recursive: true });
142861
143646
  for (const request of requests) {
142862
143647
  await seekCompositionTimeline(page, request.time, AUDIT_SEEK_OPTIONS);
142863
143648
  const canvas = await page.evaluate(() => ({
@@ -142866,8 +143651,8 @@ async function captureFindingCrops(project, options, requests) {
142866
143651
  }));
142867
143652
  const region = padCropRegion(request.bbox, canvas, DEFAULT_ZOOM_PADDING_PX);
142868
143653
  const buffer = await captureRegionCrop(page, region, DEFAULT_ZOOM_SCALE);
142869
- writeFileSync31(join93(snapshotDir, request.filename), buffer);
142870
- written.push(join93("snapshots", request.filename));
143654
+ writeFileSync33(join95(snapshotDir, request.filename), buffer);
143655
+ written.push(join95("snapshots", request.filename));
142871
143656
  }
142872
143657
  return written;
142873
143658
  } finally {
@@ -143673,8 +144458,8 @@ var init_checkBrowser = __esm({
143673
144458
  });
143674
144459
 
143675
144460
  // src/utils/checkPipeline.ts
143676
- import { mkdirSync as mkdirSync44, writeFileSync as writeFileSync33 } from "fs";
143677
- import { join as join94, relative as relative21 } from "path";
144461
+ import { mkdirSync as mkdirSync46, writeFileSync as writeFileSync34 } from "fs";
144462
+ import { join as join96, relative as relative21 } from "path";
143678
144463
  function selectContrastTimes(grid) {
143679
144464
  if (grid.length <= 5) return [...grid];
143680
144465
  return Array.from({ length: 5 }, (_, index) => {
@@ -144619,12 +145404,12 @@ async function runBrowserCheck2(project, options, motion) {
144619
145404
  return module.runBrowserCheck(project, options, motion, runAuditGrid);
144620
145405
  }
144621
145406
  async function writeSnapshot(projectDir, index, time, pngBase64) {
144622
- const snapshotDir = join94(projectDir, "snapshots");
144623
- mkdirSync44(snapshotDir, { recursive: true });
145407
+ const snapshotDir = join96(projectDir, "snapshots");
145408
+ mkdirSync46(snapshotDir, { recursive: true });
144624
145409
  const filename = `frame-${String(index).padStart(2, "0")}-at-${time.toFixed(1)}s.png`;
144625
- const path2 = join94(snapshotDir, filename);
144626
- writeFileSync33(path2, Buffer.from(pngBase64, "base64"));
144627
- return join94("snapshots", filename);
145410
+ const path2 = join96(snapshotDir, filename);
145411
+ writeFileSync34(path2, Buffer.from(pngBase64, "base64"));
145412
+ return join96("snapshots", filename);
144628
145413
  }
144629
145414
  async function captureFindingCrops2(project, options, requests) {
144630
145415
  const module = await Promise.resolve().then(() => (init_checkBrowser(), checkBrowser_exports));
@@ -145219,28 +146004,28 @@ var init_beats = __esm({
145219
146004
  });
145220
146005
 
145221
146006
  // src/beats/headlessAnalyzer.ts
145222
- import { existsSync as existsSync85, readFileSync as readFileSync57 } from "fs";
146007
+ import { existsSync as existsSync87, readFileSync as readFileSync60 } from "fs";
145223
146008
  import { createRequire as createRequire3 } from "module";
145224
- import { dirname as dirname44, join as join95 } from "path";
146009
+ import { dirname as dirname44, join as join97 } from "path";
145225
146010
  import { fileURLToPath as fileURLToPath13 } from "url";
145226
146011
  function findPrebuiltBundle() {
145227
146012
  const here = dirname44(fileURLToPath13(import.meta.url));
145228
146013
  const candidates = [
145229
- join95(here, "beat-analyzer.global.js"),
146014
+ join97(here, "beat-analyzer.global.js"),
145230
146015
  // dist root (tsup-bundled cli)
145231
- join95(here, "../beat-analyzer.global.js"),
146016
+ join97(here, "../beat-analyzer.global.js"),
145232
146017
  // dist/beats → dist
145233
- join95(here, "../dist/beat-analyzer.global.js")
146018
+ join97(here, "../dist/beat-analyzer.global.js")
145234
146019
  ];
145235
146020
  for (const p2 of candidates) {
145236
- if (existsSync85(p2)) return p2;
146021
+ if (existsSync87(p2)) return p2;
145237
146022
  }
145238
146023
  return null;
145239
146024
  }
145240
146025
  async function buildFromCoreSource() {
145241
146026
  const esbuild = await import("esbuild");
145242
146027
  const coreRoot = dirname44(require2.resolve("@hyperframes/core/package.json"));
145243
- const entry = join95(coreRoot, "src/beats/beatDetection.ts");
146028
+ const entry = join97(coreRoot, "src/beats/beatDetection.ts");
145244
146029
  const result = await esbuild.build({
145245
146030
  stdin: {
145246
146031
  contents: `import { analyzeMusicFromBuffer } from ${JSON.stringify(entry)};
@@ -145262,7 +146047,7 @@ function buildAnalyzerBundle() {
145262
146047
  if (bundlePromise) return bundlePromise;
145263
146048
  bundlePromise = (async () => {
145264
146049
  const prebuilt = findPrebuiltBundle();
145265
- if (prebuilt) return readFileSync57(prebuilt, "utf8");
146050
+ if (prebuilt) return readFileSync60(prebuilt, "utf8");
145266
146051
  return buildFromCoreSource();
145267
146052
  })().catch((err) => {
145268
146053
  bundlePromise = null;
@@ -145340,14 +146125,14 @@ __export(beats_exports, {
145340
146125
  default: () => beats_default,
145341
146126
  examples: () => examples13
145342
146127
  });
145343
- import { existsSync as existsSync86, readFileSync as readFileSync58, mkdirSync as mkdirSync45, writeFileSync as writeFileSync34 } from "fs";
145344
- import { resolve as resolve57, join as join96, dirname as dirname45 } from "path";
146128
+ import { existsSync as existsSync88, readFileSync as readFileSync61, mkdirSync as mkdirSync47, writeFileSync as writeFileSync35 } from "fs";
146129
+ import { resolve as resolve57, join as join98, dirname as dirname45 } from "path";
145345
146130
  function fail(message) {
145346
146131
  console.error(c.error(message));
145347
146132
  failCommand();
145348
146133
  }
145349
146134
  function resolveMusicTarget(project) {
145350
- const src = findMusicAudioSrc(readFileSync58(project.indexPath, "utf-8"));
146135
+ const src = findMusicAudioSrc(readFileSync61(project.indexPath, "utf-8"));
145351
146136
  if (!src) {
145352
146137
  fail(
145353
146138
  'No music track found. Add data-timeline-role="music" to the <audio> element (or give it an id like music/bgm/soundtrack).'
@@ -145356,12 +146141,12 @@ function resolveMusicTarget(project) {
145356
146141
  const rel = audioRelPathForSrc(src);
145357
146142
  if (!rel) fail(`Cannot derive a beat-file path for music src: ${src}`);
145358
146143
  const audioPath = resolve57(project.dir, rel);
145359
- if (!existsSync86(audioPath)) fail(`Audio file not found: ${rel}`);
146144
+ if (!existsSync88(audioPath)) fail(`Audio file not found: ${rel}`);
145360
146145
  return { rel, audioPath };
145361
146146
  }
145362
146147
  async function detect(audioPath) {
145363
146148
  try {
145364
- return await analyzeBeatsHeadless(readFileSync58(audioPath));
146149
+ return await analyzeBeatsHeadless(readFileSync61(audioPath));
145365
146150
  } catch (err) {
145366
146151
  const msg = err instanceof Error ? err.message : String(err);
145367
146152
  const hint2 = /chrome|executable|browser|ENOENT/i.test(msg) ? "\nRun: npx hyperframes browser ensure" : "";
@@ -145412,9 +146197,9 @@ var init_beats2 = __esm({
145412
146197
  if (result.beatTimes.length === 0) {
145413
146198
  fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
145414
146199
  }
145415
- const outPath = join96(project.dir, "beats", `${rel}.json`);
145416
- mkdirSync45(dirname45(outPath), { recursive: true });
145417
- writeFileSync34(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
146200
+ const outPath = join98(project.dir, "beats", `${rel}.json`);
146201
+ mkdirSync47(dirname45(outPath), { recursive: true });
146202
+ writeFileSync35(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
145418
146203
  report(`beats/${rel}.json`, result, Boolean(args.json));
145419
146204
  }
145420
146205
  });
@@ -147369,10 +148154,10 @@ __export(motionShot_exports, {
147369
148154
  ensureShotOutputDir: () => ensureShotOutputDir,
147370
148155
  seekAllAdaptersInBrowser: () => seekAllAdaptersInBrowser
147371
148156
  });
147372
- import { mkdirSync as mkdirSync46, writeFileSync as writeFileSync35 } from "fs";
148157
+ import { mkdirSync as mkdirSync48, writeFileSync as writeFileSync36 } from "fs";
147373
148158
  import { dirname as dirname46 } from "path";
147374
148159
  function ensureShotOutputDir(outPath) {
147375
- mkdirSync46(dirname46(outPath), { recursive: true });
148160
+ mkdirSync48(dirname46(outPath), { recursive: true });
147376
148161
  }
147377
148162
  function applyOrbitCamera(selectors, cam) {
147378
148163
  const first = document.querySelector(selectors[0] ?? "");
@@ -147693,7 +148478,7 @@ async function captureGhostOnionSkin(page, requests, times, size, camera, outPat
147693
148478
  );
147694
148479
  const b64 = String(dataUrl).replace(/^data:image\/png;base64,/, "");
147695
148480
  if (!b64) throw new Error("ghost composite returned no data");
147696
- writeFileSync35(outPath, Buffer.from(b64, "base64"));
148481
+ writeFileSync36(outPath, Buffer.from(b64, "base64"));
147697
148482
  return outPath;
147698
148483
  }
147699
148484
  async function captureMarkerOnionSkin(page, requests, times, size, camera, frame, outPath) {
@@ -147763,7 +148548,7 @@ async function captureMarkerOnionSkin(page, requests, times, size, camera, frame
147763
148548
  await new Promise((r2) => setTimeout(r2, 60));
147764
148549
  const buf = await page.screenshot({ type: "png" });
147765
148550
  if (!buf) throw new Error("screenshot returned no data");
147766
- writeFileSync35(outPath, buf);
148551
+ writeFileSync36(outPath, buf);
147767
148552
  return outPath;
147768
148553
  }
147769
148554
  async function captureMotionPathShot(projectDir, requestsIn, outPath, opts = {}) {
@@ -147835,8 +148620,8 @@ __export(keyframes_exports, {
147835
148620
  resolveScope: () => resolveScope,
147836
148621
  surfaceComposition: () => surfaceComposition
147837
148622
  });
147838
- import { existsSync as existsSync87, readFileSync as readFileSync59, statSync as statSync31 } from "fs";
147839
- import { resolve as resolve58, dirname as dirname47, basename as basename18, join as join97, relative as relative23, sep as sep13 } from "path";
148623
+ import { existsSync as existsSync89, readFileSync as readFileSync63, statSync as statSync31 } from "fs";
148624
+ import { resolve as resolve58, dirname as dirname47, basename as basename18, join as join99, relative as relative23, sep as sep13 } from "path";
147840
148625
  function queryIncludingTemplates(html, selector) {
147841
148626
  const doc = new DOMParser().parseFromString(html, "text/html");
147842
148627
  const roots = [doc];
@@ -148197,7 +148982,7 @@ function groupTraces(tweens) {
148197
148982
  return traces;
148198
148983
  }
148199
148984
  function collectCompositions(indexPath2) {
148200
- const html = readFileSync59(indexPath2, "utf-8");
148985
+ const html = readFileSync63(indexPath2, "utf-8");
148201
148986
  const baseDir = dirname47(indexPath2);
148202
148987
  const out = [
148203
148988
  surfaceComposition(html, basename18(indexPath2), basename18(indexPath2))
@@ -148207,9 +148992,9 @@ function collectCompositions(indexPath2) {
148207
148992
  const src = div.getAttribute("data-composition-src");
148208
148993
  if (!src) continue;
148209
148994
  const subPath = resolve58(baseDir, src);
148210
- if (!existsSync87(subPath)) continue;
148995
+ if (!existsSync89(subPath)) continue;
148211
148996
  const id = div.getAttribute("data-composition-id") ?? src;
148212
- out.push(surfaceComposition(readFileSync59(subPath, "utf-8"), id, src));
148997
+ out.push(surfaceComposition(readFileSync63(subPath, "utf-8"), id, src));
148213
148998
  }
148214
148999
  return out;
148215
149000
  }
@@ -148326,9 +149111,9 @@ function resolveScope(args) {
148326
149111
  let projectName;
148327
149112
  let projectDir;
148328
149113
  let entryFile;
148329
- if (raw && raw.endsWith(".html") && existsSync87(raw) && statSync31(raw).isFile()) {
149114
+ if (raw && raw.endsWith(".html") && existsSync89(raw) && statSync31(raw).isFile()) {
148330
149115
  const entryPath = resolve58(raw);
148331
- comps = [surfaceComposition(readFileSync59(entryPath, "utf-8"), basename18(entryPath), entryPath)];
149116
+ comps = [surfaceComposition(readFileSync63(entryPath, "utf-8"), basename18(entryPath), entryPath)];
148332
149117
  projectName = basename18(entryPath);
148333
149118
  projectDir = findProjectRoot(entryPath);
148334
149119
  entryFile = relative23(projectDir, entryPath).split(sep13).join("/");
@@ -148358,8 +149143,8 @@ function findProjectRoot(entryPath) {
148358
149143
  const entryDir = dirname47(entryPath);
148359
149144
  let candidate = entryDir;
148360
149145
  for (; ; ) {
148361
- if (existsSync87(join97(candidate, "index.html"))) return candidate;
148362
- if (existsSync87(join97(candidate, ".git"))) return entryDir;
149146
+ if (existsSync89(join99(candidate, "index.html"))) return candidate;
149147
+ if (existsSync89(join99(candidate, ".git"))) return entryDir;
148363
149148
  const parent = dirname47(candidate);
148364
149149
  if (parent === candidate) return entryDir;
148365
149150
  candidate = parent;
@@ -148549,8 +149334,8 @@ __export(info_exports, {
148549
149334
  examples: () => examples16,
148550
149335
  orientation: () => orientation
148551
149336
  });
148552
- import { readFileSync as readFileSync60, readdirSync as readdirSync30, statSync as statSync33 } from "fs";
148553
- import { join as join98 } from "path";
149337
+ import { readFileSync as readFileSync64, readdirSync as readdirSync30, statSync as statSync33 } from "fs";
149338
+ import { join as join100 } from "path";
148554
149339
  function orientation(width, height) {
148555
149340
  if (width > height) return "landscape";
148556
149341
  if (height > width) return "portrait";
@@ -148564,7 +149349,7 @@ function durationFromHtml(html, fallback) {
148564
149349
  function totalSize(dir) {
148565
149350
  let total = 0;
148566
149351
  for (const entry of readdirSync30(dir, { withFileTypes: true })) {
148567
- const path2 = join98(dir, entry.name);
149352
+ const path2 = join100(dir, entry.name);
148568
149353
  if (entry.isDirectory()) {
148569
149354
  total += totalSize(path2);
148570
149355
  } else {
@@ -148596,7 +149381,7 @@ var init_info = __esm({
148596
149381
  },
148597
149382
  async run({ args }) {
148598
149383
  const project = resolveProject(args.dir);
148599
- const html = readFileSync60(project.indexPath, "utf-8");
149384
+ const html = readFileSync64(project.indexPath, "utf-8");
148600
149385
  ensureDOMParser();
148601
149386
  const parsed = parseHtml(html);
148602
149387
  const tracks = new Set(parsed.elements.map((el) => el.zIndex));
@@ -148656,7 +149441,7 @@ __export(compositions_exports, {
148656
149441
  parseCompositions: () => parseCompositions,
148657
149442
  parseSubComposition: () => parseSubComposition
148658
149443
  });
148659
- import { existsSync as existsSync88, readFileSync as readFileSync61 } from "fs";
149444
+ import { existsSync as existsSync90, readFileSync as readFileSync65 } from "fs";
148660
149445
  import { resolve as resolve59, dirname as dirname48 } from "path";
148661
149446
  function countRenderableDescendants(root) {
148662
149447
  return Array.from(root.querySelectorAll("*")).filter(
@@ -148736,8 +149521,8 @@ function parseCompositions(html, baseDir) {
148736
149521
  const compositionSrc = div.getAttribute("data-composition-src");
148737
149522
  if (compositionSrc) {
148738
149523
  const subPath = resolve59(baseDir, compositionSrc);
148739
- if (existsSync88(subPath)) {
148740
- const subHtml = readFileSync61(subPath, "utf-8");
149524
+ if (existsSync90(subPath)) {
149525
+ const subHtml = readFileSync65(subPath, "utf-8");
148741
149526
  const subInfo = parseSubComposition(subHtml, id, width, height);
148742
149527
  compositions.push({ ...subInfo, source: compositionSrc });
148743
149528
  return;
@@ -148843,7 +149628,7 @@ var init_compositions = __esm({
148843
149628
  },
148844
149629
  async run({ args }) {
148845
149630
  const project = resolveProject(args.dir);
148846
- const html = readFileSync61(project.indexPath, "utf-8");
149631
+ const html = readFileSync65(project.indexPath, "utf-8");
148847
149632
  ensureDOMParser();
148848
149633
  const compositions = parseCompositions(html, dirname48(project.indexPath));
148849
149634
  if (args.json) {
@@ -148881,8 +149666,8 @@ __export(benchmark_exports, {
148881
149666
  default: () => benchmark_default,
148882
149667
  examples: () => examples18
148883
149668
  });
148884
- import { existsSync as existsSync89, statSync as statSync34 } from "fs";
148885
- import { resolve as resolve60, join as join99 } from "path";
149669
+ import { existsSync as existsSync91, statSync as statSync34 } from "fs";
149670
+ import { resolve as resolve60, join as join101 } from "path";
148886
149671
  var examples18, FPS_30, FPS_60, DEFAULT_CONFIGS, benchmark_default;
148887
149672
  var init_benchmark = __esm({
148888
149673
  "src/commands/benchmark.ts"() {
@@ -148961,7 +149746,7 @@ var init_benchmark = __esm({
148961
149746
  s2?.start(`Benchmarking ${config.label}...`);
148962
149747
  for (let i2 = 0; i2 < runsPerConfig; i2++) {
148963
149748
  s2?.message(`${config.label} \u2014 run ${i2 + 1}/${runsPerConfig}`);
148964
- const outputPath = join99(
149749
+ const outputPath = join101(
148965
149750
  benchDir,
148966
149751
  `${config.label.replace(/[^a-zA-Z0-9]/g, "_")}_run${i2}.mp4`
148967
149752
  );
@@ -148975,7 +149760,7 @@ var init_benchmark = __esm({
148975
149760
  await producer.executeRenderJob(job, project.dir, outputPath);
148976
149761
  const elapsedMs = Date.now() - startTime;
148977
149762
  let fileSize = null;
148978
- if (existsSync89(outputPath)) {
149763
+ if (existsSync91(outputPath)) {
148979
149764
  const stat3 = statSync34(outputPath);
148980
149765
  fileSize = stat3.size;
148981
149766
  }
@@ -149250,12 +150035,12 @@ __export(remove_background_exports, {
149250
150035
  examples: () => examples20
149251
150036
  });
149252
150037
  import { resolve as resolve61 } from "path";
149253
- import { existsSync as existsSync90 } from "fs";
150038
+ import { existsSync as existsSync93 } from "fs";
149254
150039
  async function showInfo(json) {
149255
150040
  const { selectProviders: selectProviders2, listAvailableProviders: listAvailableProviders2, DEFAULT_MODEL: DEFAULT_MODEL5, MODEL_MEMORY_MB: MODEL_MEMORY_MB2, modelPath: modelPath2 } = await Promise.resolve().then(() => (init_manager3(), manager_exports3));
149256
150041
  const providers = listAvailableProviders2();
149257
150042
  const auto = selectProviders2("auto");
149258
- const cached2 = existsSync90(modelPath2());
150043
+ const cached2 = existsSync93(modelPath2());
149259
150044
  if (json) {
149260
150045
  console.log(
149261
150046
  JSON.stringify({
@@ -149461,9 +150246,9 @@ var init_remove_background = __esm({
149461
150246
 
149462
150247
  // src/whisper/parakeet.ts
149463
150248
  import { execFileSync as execFileSync12 } from "child_process";
149464
- import { existsSync as existsSync91, mkdtempSync as mkdtempSync14, readFileSync as readFileSync63, rmSync as rmSync29, writeFileSync as writeFileSync36 } from "fs";
149465
- import { homedir as homedir17, tmpdir as tmpdir14 } from "os";
149466
- import { basename as basename19, extname as extname16, join as join100 } from "path";
150249
+ import { existsSync as existsSync94, mkdtempSync as mkdtempSync14, readFileSync as readFileSync66, rmSync as rmSync29, writeFileSync as writeFileSync37 } from "fs";
150250
+ import { homedir as homedir19, tmpdir as tmpdir14 } from "os";
150251
+ import { basename as basename19, extname as extname16, join as join103 } from "path";
149467
150252
  function isRunnable(bin) {
149468
150253
  try {
149469
150254
  execFileSync12(bin, ["--help"], { stdio: ["ignore", "ignore", "ignore"], timeout: 1e4 });
@@ -149475,10 +150260,10 @@ function isRunnable(bin) {
149475
150260
  function findParakeet() {
149476
150261
  const candidates = [
149477
150262
  process.env.HYPERFRAMES_PARAKEET,
149478
- join100(homedir17(), ".venvs", "parakeet", "bin", "parakeet-mlx")
150263
+ join103(homedir19(), ".venvs", "parakeet", "bin", "parakeet-mlx")
149479
150264
  ].filter((p2) => Boolean(p2));
149480
150265
  for (const path2 of candidates) {
149481
- if (existsSync91(path2) && isRunnable(path2)) return path2;
150266
+ if (existsSync94(path2) && isRunnable(path2)) return path2;
149482
150267
  }
149483
150268
  try {
149484
150269
  const which = process.platform === "win32" ? "where" : "which";
@@ -149488,7 +150273,7 @@ function findParakeet() {
149488
150273
  timeout: 5e3
149489
150274
  });
149490
150275
  const first = out.split(/\r?\n/).map((s2) => s2.trim()).find(Boolean);
149491
- if (first && existsSync91(first)) return first;
150276
+ if (first && existsSync94(first)) return first;
149492
150277
  } catch {
149493
150278
  }
149494
150279
  return void 0;
@@ -149525,22 +150310,22 @@ function transcribeWithParakeet(inputPath, dir, options) {
149525
150310
  );
149526
150311
  }
149527
150312
  const model = options?.model ?? DEFAULT_MODEL3;
149528
- const cached2 = existsSync91(
149529
- join100(homedir17(), ".cache", "huggingface", "hub", `models--${model.replace(/\//g, "--")}`)
150313
+ const cached2 = existsSync94(
150314
+ join103(homedir19(), ".cache", "huggingface", "hub", `models--${model.replace(/\//g, "--")}`)
149530
150315
  );
149531
150316
  options?.onProgress?.(
149532
150317
  cached2 ? "Transcribing with Parakeet..." : "Downloading Parakeet model (first run, ~600MB)..."
149533
150318
  );
149534
- const workDir = mkdtempSync14(join100(tmpdir14(), "hyperframes-parakeet-"));
150319
+ const workDir = mkdtempSync14(join103(tmpdir14(), "hyperframes-parakeet-"));
149535
150320
  try {
149536
150321
  const argv2 = [inputPath, "--model", model, "--output-format", "json", "--output-dir", workDir];
149537
150322
  if (options?.language) argv2.push("--language", options.language);
149538
150323
  execFileSync12(runner, argv2, { stdio: ["ignore", "pipe", "pipe"], timeout: 18e5 });
149539
- const produced = join100(workDir, `${basename19(inputPath, extname16(inputPath))}.json`);
149540
- if (!existsSync91(produced)) throw new Error("Parakeet did not produce output.");
149541
- const words = mergeTokensToWords(JSON.parse(readFileSync63(produced, "utf-8")));
149542
- const transcriptPath = join100(dir, "transcript.json");
149543
- writeFileSync36(transcriptPath, JSON.stringify(words, null, 2));
150324
+ const produced = join103(workDir, `${basename19(inputPath, extname16(inputPath))}.json`);
150325
+ if (!existsSync94(produced)) throw new Error("Parakeet did not produce output.");
150326
+ const words = mergeTokensToWords(JSON.parse(readFileSync66(produced, "utf-8")));
150327
+ const transcriptPath = join103(dir, "transcript.json");
150328
+ writeFileSync37(transcriptPath, JSON.stringify(words, null, 2));
149544
150329
  const durationSeconds = words.length > 0 ? words[words.length - 1].end : 0;
149545
150330
  return { transcriptPath, wordCount: words.length, durationSeconds, speechOnsetSeconds: null };
149546
150331
  } finally {
@@ -149562,8 +150347,8 @@ __export(transcribe_exports2, {
149562
150347
  default: () => transcribe_default,
149563
150348
  examples: () => examples21
149564
150349
  });
149565
- import { existsSync as existsSync93, writeFileSync as writeFileSync37 } from "fs";
149566
- import { resolve as resolve62, join as join101, extname as extname17, dirname as dirname49 } from "path";
150350
+ import { existsSync as existsSync95, writeFileSync as writeFileSync38 } from "fs";
150351
+ import { resolve as resolve62, join as join104, extname as extname17, dirname as dirname49 } from "path";
149567
150352
  function parseTimeoutMs(raw, json) {
149568
150353
  const source = raw ?? process.env["HYPERFRAMES_TRANSCRIBE_TIMEOUT_MS"];
149569
150354
  if (source == null || source === "") return void 0;
@@ -149599,8 +150384,8 @@ async function importTranscript(inputPath, dir, json) {
149599
150384
  const { loadTranscript: loadTranscript2, patchCaptionHtml: patchCaptionHtml2 } = await Promise.resolve().then(() => (init_normalize(), normalize_exports));
149600
150385
  const { words, format } = loadTranscript2(inputPath);
149601
150386
  if (words.length === 0) exitNoWords(json);
149602
- const outPath = join101(dir, "transcript.json");
149603
- writeFileSync37(outPath, JSON.stringify(words, null, 2));
150387
+ const outPath = join104(dir, "transcript.json");
150388
+ writeFileSync38(outPath, JSON.stringify(words, null, 2));
149604
150389
  patchCaptionHtml2(dir, words);
149605
150390
  if (json) {
149606
150391
  console.log(
@@ -149617,9 +150402,9 @@ async function exportTranscript(inputPath, dir, to, output, json, preserveCues)
149617
150402
  const { words, format } = loadTranscript2(inputPath);
149618
150403
  if (words.length === 0) exitNoWords(json);
149619
150404
  const preGrouped = preserveCues || format === "srt" || format === "vtt" || void 0;
149620
- const outPath = resolve62(output ?? join101(dir, `transcript.${to}`));
150405
+ const outPath = resolve62(output ?? join104(dir, `transcript.${to}`));
149621
150406
  const content = to === "srt" ? formatSrt2(words, { preGrouped }) : formatVtt2(words, { preGrouped });
149622
- writeFileSync37(outPath, content);
150407
+ writeFileSync38(outPath, content);
149623
150408
  if (json) {
149624
150409
  console.log(
149625
150410
  JSON.stringify({ ok: true, format: to, wordCount: words.length, outputPath: outPath })
@@ -149668,7 +150453,7 @@ async function transcribeAudio(inputPath, dir, opts) {
149668
150453
  );
149669
150454
  }
149670
150455
  }
149671
- writeFileSync37(result.transcriptPath, JSON.stringify(words, null, 2));
150456
+ writeFileSync38(result.transcriptPath, JSON.stringify(words, null, 2));
149672
150457
  patchCaptionHtml2(dir, words);
149673
150458
  if (opts.json) {
149674
150459
  console.log(
@@ -149801,7 +150586,7 @@ var init_transcribe2 = __esm({
149801
150586
  },
149802
150587
  async run({ args }) {
149803
150588
  const inputPath = resolve62(args.input);
149804
- if (!existsSync93(inputPath)) {
150589
+ if (!existsSync95(inputPath)) {
149805
150590
  const message = `File not found: ${args.input}`;
149806
150591
  trackCommandFailure("transcribe", message);
149807
150592
  console.error(c.error(message));
@@ -149838,9 +150623,9 @@ var init_transcribe2 = __esm({
149838
150623
  });
149839
150624
 
149840
150625
  // src/tts/manager.ts
149841
- import { existsSync as existsSync94, mkdirSync as mkdirSync47 } from "fs";
149842
- import { homedir as homedir18 } from "os";
149843
- import { join as join103 } from "path";
150626
+ import { existsSync as existsSync96, mkdirSync as mkdirSync49 } from "fs";
150627
+ import { homedir as homedir20 } from "os";
150628
+ import { join as join105 } from "path";
149844
150629
  function inferLangFromVoiceId(voiceId) {
149845
150630
  const first = voiceId.charAt(0).toLowerCase();
149846
150631
  return VOICE_PREFIX_LANG[first] ?? "en-us";
@@ -149849,41 +150634,41 @@ function isSupportedLang(value) {
149849
150634
  return SUPPORTED_LANGS.includes(value);
149850
150635
  }
149851
150636
  async function ensureModel3(model = DEFAULT_MODEL4, options) {
149852
- const modelPath2 = join103(MODELS_DIR3, `${model}.onnx`);
149853
- if (existsSync94(modelPath2)) return modelPath2;
150637
+ const modelPath2 = join105(MODELS_DIR4, `${model}.onnx`);
150638
+ if (existsSync96(modelPath2)) return modelPath2;
149854
150639
  const url = MODEL_URLS2[model];
149855
150640
  if (!url) {
149856
150641
  throw new Error(
149857
150642
  `Unknown TTS model: ${model}. Available: ${Object.keys(MODEL_URLS2).join(", ")}`
149858
150643
  );
149859
150644
  }
149860
- mkdirSync47(MODELS_DIR3, { recursive: true });
150645
+ mkdirSync49(MODELS_DIR4, { recursive: true });
149861
150646
  options?.onProgress?.(`Downloading TTS model ${model} (~311 MB)...`);
149862
150647
  await downloadFile(url, modelPath2);
149863
- if (!existsSync94(modelPath2)) {
150648
+ if (!existsSync96(modelPath2)) {
149864
150649
  throw new Error(`Model download failed: ${model}`);
149865
150650
  }
149866
150651
  return modelPath2;
149867
150652
  }
149868
150653
  async function ensureVoices(options) {
149869
- const voicesPath = join103(VOICES_DIR, "voices-v1.0.bin");
149870
- if (existsSync94(voicesPath)) return voicesPath;
149871
- mkdirSync47(VOICES_DIR, { recursive: true });
150654
+ const voicesPath = join105(VOICES_DIR, "voices-v1.0.bin");
150655
+ if (existsSync96(voicesPath)) return voicesPath;
150656
+ mkdirSync49(VOICES_DIR, { recursive: true });
149872
150657
  options?.onProgress?.("Downloading voice data (~27 MB)...");
149873
150658
  await downloadFile(VOICES_URL, voicesPath);
149874
- if (!existsSync94(voicesPath)) {
150659
+ if (!existsSync96(voicesPath)) {
149875
150660
  throw new Error("Voice data download failed");
149876
150661
  }
149877
150662
  return voicesPath;
149878
150663
  }
149879
- var CACHE_DIR3, MODELS_DIR3, VOICES_DIR, DEFAULT_MODEL4, MODEL_URLS2, VOICES_URL, SUPPORTED_LANGS, VOICE_PREFIX_LANG, BUNDLED_VOICES, DEFAULT_VOICE;
150664
+ var CACHE_DIR3, MODELS_DIR4, VOICES_DIR, DEFAULT_MODEL4, MODEL_URLS2, VOICES_URL, SUPPORTED_LANGS, VOICE_PREFIX_LANG, BUNDLED_VOICES, DEFAULT_VOICE;
149880
150665
  var init_manager4 = __esm({
149881
150666
  "src/tts/manager.ts"() {
149882
150667
  "use strict";
149883
150668
  init_download();
149884
- CACHE_DIR3 = join103(homedir18(), ".cache", "hyperframes", "tts");
149885
- MODELS_DIR3 = join103(CACHE_DIR3, "models");
149886
- VOICES_DIR = join103(CACHE_DIR3, "voices");
150669
+ CACHE_DIR3 = join105(homedir20(), ".cache", "hyperframes", "tts");
150670
+ MODELS_DIR4 = join105(CACHE_DIR3, "models");
150671
+ VOICES_DIR = join105(CACHE_DIR3, "voices");
149887
150672
  DEFAULT_MODEL4 = "kokoro-v1.0";
149888
150673
  MODEL_URLS2 = {
149889
150674
  "kokoro-v1.0": "https://github.com/thewh1teagle/kokoro-onnx/releases/download/model-files-v1.0/kokoro-v1.0.onnx"
@@ -150012,19 +150797,19 @@ __export(synthesize_exports, {
150012
150797
  synthesize: () => synthesize
150013
150798
  });
150014
150799
  import { execFileSync as execFileSync14 } from "child_process";
150015
- import { existsSync as existsSync95, writeFileSync as writeFileSync38, mkdirSync as mkdirSync48, readdirSync as readdirSync31, unlinkSync as unlinkSync8 } from "fs";
150016
- import { join as join104, dirname as dirname50, basename as basename20 } from "path";
150017
- import { homedir as homedir19 } from "os";
150800
+ import { existsSync as existsSync97, writeFileSync as writeFileSync39, mkdirSync as mkdirSync50, readdirSync as readdirSync31, unlinkSync as unlinkSync9 } from "fs";
150801
+ import { join as join106, dirname as dirname50, basename as basename20 } from "path";
150802
+ import { homedir as homedir21 } from "os";
150018
150803
  function ensureSynthScript() {
150019
- if (!existsSync95(SCRIPT_PATH)) {
150020
- mkdirSync48(SCRIPT_DIR, { recursive: true });
150021
- writeFileSync38(SCRIPT_PATH, SYNTH_SCRIPT);
150804
+ if (!existsSync97(SCRIPT_PATH)) {
150805
+ mkdirSync50(SCRIPT_DIR, { recursive: true });
150806
+ writeFileSync39(SCRIPT_PATH, SYNTH_SCRIPT);
150022
150807
  const currentName = basename20(SCRIPT_PATH);
150023
150808
  try {
150024
150809
  for (const entry of readdirSync31(SCRIPT_DIR)) {
150025
150810
  if (entry !== currentName && /^synth(-v\d+)?\.py$/.test(entry)) {
150026
150811
  try {
150027
- unlinkSync8(join104(SCRIPT_DIR, entry));
150812
+ unlinkSync9(join106(SCRIPT_DIR, entry));
150028
150813
  } catch {
150029
150814
  }
150030
150815
  }
@@ -150058,7 +150843,7 @@ async function synthesize(text2, outputPath, options) {
150058
150843
  ensureVoices({ onProgress: options?.onProgress })
150059
150844
  ]);
150060
150845
  const scriptPath = ensureSynthScript();
150061
- mkdirSync48(dirname50(outputPath), { recursive: true });
150846
+ mkdirSync50(dirname50(outputPath), { recursive: true });
150062
150847
  options?.onProgress?.(`Generating speech with voice ${voice} (${lang})...`);
150063
150848
  try {
150064
150849
  const espeakLang = ESPEAK_LANG_OVERRIDES[lang] ?? lang;
@@ -150071,7 +150856,7 @@ async function synthesize(text2, outputPath, options) {
150071
150856
  stdio: ["pipe", "pipe", "pipe"]
150072
150857
  }
150073
150858
  );
150074
- if (!existsSync95(outputPath)) {
150859
+ if (!existsSync97(outputPath)) {
150075
150860
  throw new Error("Synthesis completed but no output file was created");
150076
150861
  }
150077
150862
  const lines = stdout2.trim().split("\n");
@@ -150084,7 +150869,7 @@ async function synthesize(text2, outputPath, options) {
150084
150869
  langApplied: result.langApplied
150085
150870
  };
150086
150871
  } catch (err) {
150087
- if (err instanceof SyntaxError && existsSync95(outputPath)) {
150872
+ if (err instanceof SyntaxError && existsSync97(outputPath)) {
150088
150873
  throw new Error(
150089
150874
  "Speech was generated but metadata could not be read. Check the output file manually."
150090
150875
  );
@@ -150139,8 +150924,8 @@ print(json.dumps({
150139
150924
  ESPEAK_LANG_OVERRIDES = {
150140
150925
  zh: "cmn"
150141
150926
  };
150142
- SCRIPT_DIR = join104(homedir19(), ".cache", "hyperframes", "tts");
150143
- SCRIPT_PATH = join104(SCRIPT_DIR, "synth-v2.py");
150927
+ SCRIPT_DIR = join106(homedir21(), ".cache", "hyperframes", "tts");
150928
+ SCRIPT_PATH = join106(SCRIPT_DIR, "synth-v2.py");
150144
150929
  }
150145
150930
  });
150146
150931
 
@@ -150150,7 +150935,7 @@ __export(tts_exports, {
150150
150935
  default: () => tts_default,
150151
150936
  examples: () => examples22
150152
150937
  });
150153
- import { existsSync as existsSync96, readFileSync as readFileSync64 } from "fs";
150938
+ import { existsSync as existsSync98, readFileSync as readFileSync67 } from "fs";
150154
150939
  import { resolve as resolve63, extname as extname18 } from "path";
150155
150940
  function listVoices(json) {
150156
150941
  const rows = BUNDLED_VOICES.map((v2) => ({ ...v2, defaultLang: inferLangFromVoiceId(v2.id) }));
@@ -150267,8 +151052,8 @@ var init_tts = __esm({
150267
151052
  }
150268
151053
  let text2;
150269
151054
  const maybeFile = resolve63(input2);
150270
- if (existsSync96(maybeFile) && extname18(maybeFile).toLowerCase() === ".txt") {
150271
- text2 = readFileSync64(maybeFile, "utf-8").trim();
151055
+ if (existsSync98(maybeFile) && extname18(maybeFile).toLowerCase() === ".txt") {
151056
+ text2 = readFileSync67(maybeFile, "utf-8").trim();
150272
151057
  if (!text2) {
150273
151058
  console.error(c.error("File is empty."));
150274
151059
  failCommand();
@@ -150360,15 +151145,15 @@ __export(docs_exports, {
150360
151145
  default: () => docs_default,
150361
151146
  examples: () => examples23
150362
151147
  });
150363
- import { readFileSync as readFileSync65, existsSync as existsSync97 } from "fs";
150364
- import { resolve as resolve64, dirname as dirname51, join as join105 } from "path";
151148
+ import { readFileSync as readFileSync68, existsSync as existsSync99 } from "fs";
151149
+ import { resolve as resolve64, dirname as dirname51, join as join107 } from "path";
150365
151150
  import { fileURLToPath as fileURLToPath14 } from "url";
150366
151151
  function docsDir() {
150367
151152
  const thisFile = fileURLToPath14(import.meta.url);
150368
151153
  const dir = dirname51(thisFile);
150369
151154
  const devPath = resolve64(dir, "..", "docs");
150370
151155
  const builtPath = resolve64(dir, "docs");
150371
- return existsSync97(devPath) ? devPath : builtPath;
151156
+ return existsSync99(devPath) ? devPath : builtPath;
150372
151157
  }
150373
151158
  function formatInlineCode(line2) {
150374
151159
  return line2.replace(/`([^`]+)`/g, (_match, code) => c.accent(code));
@@ -150466,12 +151251,12 @@ var init_docs = __esm({
150466
151251
  }
150467
151252
  failCommand();
150468
151253
  }
150469
- const filePath = join105(docsDir(), entry.file);
150470
- if (!existsSync97(filePath)) {
151254
+ const filePath = join107(docsDir(), entry.file);
151255
+ if (!existsSync99(filePath)) {
150471
151256
  console.error(c.error(`Doc file not found: ${filePath}`));
150472
151257
  failCommand();
150473
151258
  }
150474
- const content = readFileSync65(filePath, "utf-8");
151259
+ const content = readFileSync68(filePath, "utf-8");
150475
151260
  console.log();
150476
151261
  renderMarkdown(content);
150477
151262
  }
@@ -150545,7 +151330,7 @@ __export(doctor_exports, {
150545
151330
  redactHome: () => redactHome
150546
151331
  });
150547
151332
  import { execFileSync as execFileSync15, execSync as execSync5 } from "child_process";
150548
- import { existsSync as existsSync98 } from "fs";
151333
+ import { existsSync as existsSync100 } from "fs";
150549
151334
  import { platform as platform9 } from "os";
150550
151335
  import { dirname as dirname52 } from "path";
150551
151336
  function checkDocker() {
@@ -150635,7 +151420,7 @@ function checkDisk2() {
150635
151420
  }
150636
151421
  return { ok: true, detail: `${freeGb} GB free` };
150637
151422
  }
150638
- function checkFramesCache(env = process.env, freeDiskMb = getFreeDiskMb, fileExists = existsSync98) {
151423
+ function checkFramesCache(env = process.env, freeDiskMb = getFreeDiskMb, fileExists = existsSync100) {
150639
151424
  const resolution = resolveExtractCacheDir(env);
150640
151425
  if (resolution.disabled) {
150641
151426
  return {
@@ -150869,7 +151654,7 @@ __export(upgrade_exports, {
150869
151654
  upgradeProjectPins: () => upgradeProjectPins
150870
151655
  });
150871
151656
  import { execFileSync as execFileSync16 } from "child_process";
150872
- import { existsSync as existsSync99, readFileSync as readFileSync66, writeFileSync as writeFileSync39, renameSync as renameSync14 } from "fs";
151657
+ import { existsSync as existsSync101, readFileSync as readFileSync69, writeFileSync as writeFileSync40, renameSync as renameSync14 } from "fs";
150873
151658
  import { resolve as resolve65 } from "path";
150874
151659
  async function confirmUpgrade() {
150875
151660
  const shouldUpgrade = await ue({ message: "Upgrade now?" });
@@ -150929,10 +151714,10 @@ function resolveProjectArgs(project, opts) {
150929
151714
  }
150930
151715
  async function upgradeProjectPins(dir, opts) {
150931
151716
  const pkgPath = resolve65(dir, "package.json");
150932
- if (!existsSync99(pkgPath)) {
151717
+ if (!existsSync101(pkgPath)) {
150933
151718
  return { changed: false, from: [], to: "", path: pkgPath };
150934
151719
  }
150935
- const raw = JSON.parse(readFileSync66(pkgPath, "utf-8"));
151720
+ const raw = JSON.parse(readFileSync69(pkgPath, "utf-8"));
150936
151721
  const scripts = raw.scripts ?? {};
150937
151722
  const { latest } = await checkForUpdate(true);
150938
151723
  if (!isSafeVersion(latest)) return { changed: false, from: [], to: latest, path: pkgPath };
@@ -150940,14 +151725,14 @@ async function upgradeProjectPins(dir, opts) {
150940
151725
  if (rewrite.changed && !opts.check) {
150941
151726
  raw.scripts = rewrite.scripts;
150942
151727
  const tmp = `${pkgPath}.tmp`;
150943
- writeFileSync39(tmp, `${JSON.stringify(raw, null, 2)}
151728
+ writeFileSync40(tmp, `${JSON.stringify(raw, null, 2)}
150944
151729
  `, "utf-8");
150945
151730
  renameSync14(tmp, pkgPath);
150946
151731
  }
150947
151732
  return { changed: rewrite.changed, from: rewrite.fromVersions, to: latest, path: pkgPath };
150948
151733
  }
150949
151734
  function printProjectPinResult(res, checkOnly) {
150950
- if (!existsSync99(res.path)) {
151735
+ if (!existsSync101(res.path)) {
150951
151736
  console.log(` ${c.dim("No package.json found \u2014 nothing to upgrade.")}`);
150952
151737
  return;
150953
151738
  }
@@ -151095,13 +151880,13 @@ function normalizeRepoUrl(repoUrl) {
151095
151880
  const trimmed = repoUrl.trim().replace(/\/$/, "").replace(/\.git$/, "");
151096
151881
  return trimmed || HYPERFRAMES_REPO_URL;
151097
151882
  }
151098
- function truncate(value, max) {
151883
+ function truncate2(value, max) {
151099
151884
  return value.length > max ? `${value.slice(0, max - 1)}\u2026` : value;
151100
151885
  }
151101
151886
  function buildIssueTitle(rating, comment) {
151102
151887
  const firstLine = comment?.split("\n")[0]?.trim();
151103
151888
  if (!firstLine) return `Render feedback (rating ${rating}/${FEEDBACK_RATING_SCALE})`;
151104
- return `[feedback] ${truncate(firstLine, TITLE_MAX)}`;
151889
+ return `[feedback] ${truncate2(firstLine, TITLE_MAX)}`;
151105
151890
  }
151106
151891
  function buildIssueBody(input2) {
151107
151892
  const comment = input2.comment?.trim();
@@ -151110,7 +151895,7 @@ function buildIssueBody(input2) {
151110
151895
  `**Rating:** ${input2.rating}/${FEEDBACK_RATING_SCALE}`,
151111
151896
  "",
151112
151897
  "## Comment",
151113
- comment ? truncate(comment, COMMENT_MAX) : "_No comment provided._",
151898
+ comment ? truncate2(comment, COMMENT_MAX) : "_No comment provided._",
151114
151899
  "",
151115
151900
  "## Minimal repro",
151116
151901
  repro,
@@ -151209,7 +151994,7 @@ __export(feedback_exports, {
151209
151994
  default: () => feedback_default,
151210
151995
  examples: () => examples26
151211
151996
  });
151212
- import { randomUUID as randomUUID11 } from "crypto";
151997
+ import { randomUUID as randomUUID12 } from "crypto";
151213
151998
  import { resolve as resolve66 } from "path";
151214
151999
  import open from "open";
151215
152000
  function normalizeComment(raw) {
@@ -151362,7 +152147,7 @@ var init_feedback2 = __esm({
151362
152147
  }
151363
152148
  const comment = normalizeComment(args.comment);
151364
152149
  const doctorSummary = await getDoctorSummary();
151365
- const feedbackId = randomUUID11();
152150
+ const feedbackId = randomUUID12();
151366
152151
  const config = readConfig();
151367
152152
  const joinKeys = buildTelemetryJoinKeys({
151368
152153
  feedbackId,
@@ -151587,8 +152372,8 @@ __export(contactSheet_exports, {
151587
152372
  createSvgContactSheet: () => createSvgContactSheet
151588
152373
  });
151589
152374
  import sharp from "sharp";
151590
- import { readdirSync as readdirSync33, readFileSync as readFileSync67, writeFileSync as writeFileSync40, unlinkSync as unlinkSync9, existsSync as existsSync100 } from "fs";
151591
- import { join as join106, extname as extname19, basename as basename21, dirname as dirname53 } from "path";
152375
+ import { readdirSync as readdirSync33, readFileSync as readFileSync70, writeFileSync as writeFileSync41, unlinkSync as unlinkSync10, existsSync as existsSync103 } from "fs";
152376
+ import { join as join108, extname as extname19, basename as basename21, dirname as dirname53 } from "path";
151592
152377
  async function createContactSheet(imagePaths, outputPath, opts = {}) {
151593
152378
  const {
151594
152379
  cols = 3,
@@ -151674,10 +152459,10 @@ async function createContactSheetPages(imagePaths, outputBasePath, opts = {}, la
151674
152459
  return results;
151675
152460
  }
151676
152461
  async function createScrollContactSheet(screenshotsDir, outputPath, budget = {}) {
151677
- if (!existsSync100(screenshotsDir)) return [];
152462
+ if (!existsSync103(screenshotsDir)) return [];
151678
152463
  const scrollFiles = readdirSync33(screenshotsDir).filter((f3) => f3.startsWith("scroll-") && f3.endsWith(".png")).sort();
151679
152464
  if (scrollFiles.length === 0) return [];
151680
- const paths = scrollFiles.map((f3) => join106(screenshotsDir, f3));
152465
+ const paths = scrollFiles.map((f3) => join108(screenshotsDir, f3));
151681
152466
  const labels = scrollFiles.map((f3) => {
151682
152467
  const m2 = f3.match(/scroll-(\d+)\.png/);
151683
152468
  return m2 ? `${m2[1]}% scroll` : f3;
@@ -151691,10 +152476,10 @@ async function createScrollContactSheet(screenshotsDir, outputPath, budget = {})
151691
152476
  );
151692
152477
  }
151693
152478
  async function createSnapshotContactSheet(snapshotsDir, outputPath, budget = {}) {
151694
- if (!existsSync100(snapshotsDir)) return [];
152479
+ if (!existsSync103(snapshotsDir)) return [];
151695
152480
  const snapshotFiles = readdirSync33(snapshotsDir).filter((f3) => f3.startsWith("frame-") && f3.endsWith(".png")).sort();
151696
152481
  if (snapshotFiles.length === 0) return [];
151697
- const paths = snapshotFiles.map((f3) => join106(snapshotsDir, f3));
152482
+ const paths = snapshotFiles.map((f3) => join108(snapshotsDir, f3));
151698
152483
  const labels = snapshotFiles.map((f3) => {
151699
152484
  const m2 = f3.match(/at-([\d.]+)s/);
151700
152485
  return m2 ? `${m2[1]}s` : f3;
@@ -151708,11 +152493,11 @@ async function createSnapshotContactSheet(snapshotsDir, outputPath, budget = {})
151708
152493
  );
151709
152494
  }
151710
152495
  async function createAssetContactSheet(assetsDir, outputPath, budget = {}) {
151711
- if (!existsSync100(assetsDir)) return [];
152496
+ if (!existsSync103(assetsDir)) return [];
151712
152497
  const imageExts = /* @__PURE__ */ new Set([".png", ".jpg", ".jpeg", ".webp"]);
151713
152498
  const assetFiles = readdirSync33(assetsDir).filter((f3) => imageExts.has(extname19(f3).toLowerCase()) && !f3.includes("contact-sheet")).sort();
151714
152499
  if (assetFiles.length === 0) return [];
151715
- const paths = assetFiles.map((f3) => join106(assetsDir, f3));
152500
+ const paths = assetFiles.map((f3) => join108(assetsDir, f3));
151716
152501
  return createContactSheetPages(paths, outputPath, {
151717
152502
  cols: 4,
151718
152503
  cellWidth: 480,
@@ -151723,7 +152508,7 @@ async function createAssetContactSheet(assetsDir, outputPath, budget = {}) {
151723
152508
  }
151724
152509
  async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir, budget = {}) {
151725
152510
  const dirsToScan = [svgsDir, assetsRootDir].filter(
151726
- (d2) => d2 !== void 0 && existsSync100(d2)
152511
+ (d2) => d2 !== void 0 && existsSync103(d2)
151727
152512
  );
151728
152513
  if (dirsToScan.length === 0) return [];
151729
152514
  const seen = /* @__PURE__ */ new Set();
@@ -151732,7 +152517,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir, budget
151732
152517
  for (const f3 of readdirSync33(dir).filter((f4) => f4.endsWith(".svg")).sort()) {
151733
152518
  if (!seen.has(f3)) {
151734
152519
  seen.add(f3);
151735
- svgPaths.push(join106(dir, f3));
152520
+ svgPaths.push(join108(dir, f3));
151736
152521
  }
151737
152522
  }
151738
152523
  }
@@ -151745,14 +152530,14 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir, budget
151745
152530
  for (let i2 = 0; i2 < svgPaths.length; i2++) {
151746
152531
  if ((budget.remainingMs?.() ?? 1) <= 0) break;
151747
152532
  const svgPath = svgPaths[i2];
151748
- const tmpPath = join106(tmpDir, `.thumb-${i2}.png`);
152533
+ const tmpPath = join108(tmpDir, `.thumb-${i2}.png`);
151749
152534
  try {
151750
- const svgBuf = readFileSync67(svgPath);
152535
+ const svgBuf = readFileSync70(svgPath);
151751
152536
  const thumb = await sharp(svgBuf).resize(thumbSize, thumbSize, {
151752
152537
  fit: "contain",
151753
152538
  background: { r: 245, g: 245, b: 245, alpha: 1 }
151754
152539
  }).flatten({ background: { r: 245, g: 245, b: 245 } }).png().toBuffer();
151755
- writeFileSync40(tmpPath, thumb);
152540
+ writeFileSync41(tmpPath, thumb);
151756
152541
  tmpPaths.push(tmpPath);
151757
152542
  labels.push(svgFileNames[i2].replace(".svg", ""));
151758
152543
  } catch {
@@ -151776,7 +152561,7 @@ async function createSvgContactSheet(svgsDir, outputPath, assetsRootDir, budget
151776
152561
  } finally {
151777
152562
  for (const tmp of tmpPaths) {
151778
152563
  try {
151779
- unlinkSync9(tmp);
152564
+ unlinkSync10(tmp);
151780
152565
  } catch {
151781
152566
  }
151782
152567
  }
@@ -159667,7 +160452,7 @@ var require_gaxios = __commonJS({
159667
160452
  var retry_js_1 = require_retry3();
159668
160453
  var stream_1 = __require("stream");
159669
160454
  var interceptor_js_1 = require_interceptor();
159670
- var randomUUID12 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
160455
+ var randomUUID13 = async () => globalThis.crypto?.randomUUID() || (await import("crypto")).randomUUID();
159671
160456
  var HTTP_STATUS_NO_CONTENT = 204;
159672
160457
  var Gaxios = class {
159673
160458
  agentCache = /* @__PURE__ */ new Map();
@@ -159940,7 +160725,7 @@ var require_gaxios = __commonJS({
159940
160725
  */
159941
160726
  ["Blob", "File", "FormData"].includes(opts.data?.constructor?.name || "");
159942
160727
  if (opts.multipart?.length) {
159943
- const boundary = await randomUUID12();
160728
+ const boundary = await randomUUID13();
159944
160729
  preparedHeaders.set("content-type", `multipart/related; boundary=${boundary}`);
159945
160730
  opts.body = stream_1.Readable.from(this.getMultipartRequest(opts.multipart, boundary));
159946
160731
  } else if (shouldDirectlyPassData) {
@@ -171752,7 +172537,7 @@ var require_websocket = __commonJS({
171752
172537
  var http4 = __require("http");
171753
172538
  var net2 = __require("net");
171754
172539
  var tls = __require("tls");
171755
- var { randomBytes: randomBytes4, createHash: createHash21 } = __require("crypto");
172540
+ var { randomBytes: randomBytes4, createHash: createHash23 } = __require("crypto");
171756
172541
  var { Duplex, Readable: Readable5 } = __require("stream");
171757
172542
  var { URL: URL2 } = __require("url");
171758
172543
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -172412,7 +173197,7 @@ var require_websocket = __commonJS({
172412
173197
  abortHandshake(websocket, socket, "Invalid Upgrade header");
172413
173198
  return;
172414
173199
  }
172415
- const digest = createHash21("sha1").update(key2 + GUID).digest("base64");
173200
+ const digest = createHash23("sha1").update(key2 + GUID).digest("base64");
172416
173201
  if (res.headers["sec-websocket-accept"] !== digest) {
172417
173202
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
172418
173203
  return;
@@ -172779,7 +173564,7 @@ var require_websocket_server = __commonJS({
172779
173564
  var EventEmitter = __require("events");
172780
173565
  var http4 = __require("http");
172781
173566
  var { Duplex } = __require("stream");
172782
- var { createHash: createHash21 } = __require("crypto");
173567
+ var { createHash: createHash23 } = __require("crypto");
172783
173568
  var extension2 = require_extension();
172784
173569
  var PerMessageDeflate2 = require_permessage_deflate();
172785
173570
  var subprotocol2 = require_subprotocol();
@@ -173080,7 +173865,7 @@ var require_websocket_server = __commonJS({
173080
173865
  );
173081
173866
  }
173082
173867
  if (this._state > RUNNING) return abortHandshake(socket, 503);
173083
- const digest = createHash21("sha1").update(key2 + GUID).digest("base64");
173868
+ const digest = createHash23("sha1").update(key2 + GUID).digest("base64");
173084
173869
  const headers = [
173085
173870
  "HTTP/1.1 101 Switching Protocols",
173086
173871
  "Upgrade: websocket",
@@ -191532,9 +192317,9 @@ __export(snapshot_exports, {
191532
192317
  resolveSnapshotVideoFrameTime: () => resolveSnapshotVideoFrameTime,
191533
192318
  tailFrameTime: () => tailFrameTime
191534
192319
  });
191535
- import { existsSync as existsSync101, mkdtempSync as mkdtempSync15, readFileSync as readFileSync68, mkdirSync as mkdirSync49, rmSync as rmSync30, writeFileSync as writeFileSync41 } from "fs";
192320
+ import { existsSync as existsSync104, mkdtempSync as mkdtempSync15, readFileSync as readFileSync71, mkdirSync as mkdirSync51, rmSync as rmSync30, writeFileSync as writeFileSync43 } from "fs";
191536
192321
  import { tmpdir as tmpdir15 } from "os";
191537
- import { resolve as resolve67, join as join107, relative as relative24, isAbsolute as isAbsolute15, basename as basename25 } from "path";
192322
+ import { resolve as resolve67, join as join109, relative as relative24, isAbsolute as isAbsolute15, basename as basename25 } from "path";
191538
192323
  function orbitStageSource() {
191539
192324
  return `function(cam) {
191540
192325
  var root = document.querySelector("[data-composition-id]")
@@ -191580,8 +192365,8 @@ function requireSnapshotFfmpeg(ffmpegPath) {
191580
192365
  );
191581
192366
  }
191582
192367
  async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDecoder = false) {
191583
- const tmp = mkdtempSync15(join107(tmpdir15(), "hf-snapshot-frame-"));
191584
- const outPath = join107(tmp, "frame.png");
192368
+ const tmp = mkdtempSync15(join109(tmpdir15(), "hf-snapshot-frame-"));
192369
+ const outPath = join109(tmp, "frame.png");
191585
192370
  try {
191586
192371
  const ffmpegPath = requireSnapshotFfmpeg(findFFmpeg());
191587
192372
  const args = ["-hide_banner", "-loglevel", "error"];
@@ -191601,8 +192386,8 @@ async function extractVideoFrameToBuffer(videoPath, timeSeconds, useVp9AlphaDeco
191601
192386
  outPath
191602
192387
  );
191603
192388
  const result = await runFfmpegOnce(ffmpegPath, args, FFMPEG_EXTRACT_TIMEOUT_MS);
191604
- if (result.code !== 0 || result.timedOut || !existsSync101(outPath)) return null;
191605
- return readFileSync68(outPath);
192389
+ if (result.code !== 0 || result.timedOut || !existsSync104(outPath)) return null;
192390
+ return readFileSync71(outPath);
191606
192391
  } finally {
191607
192392
  try {
191608
192393
  rmSync30(tmp, { recursive: true, force: true });
@@ -191694,13 +192479,13 @@ async function captureSnapshots(projectDir, opts) {
191694
192479
  );
191695
192480
  }
191696
192481
  const cameraExpr = opts.angle && (opts.angle.yaw !== 0 || opts.angle.pitch !== 0) ? `(${orbitStageSource()})(${JSON.stringify(opts.angle)})` : null;
191697
- const snapshotDir = opts.outputDir ?? join107(projectDir, "snapshots");
191698
- mkdirSync49(snapshotDir, { recursive: true });
192482
+ const snapshotDir = opts.outputDir ?? join109(projectDir, "snapshots");
192483
+ mkdirSync51(snapshotDir, { recursive: true });
191699
192484
  try {
191700
192485
  const { readdirSync: readdirSync39 } = await import("fs");
191701
192486
  for (const file of readdirSync39(snapshotDir)) {
191702
192487
  if (/\.(png|jpg|jpeg)$/i.test(file)) {
191703
- rmSync30(join107(snapshotDir, file), { force: true });
192488
+ rmSync30(join109(snapshotDir, file), { force: true });
191704
192489
  }
191705
192490
  }
191706
192491
  } catch {
@@ -191786,7 +192571,7 @@ async function captureSnapshots(projectDir, opts) {
191786
192571
  const decodedPath = decodeURIComponent(url.pathname).replace(/^\//, "");
191787
192572
  const candidate = resolve67(projectDir, decodedPath);
191788
192573
  const rel2 = relative24(projectDir, candidate);
191789
- if (!rel2.startsWith("..") && !isAbsolute15(rel2) && existsSync101(candidate)) {
192574
+ if (!rel2.startsWith("..") && !isAbsolute15(rel2) && existsSync104(candidate)) {
191790
192575
  ffmpegInput = candidate;
191791
192576
  inputIsLocal = true;
191792
192577
  } else if (url.protocol === "http:" || url.protocol === "https:") {
@@ -191829,7 +192614,7 @@ async function captureSnapshots(projectDir, opts) {
191829
192614
  }
191830
192615
  const timeLabel = formatSnapshotTimestamp(time);
191831
192616
  const filename = `frame-${String(i2).padStart(2, "0")}-at-${timeLabel}.png`;
191832
- const framePath = join107(snapshotDir, filename);
192617
+ const framePath = join109(snapshotDir, filename);
191833
192618
  if (opts.zoom) {
191834
192619
  const canvas = await page.evaluate(() => ({
191835
192620
  width: window.innerWidth,
@@ -191847,7 +192632,7 @@ async function captureSnapshots(projectDir, opts) {
191847
192632
  region,
191848
192633
  opts.zoomScale ?? DEFAULT_ZOOM_SCALE
191849
192634
  );
191850
- writeFileSync41(framePath, buffer);
192635
+ writeFileSync43(framePath, buffer);
191851
192636
  } else {
191852
192637
  await page.screenshot({ path: framePath, type: "png", omitBackground: true });
191853
192638
  }
@@ -191963,7 +192748,7 @@ var init_snapshot = __esm({
191963
192748
  const angleLabel = camera && (camera.yaw !== 0 || camera.pitch !== 0) ? ` ${c.dim(`(angle yaw ${camera.yaw}\xB0 pitch ${camera.pitch}\xB0)`)}` : "";
191964
192749
  console.log(`${c.accent("\u25C6")} Capturing ${label2} from ${c.accent(project.name)}${angleLabel}`);
191965
192750
  try {
191966
- const snapshotDir = args.output ? resolve67(String(args.output)) : join107(project.dir, "snapshots");
192751
+ const snapshotDir = args.output ? resolve67(String(args.output)) : join109(project.dir, "snapshots");
191967
192752
  const paths = await captureSnapshots(project.dir, {
191968
192753
  frames,
191969
192754
  timeout,
@@ -191994,7 +192779,7 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
191994
192779
  const { createSnapshotContactSheet: createSnapshotContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
191995
192780
  const sheets = await createSnapshotContactSheet2(
191996
192781
  snapshotDir,
191997
- join107(snapshotDir, "contact-sheet.jpg")
192782
+ join109(snapshotDir, "contact-sheet.jpg")
191998
192783
  );
191999
192784
  if (sheets.length > 0) {
192000
192785
  const label3 = sheets.length === 1 ? "contact-sheet.jpg" : `contact-sheet-1..${sheets.length}.jpg`;
@@ -192030,9 +192815,9 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
192030
192815
  const results = await Promise.allSettled(
192031
192816
  paths.map(async (p2) => {
192032
192817
  const filename = basename25(p2);
192033
- const filePath = join107(snapshotDir, filename);
192034
- if (!existsSync101(filePath)) return { filename, desc: "file not found" };
192035
- const raw = readFileSync68(filePath);
192818
+ const filePath = join109(snapshotDir, filename);
192819
+ if (!existsSync104(filePath)) return { filename, desc: "file not found" };
192820
+ const raw = readFileSync71(filePath);
192036
192821
  let imageData;
192037
192822
  let mimeType = "image/png";
192038
192823
  if (sharpFn) {
@@ -192068,8 +192853,8 @@ ${c.success("\u25C7")} ${paths.length} snapshots saved to ${args.output ? snaps
192068
192853
  descriptions.push(`## (error)`, `Gemini call failed: ${errMsg.slice(0, 120)}`, ``);
192069
192854
  }
192070
192855
  }
192071
- const descPath = join107(snapshotDir, "descriptions.md");
192072
- writeFileSync41(descPath, descriptions.join("\n"));
192856
+ const descPath = join109(snapshotDir, "descriptions.md");
192857
+ writeFileSync43(descPath, descriptions.join("\n"));
192073
192858
  console.log(` ${c.dim("descriptions.md")} (Gemini frame analysis)`);
192074
192859
  }
192075
192860
  } catch (descErr) {
@@ -192401,8 +193186,8 @@ __export(media_treatment_exports, {
192401
193186
  mediaTreatmentCommand: () => mediaTreatmentCommand,
192402
193187
  resolveMediaTreatmentSource: () => resolveMediaTreatmentSource
192403
193188
  });
192404
- import { existsSync as existsSync103, readFileSync as readFileSync69, writeFileSync as writeFileSync43 } from "fs";
192405
- import { join as join108, relative as relative26, resolve as resolve69 } from "path";
193189
+ import { existsSync as existsSync105, readFileSync as readFileSync73, writeFileSync as writeFileSync44 } from "fs";
193190
+ import { join as join110, relative as relative26, resolve as resolve69 } from "path";
192406
193191
  function getMediaTreatmentCapabilityOverview() {
192407
193192
  const capabilities = getHfColorGradingCapabilities();
192408
193193
  const family = (id, label2, description) => ({
@@ -192780,7 +193565,7 @@ function resolveMediaTreatmentSource(projectDir, compositionFile, source) {
192780
193565
  }
192781
193566
  const cleanSource = cleanAssetUrl(sourceUrl);
192782
193567
  if (!cleanSource) throw new Error("Selected media has no analyzable local src");
192783
- const projectRelative = cleanSource.startsWith("/") ? cleanSource : rewriteAssetPath(compositionFile, cleanSource, (path2) => existsSync103(join108(projectDir, path2)));
193568
+ const projectRelative = cleanSource.startsWith("/") ? cleanSource : rewriteAssetPath(compositionFile, cleanSource, (path2) => existsSync105(join110(projectDir, path2)));
192784
193569
  const asset = resolveExistingLocalAsset(projectDir, projectRelative);
192785
193570
  if (!asset) throw new Error(`Media file not found: ${source}`);
192786
193571
  return asset.resolved;
@@ -192833,7 +193618,7 @@ function resolveMutationFile(args) {
192833
193618
  if (!isPathInside(filePath, project.dir) || !filePath.toLowerCase().endsWith(".html")) {
192834
193619
  throw new Error("--file must be an HTML file inside the project");
192835
193620
  }
192836
- if (!existsSync103(filePath)) throw new Error(`Composition file not found: ${fileArg}`);
193621
+ if (!existsSync105(filePath)) throw new Error(`Composition file not found: ${fileArg}`);
192837
193622
  return { project, filePath };
192838
193623
  }
192839
193624
  function analyzeTarget(args) {
@@ -192845,7 +193630,7 @@ function analyzeTarget(args) {
192845
193630
  }
192846
193631
  const selectorIndex = parseSelectorIndex(readOptionalString(args["selector-index"]));
192847
193632
  const { element, tag } = selectMediaElement(
192848
- readFileSync69(filePath, "utf8"),
193633
+ readFileSync73(filePath, "utf8"),
192849
193634
  selector,
192850
193635
  selectorIndex
192851
193636
  );
@@ -192870,14 +193655,14 @@ function prepareMutation(args) {
192870
193655
  const clear = args.clear === true;
192871
193656
  const apply = args.apply === true;
192872
193657
  const selectorIndex = parseSelectorIndex(readOptionalString(args["selector-index"]));
192873
- const result = applyMediaTreatmentToHtml(readFileSync69(filePath, "utf8"), {
193658
+ const result = applyMediaTreatmentToHtml(readFileSync73(filePath, "utf8"), {
192874
193659
  selector,
192875
193660
  selectorIndex,
192876
193661
  grading: parseGrading(readOptionalString(args.grading), apply, clear),
192877
193662
  clear
192878
193663
  });
192879
193664
  const dryRun = args["dry-run"] === true;
192880
- if (result.changed && !dryRun) writeFileSync43(filePath, result.html);
193665
+ if (result.changed && !dryRun) writeFileSync44(filePath, result.html);
192881
193666
  const action = result.value === null ? "clear" : "apply";
192882
193667
  return {
192883
193668
  action,
@@ -193056,15 +193841,15 @@ __export(grade_compare_exports, {
193056
193841
  });
193057
193842
  import {
193058
193843
  copyFileSync as copyFileSync10,
193059
- existsSync as existsSync104,
193060
- mkdirSync as mkdirSync50,
193844
+ existsSync as existsSync106,
193845
+ mkdirSync as mkdirSync53,
193061
193846
  mkdtempSync as mkdtempSync16,
193062
- readFileSync as readFileSync70,
193847
+ readFileSync as readFileSync74,
193063
193848
  rmSync as rmSync31,
193064
- writeFileSync as writeFileSync44
193849
+ writeFileSync as writeFileSync45
193065
193850
  } from "fs";
193066
193851
  import { tmpdir as tmpdir16 } from "os";
193067
- import { basename as basename27, dirname as dirname54, extname as extname21, join as join109, resolve as resolve70 } from "path";
193852
+ import { basename as basename27, dirname as dirname54, extname as extname21, join as join111, resolve as resolve70 } from "path";
193068
193853
  import sharp2 from "sharp";
193069
193854
  function isRecord13(value) {
193070
193855
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -193150,12 +193935,12 @@ function rewriteGradingLutSrc(grading, src) {
193150
193935
  return next;
193151
193936
  }
193152
193937
  function parseGradesFile(filePath) {
193153
- if (!existsSync104(filePath)) {
193938
+ if (!existsSync106(filePath)) {
193154
193939
  throw new Error(`Grades file not found: ${filePath}`);
193155
193940
  }
193156
193941
  let parsed;
193157
193942
  try {
193158
- parsed = JSON.parse(readFileSync70(filePath, "utf-8"));
193943
+ parsed = JSON.parse(readFileSync74(filePath, "utf-8"));
193159
193944
  } catch (err) {
193160
193945
  throw new Error(`Could not parse grades JSON: ${normalizeErrorMessage(err)}`);
193161
193946
  }
@@ -193320,19 +194105,19 @@ function frameFileNameForPath(framePath) {
193320
194105
  return "frame.png";
193321
194106
  }
193322
194107
  async function prepareGradeCompareTempProject(opts) {
193323
- const tempDir = mkdtempSync16(join109(tmpdir16(), "hf-grade-compare-"));
194108
+ const tempDir = mkdtempSync16(join111(tmpdir16(), "hf-grade-compare-"));
193324
194109
  try {
193325
194110
  const frameFileName2 = opts.frameFileName ?? frameFileNameForPath(opts.framePath);
193326
- writeFileSync44(join109(tempDir, frameFileName2), opts.frameBuffer);
194111
+ writeFileSync45(join111(tempDir, frameFileName2), opts.frameBuffer);
193327
194112
  let lutIndex = 0;
193328
194113
  const stagedCells = opts.cells.map((cell) => {
193329
194114
  const lutSrc = lutSrcFromGrading(cell.grading);
193330
194115
  if (!lutSrc) return cell;
193331
194116
  const sourcePath = resolveFromBase(opts.projectDir, lutSrc);
193332
- if (!existsSync104(sourcePath)) {
194117
+ if (!existsSync106(sourcePath)) {
193333
194118
  throw new Error(`LUT file not found for "${cell.label}": ${sourcePath}`);
193334
194119
  }
193335
- const lutText = readFileSync70(sourcePath, "utf-8");
194120
+ const lutText = readFileSync74(sourcePath, "utf-8");
193336
194121
  try {
193337
194122
  parseCubeLut(lutText, { maxSize: 64 });
193338
194123
  } catch (err) {
@@ -193343,7 +194128,7 @@ async function prepareGradeCompareTempProject(opts) {
193343
194128
  const lutExt = extname21(sourcePath) || ".cube";
193344
194129
  const stagedName = `lut-${lutIndex}${lutExt}`;
193345
194130
  lutIndex += 1;
193346
- copyFileSync10(sourcePath, join109(tempDir, stagedName));
194131
+ copyFileSync10(sourcePath, join111(tempDir, stagedName));
193347
194132
  return {
193348
194133
  label: cell.label,
193349
194134
  grading: rewriteGradingLutSrc(cell.grading, stagedName)
@@ -193355,7 +194140,7 @@ async function prepareGradeCompareTempProject(opts) {
193355
194140
  frameWidth: opts.frameWidth,
193356
194141
  frameHeight: opts.frameHeight
193357
194142
  });
193358
- writeFileSync44(join109(tempDir, "index.html"), html);
194143
+ writeFileSync45(join111(tempDir, "index.html"), html);
193359
194144
  return { tempDir, html, cells: stagedCells };
193360
194145
  } catch (err) {
193361
194146
  rmSync31(tempDir, { recursive: true, force: true });
@@ -193367,8 +194152,8 @@ function isVideoPath2(filePath) {
193367
194152
  return [".mp4", ".mov", ".m4v", ".webm", ".mkv", ".avi", ".mpeg", ".mpg", ".ogv"].includes(ext);
193368
194153
  }
193369
194154
  async function extractVideoFrameToBuffer2(videoPath) {
193370
- const tmp = mkdtempSync16(join109(tmpdir16(), "hf-grade-compare-frame-"));
193371
- const outPath = join109(tmp, "frame.png");
194155
+ const tmp = mkdtempSync16(join111(tmpdir16(), "hf-grade-compare-frame-"));
194156
+ const outPath = join111(tmp, "frame.png");
193372
194157
  try {
193373
194158
  const ffmpegPath = findFFmpeg();
193374
194159
  if (!ffmpegPath) return null;
@@ -193391,20 +194176,20 @@ async function extractVideoFrameToBuffer2(videoPath) {
193391
194176
  if (result.timedOut) {
193392
194177
  throw new Error(`ffmpeg timed out extracting first frame from ${videoPath}`);
193393
194178
  }
193394
- if (result.code !== 0 || !existsSync104(outPath)) {
194179
+ if (result.code !== 0 || !existsSync106(outPath)) {
193395
194180
  const detail = result.stderr.trim() ? `: ${result.stderr.trim()}` : "";
193396
194181
  throw new Error(`ffmpeg could not extract first frame from ${videoPath}${detail}`);
193397
194182
  }
193398
- return readFileSync70(outPath);
194183
+ return readFileSync74(outPath);
193399
194184
  } finally {
193400
194185
  rmSync31(tmp, { recursive: true, force: true });
193401
194186
  }
193402
194187
  }
193403
194188
  async function loadReferenceFrame(framePath) {
193404
- if (!existsSync104(framePath)) {
194189
+ if (!existsSync106(framePath)) {
193405
194190
  throw new Error(`Reference frame not found: ${framePath}`);
193406
194191
  }
193407
- const buffer = isVideoPath2(framePath) ? await extractVideoFrameToBuffer2(framePath) : readFileSync70(framePath);
194192
+ const buffer = isVideoPath2(framePath) ? await extractVideoFrameToBuffer2(framePath) : readFileSync74(framePath);
193408
194193
  if (!buffer) {
193409
194194
  throw new Error(`Could not extract a frame from video: ${framePath}`);
193410
194195
  }
@@ -193423,7 +194208,7 @@ async function captureGradeCompareSheet(projectDir, timeoutMs) {
193423
194208
  const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
193424
194209
  const html = await bundleToSingleHtml2(projectDir);
193425
194210
  const server = await serveStaticProjectHtml(projectDir, html);
193426
- const sheetPath = join109(projectDir, "grade-compare.png");
194211
+ const sheetPath = join111(projectDir, "grade-compare.png");
193427
194212
  try {
193428
194213
  const {
193429
194214
  browser: chromeBrowser,
@@ -193564,7 +194349,7 @@ var init_grade_compare = __esm({
193564
194349
  prepared.tempDir,
193565
194350
  parsed.timeoutMs
193566
194351
  );
193567
- mkdirSync50(dirname54(parsed.outPath), { recursive: true });
194352
+ mkdirSync53(dirname54(parsed.outPath), { recursive: true });
193568
194353
  copyFileSync10(tempSheet, parsed.outPath);
193569
194354
  trackCompareSheet({
193570
194355
  command: "grade-compare",
@@ -193609,9 +194394,9 @@ __export(compare_exports, {
193609
194394
  parseCompareArgs: () => parseCompareArgs,
193610
194395
  prepareCompareVariantProjects: () => prepareCompareVariantProjects
193611
194396
  });
193612
- import { cpSync as cpSync6, existsSync as existsSync105, mkdirSync as mkdirSync51, mkdtempSync as mkdtempSync17, renameSync as renameSync15, rmSync as rmSync33, statSync as statSync36 } from "fs";
194397
+ import { cpSync as cpSync6, existsSync as existsSync107, mkdirSync as mkdirSync54, mkdtempSync as mkdtempSync17, renameSync as renameSync15, rmSync as rmSync33, statSync as statSync36 } from "fs";
193613
194398
  import { tmpdir as tmpdir17 } from "os";
193614
- import { basename as basename28, dirname as dirname55, extname as extname23, join as join110 } from "path";
194399
+ import { basename as basename28, dirname as dirname55, extname as extname23, join as join113 } from "path";
193615
194400
  function defaultLabelForPath(input2) {
193616
194401
  const name = basename28(input2);
193617
194402
  return extname23(name).toLowerCase() === ".html" ? basename28(name, extname23(name)) : name;
@@ -193710,7 +194495,7 @@ function inputError(variant) {
193710
194495
  );
193711
194496
  }
193712
194497
  function stageHtmlVariant(variant) {
193713
- const stagedDir = mkdtempSync17(join110(tmpdir17(), "hf-compare-variant-"));
194498
+ const stagedDir = mkdtempSync17(join113(tmpdir17(), "hf-compare-variant-"));
193714
194499
  try {
193715
194500
  cpSync6(dirname55(variant.inputPath), stagedDir, {
193716
194501
  recursive: true,
@@ -193721,7 +194506,7 @@ function stageHtmlVariant(variant) {
193721
194506
  });
193722
194507
  const sourceName = basename28(variant.inputPath);
193723
194508
  if (sourceName !== "index.html") {
193724
- renameSync15(join110(stagedDir, sourceName), join110(stagedDir, "index.html"));
194509
+ renameSync15(join113(stagedDir, sourceName), join113(stagedDir, "index.html"));
193725
194510
  }
193726
194511
  return {
193727
194512
  ...variant,
@@ -193737,11 +194522,11 @@ function prepareCompareVariantProjects(variants) {
193737
194522
  const prepared = [];
193738
194523
  try {
193739
194524
  for (const variant of variants) {
193740
- if (!existsSync105(variant.inputPath)) {
194525
+ if (!existsSync107(variant.inputPath)) {
193741
194526
  throw inputError(variant);
193742
194527
  }
193743
194528
  const stat3 = statSync36(variant.inputPath);
193744
- if (stat3.isDirectory() && existsSync105(join110(variant.inputPath, "index.html"))) {
194529
+ if (stat3.isDirectory() && existsSync107(join113(variant.inputPath, "index.html"))) {
193745
194530
  prepared.push({
193746
194531
  ...variant,
193747
194532
  projectDir: variant.inputPath
@@ -193807,13 +194592,13 @@ async function renderCompareSheet(parsed) {
193807
194592
  const capResult = capCompareVariants(parsed.variants);
193808
194593
  const variants = capResult.variants;
193809
194594
  const prepared = prepareCompareVariantProjects(variants);
193810
- const frameDir = mkdtempSync17(join110(tmpdir17(), "hf-compare-frames-"));
194595
+ const frameDir = mkdtempSync17(join113(tmpdir17(), "hf-compare-frames-"));
193811
194596
  const framePaths = [];
193812
194597
  try {
193813
194598
  let renderReadyTimedOut = false;
193814
194599
  for (let i2 = 0; i2 < prepared.length; i2++) {
193815
194600
  const variant = prepared[i2];
193816
- const framePath = join110(frameDir, `variant-${String(i2 + 1).padStart(2, "0")}.png`);
194601
+ const framePath = join113(frameDir, `variant-${String(i2 + 1).padStart(2, "0")}.png`);
193817
194602
  const rendered = await renderCompareVariant(variant, {
193818
194603
  atSeconds: parsed.atSeconds,
193819
194604
  framePath,
@@ -193822,7 +194607,7 @@ async function renderCompareSheet(parsed) {
193822
194607
  framePaths.push(rendered.framePath);
193823
194608
  renderReadyTimedOut = renderReadyTimedOut || rendered.renderReadyTimedOut;
193824
194609
  }
193825
- mkdirSync51(dirname55(parsed.outPath), { recursive: true });
194610
+ mkdirSync54(dirname55(parsed.outPath), { recursive: true });
193826
194611
  await createContactSheet(framePaths, parsed.outPath, {
193827
194612
  cols: parsed.cols ?? defaultCompareCols(framePaths.length),
193828
194613
  maxImages: framePaths.length,
@@ -193941,11 +194726,11 @@ ${c.error("\u2717")} Compare failed: ${message}`);
193941
194726
  });
193942
194727
 
193943
194728
  // src/capture/assetDownloader.ts
193944
- import { writeFileSync as writeFileSync45, mkdirSync as mkdirSync53 } from "fs";
193945
- import { join as join111, extname as extname24 } from "path";
193946
- import { createHash as createHash19 } from "crypto";
194729
+ import { writeFileSync as writeFileSync46, mkdirSync as mkdirSync55 } from "fs";
194730
+ import { join as join114, extname as extname24 } from "path";
194731
+ import { createHash as createHash20 } from "crypto";
193947
194732
  function svgContentHashSlug(svgSource, isLogo) {
193948
- const hash2 = createHash19("sha1").update(svgSource).digest("hex").slice(0, 8);
194733
+ const hash2 = createHash20("sha1").update(svgSource).digest("hex").slice(0, 8);
193949
194734
  return isLogo ? `logo-${hash2}` : `svg-${hash2}`;
193950
194735
  }
193951
194736
  function toStandaloneSvg(outerHTML) {
@@ -193963,11 +194748,11 @@ function toStandaloneSvg(outerHTML) {
193963
194748
  return outerHTML.replace(original, tag);
193964
194749
  }
193965
194750
  async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks, options = {}) {
193966
- const assetsDir = join111(outputDir, "assets");
193967
- mkdirSync53(assetsDir, { recursive: true });
194751
+ const assetsDir = join114(outputDir, "assets");
194752
+ mkdirSync55(assetsDir, { recursive: true });
193968
194753
  const assets = [];
193969
194754
  const downloadedUrls = /* @__PURE__ */ new Set();
193970
- mkdirSync53(join111(outputDir, "assets", "svgs"), { recursive: true });
194755
+ mkdirSync55(join114(outputDir, "assets", "svgs"), { recursive: true });
193971
194756
  const usedSvgNames = /* @__PURE__ */ new Set();
193972
194757
  for (let i2 = 0; i2 < tokens.svgs.length && i2 < 30; i2++) {
193973
194758
  const svg = tokens.svgs[i2];
@@ -193984,7 +194769,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks,
193984
194769
  const name = `${finalSlug}.svg`;
193985
194770
  const localPath = `assets/svgs/${name}`;
193986
194771
  try {
193987
- writeFileSync45(join111(outputDir, localPath), svgFile, "utf-8");
194772
+ writeFileSync46(join114(outputDir, localPath), svgFile, "utf-8");
193988
194773
  assets.push({ url: "", localPath, type: "svg" });
193989
194774
  } catch {
193990
194775
  }
@@ -193999,7 +194784,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks,
193999
194784
  const localPath = `assets/${name}`;
194000
194785
  const buffer = await fetchBuffer(icon.href, Math.min(1e4, remainingMs));
194001
194786
  if (buffer) {
194002
- writeFileSync45(join111(outputDir, localPath), buffer);
194787
+ writeFileSync46(join114(outputDir, localPath), buffer);
194003
194788
  assets.push({ url: icon.href, localPath, type: "favicon" });
194004
194789
  break;
194005
194790
  }
@@ -194066,7 +194851,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks,
194066
194851
  const name = `${slug}${ext}`;
194067
194852
  usedNames.add(slug);
194068
194853
  const localPath = `assets/${name}`;
194069
- writeFileSync45(join111(outputDir, localPath), buffer);
194854
+ writeFileSync46(join114(outputDir, localPath), buffer);
194070
194855
  assets.push({ url, localPath, type: "image" });
194071
194856
  imgIdx++;
194072
194857
  } catch {
@@ -194080,7 +194865,7 @@ async function downloadAssets(tokens, outputDir, catalogedAssets, faviconLinks,
194080
194865
  const localPath = `assets/og-image${ext}`;
194081
194866
  const buffer = remainingMs > 0 ? await fetchBuffer(tokens.ogImage, Math.min(1e4, remainingMs)) : null;
194082
194867
  if (buffer && buffer.length > 5e3) {
194083
- writeFileSync45(join111(outputDir, localPath), buffer);
194868
+ writeFileSync46(join114(outputDir, localPath), buffer);
194084
194869
  assets.push({ url: tokens.ogImage, localPath, type: "image" });
194085
194870
  }
194086
194871
  } catch {
@@ -194103,8 +194888,8 @@ function normalizeUrl(u) {
194103
194888
  }
194104
194889
  }
194105
194890
  async function downloadAndRewriteFonts(css, outputDir, options = {}) {
194106
- const assetsDir = join111(outputDir, "assets", "fonts");
194107
- mkdirSync53(assetsDir, { recursive: true });
194891
+ const assetsDir = join114(outputDir, "assets", "fonts");
194892
+ mkdirSync55(assetsDir, { recursive: true });
194108
194893
  const fontUrlRegex = /url\(['"]?(https?:\/\/[^'")\s]+\.(?:woff2?|ttf|otf)[^'")\s]*?)['"]?\)/g;
194109
194894
  const fontUrls = /* @__PURE__ */ new Set();
194110
194895
  let match;
@@ -194143,11 +194928,11 @@ async function downloadAndRewriteFonts(css, outputDir, options = {}) {
194143
194928
  try {
194144
194929
  const urlObj = new URL(fontUrl);
194145
194930
  const filename = urlObj.pathname.split("/").pop() || `font-${count}.woff2`;
194146
- const localPath = join111(assetsDir, filename);
194931
+ const localPath = join114(assetsDir, filename);
194147
194932
  const relativePath = `assets/fonts/${filename}`;
194148
194933
  const buffer = await fetchBuffer(fontUrl, Math.min(1e4, remainingMs));
194149
194934
  if (buffer) {
194150
- writeFileSync45(localPath, buffer);
194935
+ writeFileSync46(localPath, buffer);
194151
194936
  rewritten = rewritten.split(fontUrl).join(relativePath);
194152
194937
  }
194153
194938
  } catch {
@@ -194299,8 +195084,8 @@ __export(video_exports, {
194299
195084
  runVideoMode: () => runVideoMode,
194300
195085
  safeFilename: () => safeFilename
194301
195086
  });
194302
- import { createWriteStream as createWriteStream4, existsSync as existsSync106, mkdirSync as mkdirSync54, readFileSync as readFileSync71, unlinkSync as unlinkSync10 } from "fs";
194303
- import { resolve as resolve71, join as join113, basename as basename29 } from "path";
195087
+ import { createWriteStream as createWriteStream4, existsSync as existsSync108, mkdirSync as mkdirSync56, readFileSync as readFileSync75, unlinkSync as unlinkSync11 } from "fs";
195088
+ import { resolve as resolve71, join as join115, basename as basename29 } from "path";
194304
195089
  async function streamToFile(url, destPath) {
194305
195090
  const r2 = await safeFetch(url, {
194306
195091
  signal: AbortSignal.timeout(12e4),
@@ -194362,7 +195147,7 @@ async function streamToFile(url, destPath) {
194362
195147
  file.destroy();
194363
195148
  if (e3.code !== "EEXIST") {
194364
195149
  try {
194365
- unlinkSync10(destPath);
195150
+ unlinkSync11(destPath);
194366
195151
  } catch {
194367
195152
  }
194368
195153
  }
@@ -194419,11 +195204,11 @@ function pickManifestEntry(manifest, args) {
194419
195204
  }
194420
195205
  async function runVideoMode(args) {
194421
195206
  const projectDir = resolve71(args.project);
194422
- const directPath = join113(projectDir, "extracted", "video-manifest.json");
194423
- const w2hPath = join113(projectDir, "capture", "extracted", "video-manifest.json");
194424
- const manifestPath2 = existsSync106(directPath) ? directPath : w2hPath;
195207
+ const directPath = join115(projectDir, "extracted", "video-manifest.json");
195208
+ const w2hPath = join115(projectDir, "capture", "extracted", "video-manifest.json");
195209
+ const manifestPath2 = existsSync108(directPath) ? directPath : w2hPath;
194425
195210
  const isW2hLayout = manifestPath2 === w2hPath;
194426
- if (!existsSync106(manifestPath2)) {
195211
+ if (!existsSync108(manifestPath2)) {
194427
195212
  console.error(
194428
195213
  `${c.error("\u2717")} no video-manifest.json at ${directPath} or ${w2hPath}
194429
195214
  Was this directory produced by \`hyperframes capture\`?`
@@ -194433,7 +195218,7 @@ async function runVideoMode(args) {
194433
195218
  }
194434
195219
  let manifest;
194435
195220
  try {
194436
- manifest = JSON.parse(readFileSync71(manifestPath2, "utf-8"));
195221
+ manifest = JSON.parse(readFileSync75(manifestPath2, "utf-8"));
194437
195222
  } catch (e3) {
194438
195223
  console.error(`${c.error("\u2717")} video-manifest.json is malformed: ${e3.message}`);
194439
195224
  setCommandExitCode(1);
@@ -194474,10 +195259,10 @@ async function runVideoMode(args) {
194474
195259
  setCommandExitCode(1);
194475
195260
  return;
194476
195261
  }
194477
- const outDir = isW2hLayout ? join113(projectDir, "capture", "assets", "videos") : join113(projectDir, "assets", "videos");
194478
- mkdirSync54(outDir, { recursive: true });
195262
+ const outDir = isW2hLayout ? join115(projectDir, "capture", "assets", "videos") : join115(projectDir, "assets", "videos");
195263
+ mkdirSync56(outDir, { recursive: true });
194479
195264
  const fname = safeFilename(entry.filename || basename29(entry.url));
194480
- const outPath = join113(outDir, fname);
195265
+ const outPath = join115(outDir, fname);
194481
195266
  const relPath = isW2hLayout ? `capture/assets/videos/${fname}` : `assets/videos/${fname}`;
194482
195267
  console.log(
194483
195268
  `${c.accent("\u25B8")} downloading [${entry.index}] ${entry.filename} (${entry.sourceWidth || entry.width}\xD7${entry.sourceHeight || entry.height})`
@@ -195721,8 +196506,8 @@ var init_designStyleExtractor = __esm({
195721
196506
  });
195722
196507
 
195723
196508
  // src/capture/fontMetadataExtractor.ts
195724
- import { readdirSync as readdirSync34, readFileSync as readFileSync73, writeFileSync as writeFileSync46, existsSync as existsSync107 } from "fs";
195725
- import { join as join114 } from "path";
196509
+ import { readdirSync as readdirSync34, readFileSync as readFileSync76, writeFileSync as writeFileSync47, existsSync as existsSync109 } from "fs";
196510
+ import { join as join116 } from "path";
195726
196511
  import * as fontkit from "fontkit";
195727
196512
  function isFontCollection(value) {
195728
196513
  return value.type === "TTC" || value.type === "DFont";
@@ -195730,10 +196515,10 @@ function isFontCollection(value) {
195730
196515
  function extractFontMetadata(fontsDir, outputPath) {
195731
196516
  const files = [];
195732
196517
  const unidentified = [];
195733
- if (existsSync107(fontsDir)) {
196518
+ if (existsSync109(fontsDir)) {
195734
196519
  const fontFiles = readdirSync34(fontsDir).filter((f3) => /\.(woff2?|ttf|otf)$/i.test(f3));
195735
196520
  for (const filename of fontFiles) {
195736
- const fullPath = join114(fontsDir, filename);
196521
+ const fullPath = join116(fontsDir, filename);
195737
196522
  const meta = readSingleFont(fullPath, filename);
195738
196523
  if (meta.identified) {
195739
196524
  files.push(meta);
@@ -195755,7 +196540,7 @@ function extractFontMetadata(fontsDir, outputPath) {
195755
196540
  tool: "fontkit"
195756
196541
  }
195757
196542
  };
195758
- writeFileSync46(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
196543
+ writeFileSync47(outputPath, JSON.stringify(manifest, null, 2), "utf-8");
195759
196544
  return manifest;
195760
196545
  }
195761
196546
  function readSingleFont(fullPath, filename) {
@@ -195772,7 +196557,7 @@ function readSingleFont(fullPath, filename) {
195772
196557
  isIcon: false
195773
196558
  };
195774
196559
  try {
195775
- const buf = readFileSync73(fullPath);
196560
+ const buf = readFileSync76(fullPath);
195776
196561
  const created = fontkit.create(buf);
195777
196562
  const font = isFontCollection(created) ? created.fonts[0] : created;
195778
196563
  if (!font) return empty2;
@@ -196044,8 +196829,8 @@ var init_animationCataloger = __esm({
196044
196829
  });
196045
196830
 
196046
196831
  // src/capture/mediaCapture.ts
196047
- import { mkdirSync as mkdirSync55, writeFileSync as writeFileSync47, readdirSync as readdirSync35, readFileSync as readFileSync74, statSync as statSync37 } from "fs";
196048
- import { join as join115, extname as extname25 } from "path";
196832
+ import { mkdirSync as mkdirSync57, writeFileSync as writeFileSync48, readdirSync as readdirSync35, readFileSync as readFileSync77, statSync as statSync37 } from "fs";
196833
+ import { join as join117, extname as extname25 } from "path";
196049
196834
  function liveRemainingMs(budget, fallbackMs) {
196050
196835
  return budget.remainingMs?.() ?? fallbackMs;
196051
196836
  }
@@ -196083,7 +196868,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir, budget = {}) {
196083
196868
  const hash2 = buf.toString("base64").slice(0, 100);
196084
196869
  if (savedHashes.has(hash2)) continue;
196085
196870
  savedHashes.add(hash2);
196086
- writeFileSync47(join115(lottieDir, `animation-${savedCount}.lottie`), buf);
196871
+ writeFileSync48(join117(lottieDir, `animation-${savedCount}.lottie`), buf);
196087
196872
  savedCount++;
196088
196873
  continue;
196089
196874
  }
@@ -196101,7 +196886,7 @@ async function saveLottieAnimations(discoveredLotties, lottieDir, budget = {}) {
196101
196886
  } catch {
196102
196887
  continue;
196103
196888
  }
196104
- writeFileSync47(join115(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
196889
+ writeFileSync48(join117(lottieDir, `animation-${savedCount}.json`), jsonData, "utf-8");
196105
196890
  savedCount++;
196106
196891
  }
196107
196892
  } catch {
@@ -196111,18 +196896,18 @@ async function saveLottieAnimations(discoveredLotties, lottieDir, budget = {}) {
196111
196896
  }
196112
196897
  async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir, budget = {}) {
196113
196898
  const manifest = [];
196114
- const previewDir = join115(lottieDir, "previews");
196115
- mkdirSync55(previewDir, { recursive: true });
196899
+ const previewDir = join117(lottieDir, "previews");
196900
+ mkdirSync57(previewDir, { recursive: true });
196116
196901
  for (const file of readdirSync35(lottieDir)) {
196117
196902
  if (!file.endsWith(".json")) continue;
196118
196903
  if (liveRemainingMs(budget, 1) <= 0) break;
196119
196904
  try {
196120
- const raw = JSON.parse(readFileSync74(join115(lottieDir, file), "utf-8"));
196905
+ const raw = JSON.parse(readFileSync77(join117(lottieDir, file), "utf-8"));
196121
196906
  const fr = raw.fr || 30;
196122
196907
  const dur = ((raw.op || 0) - (raw.ip || 0)) / fr;
196123
196908
  const previewName = file.replace(".json", "-preview.png");
196124
196909
  let preview;
196125
- const fileSize = statSync37(join115(lottieDir, file)).size;
196910
+ const fileSize = statSync37(join117(lottieDir, file)).size;
196126
196911
  if (fileSize > 2e6) continue;
196127
196912
  let previewPage;
196128
196913
  try {
@@ -196130,7 +196915,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir, budget
196130
196915
  previewPage = await chromeBrowser.newPage();
196131
196916
  if (liveRemainingMs(budget, 1) <= 0) break;
196132
196917
  await previewPage.setViewport({ width: 400, height: 400 });
196133
- const animData = JSON.parse(readFileSync74(join115(lottieDir, file), "utf-8"));
196918
+ const animData = JSON.parse(readFileSync77(join117(lottieDir, file), "utf-8"));
196134
196919
  const midFrame = Math.floor(((raw.op || 0) - (raw.ip || 0)) * 0.3);
196135
196920
  await previewPage.setContent(
196136
196921
  `<!DOCTYPE html>
@@ -196161,7 +196946,7 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir, budget
196161
196946
  });
196162
196947
  if (liveRemainingMs(budget, 1) > 0) {
196163
196948
  await previewPage.screenshot({
196164
- path: join115(previewDir, previewName),
196949
+ path: join117(previewDir, previewName),
196165
196950
  type: "png",
196166
196951
  omitBackground: true
196167
196952
  });
@@ -196186,8 +196971,8 @@ async function renderLottiePreviews(chromeBrowser, lottieDir, outputDir, budget
196186
196971
  }
196187
196972
  }
196188
196973
  if (manifest.length > 0) {
196189
- writeFileSync47(
196190
- join115(outputDir, "extracted", "lottie-manifest.json"),
196974
+ writeFileSync48(
196975
+ join117(outputDir, "extracted", "lottie-manifest.json"),
196191
196976
  JSON.stringify(manifest, null, 2),
196192
196977
  "utf-8"
196193
196978
  );
@@ -196225,7 +197010,7 @@ async function downloadVideoBody(srcUrl, filename, videosDir, timeoutMs) {
196225
197010
  }
196226
197011
  if (total < 1024) return null;
196227
197012
  const safe = /\.[a-z0-9]+$/i.test(filename) ? filename.replace(/[^\w.-]/g, "_") : `video${ext}`;
196228
- writeFileSync47(join115(videosDir, safe), Buffer.concat(chunks));
197013
+ writeFileSync48(join117(videosDir, safe), Buffer.concat(chunks));
196229
197014
  return `assets/videos/${safe}`;
196230
197015
  } catch {
196231
197016
  return null;
@@ -196292,10 +197077,10 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
196292
197077
  }
196293
197078
  const merged = [...byKey.values()];
196294
197079
  if (merged.length === 0) return;
196295
- const videoManifestDir = join115(outputDir, "assets", "videos");
196296
- mkdirSync55(videoManifestDir, { recursive: true });
196297
- const previewDir = join115(videoManifestDir, "previews");
196298
- mkdirSync55(previewDir, { recursive: true });
197080
+ const videoManifestDir = join117(outputDir, "assets", "videos");
197081
+ mkdirSync57(videoManifestDir, { recursive: true });
197082
+ const previewDir = join117(videoManifestDir, "previews");
197083
+ mkdirSync57(previewDir, { recursive: true });
196299
197084
  const videoManifest = [];
196300
197085
  const dlStart = Date.now();
196301
197086
  for (let vi = 0; vi < merged.length && vi < 20; vi++) {
@@ -196323,7 +197108,7 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
196323
197108
  await new Promise((r2) => setTimeout(r2, 200));
196324
197109
  if (liveRemainingMs(opts ?? {}, 1) > 0) {
196325
197110
  await page.screenshot({
196326
- path: join115(previewDir, previewName),
197111
+ path: join117(previewDir, previewName),
196327
197112
  clip: {
196328
197113
  x: Math.max(0, rect.x),
196329
197114
  y: Math.max(0, rect.y),
@@ -196359,8 +197144,8 @@ async function captureVideoManifest(page, outputDir, progress, opts) {
196359
197144
  });
196360
197145
  }
196361
197146
  if (videoManifest.length > 0) {
196362
- writeFileSync47(
196363
- join115(outputDir, "extracted", "video-manifest.json"),
197147
+ writeFileSync48(
197148
+ join117(outputDir, "extracted", "video-manifest.json"),
196364
197149
  JSON.stringify(videoManifest, null, 2),
196365
197150
  "utf-8"
196366
197151
  );
@@ -196429,8 +197214,8 @@ var init_mediaCapture = __esm({
196429
197214
  });
196430
197215
 
196431
197216
  // src/capture/contentExtractor.ts
196432
- import { existsSync as existsSync108, readdirSync as readdirSync36, statSync as statSync38, readFileSync as readFileSync75 } from "fs";
196433
- import { basename as basename30, join as join116 } from "path";
197217
+ import { existsSync as existsSync110, readdirSync as readdirSync36, statSync as statSync38, readFileSync as readFileSync78 } from "fs";
197218
+ import { basename as basename30, join as join118 } from "path";
196434
197219
  function resolveVisionPhaseCompletion(outcome, remainingMs) {
196435
197220
  if (outcome.budgetExhausted || remainingMs <= 0) {
196436
197221
  return { status: "degraded", reason: "budget-exhausted" };
@@ -196668,7 +197453,7 @@ async function captionImagesWithGemini(outputDir, progress, warnings, options =
196668
197453
  return response.text?.trim() || "";
196669
197454
  };
196670
197455
  }
196671
- const imageFiles = readdirSync36(join116(outputDir, "assets")).filter(
197456
+ const imageFiles = readdirSync36(join118(outputDir, "assets")).filter(
196672
197457
  (f3) => /\.(png|jpg|jpeg|webp|gif)$/i.test(f3)
196673
197458
  );
196674
197459
  const BATCH_SIZE = 20;
@@ -196696,10 +197481,10 @@ async function captionImagesWithGemini(outputDir, progress, warnings, options =
196696
197481
  const batch = imageFiles.slice(i2, i2 + BATCH_SIZE);
196697
197482
  const results = await Promise.allSettled(
196698
197483
  batch.map(async (file) => {
196699
- const filePath = join116(outputDir, "assets", file);
197484
+ const filePath = join118(outputDir, "assets", file);
196700
197485
  const stat3 = statSync38(filePath);
196701
197486
  if (stat3.size > 4e6) return { file, caption: "" };
196702
- const buffer = readFileSync75(filePath);
197487
+ const buffer = readFileSync78(filePath);
196703
197488
  const base64 = buffer.toString("base64");
196704
197489
  const ext = file.split(".").pop()?.toLowerCase() || "png";
196705
197490
  const mimeType = ext === "jpg" ? "image/jpeg" : `image/${ext}`;
@@ -196729,12 +197514,12 @@ async function captionImagesWithGemini(outputDir, progress, warnings, options =
196729
197514
  `${Object.keys(geminiCaptions).length} images captioned with ${providerName}`
196730
197515
  );
196731
197516
  const svgFiles = [];
196732
- const assetsDir = join116(outputDir, "assets");
197517
+ const assetsDir = join118(outputDir, "assets");
196733
197518
  for (const f3 of readdirSync36(assetsDir)) {
196734
197519
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: f3 });
196735
197520
  }
196736
- const svgsSubdir = join116(assetsDir, "svgs");
196737
- if (existsSync108(svgsSubdir)) {
197521
+ const svgsSubdir = join118(assetsDir, "svgs");
197522
+ if (existsSync110(svgsSubdir)) {
196738
197523
  for (const f3 of readdirSync36(svgsSubdir)) {
196739
197524
  if (/\.svg$/i.test(f3)) svgFiles.push({ file: f3, relPath: `svgs/${f3}` });
196740
197525
  }
@@ -196764,10 +197549,10 @@ async function captionImagesWithGemini(outputDir, progress, warnings, options =
196764
197549
  const batch = svgFiles.slice(i2, i2 + SVG_BATCH);
196765
197550
  const results = await Promise.allSettled(
196766
197551
  batch.map(async ({ relPath }) => {
196767
- const filePath = join116(assetsDir, relPath);
197552
+ const filePath = join118(assetsDir, relPath);
196768
197553
  let pngBase64;
196769
197554
  try {
196770
- const svgSource = readFileSync75(filePath, "utf-8");
197555
+ const svgSource = readFileSync78(filePath, "utf-8");
196771
197556
  const lightFillHits = (svgSource.match(/fill\s*=\s*["'](#fff(fff)?|white|#[ef][ef][ef]|#[ef]{6})["']/gi) || []).length;
196772
197557
  const darkFillHits = (svgSource.match(/fill\s*=\s*["'](#000(000)?|black|#[0-3]{6}|#[0-3]{3})["']/gi) || []).length;
196773
197558
  const bg = lightFillHits > darkFillHits ? { r: 32, g: 32, b: 32 } : { r: 255, g: 255, b: 255 };
@@ -196833,11 +197618,11 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
196833
197618
  const uncaptionedLines = [];
196834
197619
  const svgLines = [];
196835
197620
  const fontLines = [];
196836
- const assetsPath = join116(outputDir, "assets");
197621
+ const assetsPath = join118(outputDir, "assets");
196837
197622
  try {
196838
197623
  for (const file of readdirSync36(assetsPath)) {
196839
197624
  if (file === "svgs" || file === "fonts" || file === "lottie" || file === "videos") continue;
196840
- const filePath = join116(assetsPath, file);
197625
+ const filePath = join118(assetsPath, file);
196841
197626
  const stat3 = statSync38(filePath);
196842
197627
  if (!stat3.isFile()) continue;
196843
197628
  const sizeKb = Math.round(stat3.size / 1024);
@@ -196866,7 +197651,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
196866
197651
  } catch {
196867
197652
  }
196868
197653
  try {
196869
- const svgsPath = join116(assetsPath, "svgs");
197654
+ const svgsPath = join118(assetsPath, "svgs");
196870
197655
  for (const file of readdirSync36(svgsPath)) {
196871
197656
  if (!file.endsWith(".svg")) continue;
196872
197657
  const svgMatch = tokens.svgs.find(
@@ -196885,7 +197670,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
196885
197670
  } catch {
196886
197671
  }
196887
197672
  try {
196888
- const fontsPath = join116(assetsPath, "fonts");
197673
+ const fontsPath = join118(assetsPath, "fonts");
196889
197674
  for (const file of readdirSync36(fontsPath)) {
196890
197675
  fontLines.push(`fonts/${file} \u2014 font file`);
196891
197676
  }
@@ -196894,7 +197679,7 @@ function generateAssetDescriptions(outputDir, tokens, catalogedAssets, geminiCap
196894
197679
  const videoLines = [];
196895
197680
  try {
196896
197681
  const manifest = JSON.parse(
196897
- readFileSync75(join116(outputDir, "extracted", "video-manifest.json"), "utf-8")
197682
+ readFileSync78(join118(outputDir, "extracted", "video-manifest.json"), "utf-8")
196898
197683
  );
196899
197684
  for (const v2 of manifest) {
196900
197685
  if (!v2.localPath) continue;
@@ -196929,8 +197714,8 @@ var agentPromptGenerator_exports = {};
196929
197714
  __export(agentPromptGenerator_exports, {
196930
197715
  generateAgentPrompt: () => generateAgentPrompt
196931
197716
  });
196932
- import { writeFileSync as writeFileSync48, readdirSync as readdirSync37, existsSync as existsSync109 } from "fs";
196933
- import { join as join117 } from "path";
197717
+ import { writeFileSync as writeFileSync49, readdirSync as readdirSync37, existsSync as existsSync111 } from "fs";
197718
+ import { join as join119 } from "path";
196934
197719
  function inferColorRole(hex) {
196935
197720
  const r2 = parseInt(hex.slice(1, 3), 16) / 255;
196936
197721
  const g = parseInt(hex.slice(3, 5), 16) / 255;
@@ -196949,9 +197734,9 @@ function inferColorRole(hex) {
196949
197734
  }
196950
197735
  function generateAgentPrompt(outputDir, url, tokens, _animations, hasScreenshot, hasLottie, hasShaders, _catalogedAssets, _detectedLibraries) {
196951
197736
  const prompt = buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders);
196952
- writeFileSync48(join117(outputDir, "AGENTS.md"), prompt, "utf-8");
196953
- writeFileSync48(join117(outputDir, "CLAUDE.md"), prompt, "utf-8");
196954
- writeFileSync48(join117(outputDir, ".cursorrules"), prompt, "utf-8");
197737
+ writeFileSync49(join119(outputDir, "AGENTS.md"), prompt, "utf-8");
197738
+ writeFileSync49(join119(outputDir, "CLAUDE.md"), prompt, "utf-8");
197739
+ writeFileSync49(join119(outputDir, ".cursorrules"), prompt, "utf-8");
196955
197740
  }
196956
197741
  function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShaders) {
196957
197742
  const title = tokens.title || new URL(url).hostname.replace(/^www\./, "");
@@ -196960,8 +197745,8 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
196960
197745
  (f3) => f3.family + (f3.variable && f3.weightRange ? ` (${f3.weightRange[0]}-${f3.weightRange[1]} variable)` : f3.weights.length > 0 ? ` (${f3.weights.join(",")})` : "")
196961
197746
  ).join(", ") || "none detected";
196962
197747
  function contactSheetRows(dir, baseFile, label2) {
196963
- const fullDir = join117(outputDir, dir);
196964
- if (!existsSync109(fullDir)) return [];
197748
+ const fullDir = join119(outputDir, dir);
197749
+ if (!existsSync111(fullDir)) return [];
196965
197750
  const baseName = baseFile.replace(/\.jpg$/, "");
196966
197751
  const escapedBase = baseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
196967
197752
  const paginatedRe = new RegExp(`^${escapedBase}(?:-(\\d+))?\\.jpg$`);
@@ -196993,7 +197778,7 @@ function buildPrompt(outputDir, url, tokens, hasScreenshot, hasLottie, hasShader
196993
197778
  tableRows.push(
196994
197779
  `| \`extracted/tokens.json\` | Design tokens: ${tokens.colors.length} colors, ${tokens.fonts.length} fonts, ${tokens.headings?.length ?? 0} headings, ${tokens.ctas?.length ?? 0} CTAs |`
196995
197780
  );
196996
- if (existsSync109(join117(outputDir, "extracted", "design-styles.json"))) {
197781
+ if (existsSync111(join119(outputDir, "extracted", "design-styles.json"))) {
196997
197782
  tableRows.push(
196998
197783
  "| `extracted/design-styles.json` | Computed styles from live DOM: typography hierarchy, button/card/nav styles, spacing scale, border-radius, box shadows. Primary data source for DESIGN.md. |"
196999
197784
  );
@@ -197064,15 +197849,15 @@ var init_agentPromptGenerator = __esm({
197064
197849
  });
197065
197850
 
197066
197851
  // src/capture/scaffolding.ts
197067
- import { existsSync as existsSync110, writeFileSync as writeFileSync49, readFileSync as readFileSync76 } from "fs";
197068
- import { join as join118, resolve as resolve72 } from "path";
197852
+ import { existsSync as existsSync113, writeFileSync as writeFileSync50, readFileSync as readFileSync79 } from "fs";
197853
+ import { join as join120, resolve as resolve72 } from "path";
197069
197854
  function loadEnvFile(startDir) {
197070
197855
  try {
197071
197856
  let dir = resolve72(startDir);
197072
197857
  for (let i2 = 0; i2 < 5; i2++) {
197073
197858
  const envPath = resolve72(dir, ".env");
197074
197859
  try {
197075
- const envContent = readFileSync76(envPath, "utf-8");
197860
+ const envContent = readFileSync79(envPath, "utf-8");
197076
197861
  for (const line2 of envContent.split("\n")) {
197077
197862
  const trimmed = line2.trim();
197078
197863
  if (!trimmed || trimmed.startsWith("#")) continue;
@@ -197091,10 +197876,10 @@ function loadEnvFile(startDir) {
197091
197876
  }
197092
197877
  }
197093
197878
  async function generateProjectScaffold(outputDir, url, tokens, animationCatalog, hasScreenshots, hasLotties, hasShaders, catalogedAssets, progress, warnings, detectedLibraries) {
197094
- const metaPath = join118(outputDir, "meta.json");
197095
- if (!existsSync110(metaPath)) {
197879
+ const metaPath = join120(outputDir, "meta.json");
197880
+ if (!existsSync113(metaPath)) {
197096
197881
  const hostname2 = new URL(url).hostname.replace(/^www\./, "");
197097
- writeFileSync49(
197882
+ writeFileSync50(
197098
197883
  metaPath,
197099
197884
  JSON.stringify({ id: hostname2 + "-video", name: tokens.title || hostname2 }, null, 2),
197100
197885
  "utf-8"
@@ -197151,8 +197936,8 @@ __export(screenshotCapture_exports, {
197151
197936
  captureScrollScreenshots: () => captureScrollScreenshots,
197152
197937
  pngHeight: () => pngHeight
197153
197938
  });
197154
- import { writeFileSync as writeFileSync50, mkdirSync as mkdirSync56 } from "fs";
197155
- import { join as join119 } from "path";
197939
+ import { writeFileSync as writeFileSync51, mkdirSync as mkdirSync58 } from "fs";
197940
+ import { join as join121 } from "path";
197156
197941
  function pngHeight(buf) {
197157
197942
  if (buf.length < 24) return null;
197158
197943
  if (buf[12] !== 73 || buf[13] !== 72 || buf[14] !== 68 || buf[15] !== 82) return null;
@@ -197177,7 +197962,7 @@ async function captureFullPagePlate(page, screenshotsDir, budget = {}) {
197177
197962
  const buffer = await page.screenshot({ type: "png", fullPage: true });
197178
197963
  const produced = pngHeight(buffer);
197179
197964
  if (produced != null && produced > MAX_PLATE_HEIGHT_PX) return null;
197180
- writeFileSync50(join119(screenshotsDir, "full-page.png"), buffer);
197965
+ writeFileSync51(join121(screenshotsDir, "full-page.png"), buffer);
197181
197966
  return "screenshots/full-page.png";
197182
197967
  } finally {
197183
197968
  try {
@@ -197192,8 +197977,8 @@ async function captureFullPagePlate(page, screenshotsDir, budget = {}) {
197192
197977
  }
197193
197978
  }
197194
197979
  async function captureScrollScreenshots(page, outputDir, budget = {}) {
197195
- const screenshotsDir = join119(outputDir, "screenshots");
197196
- mkdirSync56(screenshotsDir, { recursive: true });
197980
+ const screenshotsDir = join121(outputDir, "screenshots");
197981
+ mkdirSync58(screenshotsDir, { recursive: true });
197197
197982
  const MAX_SCREENSHOTS = 20;
197198
197983
  const filePaths = [];
197199
197984
  if ((budget.remainingMs?.() ?? 1) <= 0) return filePaths;
@@ -197286,10 +198071,10 @@ async function captureScrollScreenshots(page, outputDir, budget = {}) {
197286
198071
  finalPositions[i2] / Math.max(1, scrollHeight - viewportHeight) * 100
197287
198072
  );
197288
198073
  const filename = `scroll-${String(Math.min(pct, 100)).padStart(3, "0")}.png`;
197289
- const filePath = join119(screenshotsDir, filename);
198074
+ const filePath = join121(screenshotsDir, filename);
197290
198075
  if ((budget.remainingMs?.() ?? 1) <= 0) break;
197291
198076
  const buffer = await page.screenshot({ type: "png" });
197292
- writeFileSync50(filePath, buffer);
198077
+ writeFileSync51(filePath, buffer);
197293
198078
  filePaths.push(`screenshots/${filename}`);
197294
198079
  }
197295
198080
  await page.evaluate(`window.scrollTo(0, 0)`);
@@ -197642,8 +198427,8 @@ var capture_exports = {};
197642
198427
  __export(capture_exports, {
197643
198428
  captureWebsite: () => captureWebsite
197644
198429
  });
197645
- import { mkdirSync as mkdirSync57, writeFileSync as writeFileSync51, existsSync as existsSync111 } from "fs";
197646
- import { join as join120 } from "path";
198430
+ import { mkdirSync as mkdirSync59, writeFileSync as writeFileSync53, existsSync as existsSync114 } from "fs";
198431
+ import { join as join123 } from "path";
197647
198432
  async function captureWebsite(opts, onProgress) {
197648
198433
  const {
197649
198434
  url,
@@ -197684,9 +198469,9 @@ async function captureWebsite(opts, onProgress) {
197684
198469
  };
197685
198470
  phase("browser", "started");
197686
198471
  loadEnvFile(outputDir);
197687
- mkdirSync57(join120(outputDir, "extracted"), { recursive: true });
197688
- mkdirSync57(join120(outputDir, "screenshots"), { recursive: true });
197689
- mkdirSync57(join120(outputDir, "assets"), { recursive: true });
198472
+ mkdirSync59(join123(outputDir, "extracted"), { recursive: true });
198473
+ mkdirSync59(join123(outputDir, "screenshots"), { recursive: true });
198474
+ mkdirSync59(join123(outputDir, "assets"), { recursive: true });
197690
198475
  progress("browser", "Launching headless Chrome...");
197691
198476
  const { ensureBrowser: ensureBrowser2 } = await Promise.resolve().then(() => (init_manager2(), manager_exports2));
197692
198477
  const browser = await ensureBrowser2();
@@ -197862,8 +198647,8 @@ async function captureWebsite(opts, onProgress) {
197862
198647
  } catch {
197863
198648
  }
197864
198649
  if (discoveredLotties.length > 0 && remainingMs() > 0) {
197865
- const lottieDir = join120(outputDir, "assets", "lottie");
197866
- mkdirSync57(lottieDir, { recursive: true });
198650
+ const lottieDir = join123(outputDir, "assets", "lottie");
198651
+ mkdirSync59(lottieDir, { recursive: true });
197867
198652
  const lottieBudget = { remainingMs };
197868
198653
  const savedCount = await saveLottieAnimations(discoveredLotties, lottieDir, lottieBudget);
197869
198654
  if (savedCount > 0 && remainingMs() > 0) {
@@ -197882,8 +198667,8 @@ async function captureWebsite(opts, onProgress) {
197882
198667
  return true;
197883
198668
  });
197884
198669
  capturedShaders = unique;
197885
- writeFileSync51(
197886
- join120(outputDir, "extracted", "shaders.json"),
198670
+ writeFileSync53(
198671
+ join123(outputDir, "extracted", "shaders.json"),
197887
198672
  JSON.stringify(unique, null, 2),
197888
198673
  "utf-8"
197889
198674
  );
@@ -197897,16 +198682,16 @@ async function captureWebsite(opts, onProgress) {
197897
198682
  ...tokens,
197898
198683
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
197899
198684
  };
197900
- writeFileSync51(
197901
- join120(outputDir, "extracted", "tokens.json"),
198685
+ writeFileSync53(
198686
+ join123(outputDir, "extracted", "tokens.json"),
197902
198687
  JSON.stringify(tokensForDisk, null, 2),
197903
198688
  "utf-8"
197904
198689
  );
197905
198690
  progress("style", "Extracting design styles...");
197906
198691
  try {
197907
198692
  const designStyles = await extractDesignStyles(page1);
197908
- writeFileSync51(
197909
- join120(outputDir, "extracted", "design-styles.json"),
198693
+ writeFileSync53(
198694
+ join123(outputDir, "extracted", "design-styles.json"),
197910
198695
  JSON.stringify(designStyles, null, 2),
197911
198696
  "utf-8"
197912
198697
  );
@@ -198006,8 +198791,8 @@ ${err.stack}` : normalizeErrorMessage(err);
198006
198791
  }
198007
198792
  try {
198008
198793
  const fontsManifest = extractFontMetadata(
198009
- join120(outputDir, "assets", "fonts"),
198010
- join120(outputDir, "extracted", "fonts-manifest.json")
198794
+ join123(outputDir, "assets", "fonts"),
198795
+ join123(outputDir, "extracted", "fonts-manifest.json")
198011
198796
  );
198012
198797
  if (fontsManifest.families.length > 0) {
198013
198798
  const summary = fontsManifest.families.map((f3) => `${f3.family}${f3.variable ? " (variable)" : ""} \xD7 ${f3.fileCount}`).join(", ");
@@ -198033,8 +198818,8 @@ ${err.stack}` : normalizeErrorMessage(err);
198033
198818
  scrollTriggeredElements: (animationCatalog.scrollTargets || []).length,
198034
198819
  representativeAnimations: representativeAnims
198035
198820
  };
198036
- writeFileSync51(
198037
- join120(outputDir, "extracted", "animations.json"),
198821
+ writeFileSync53(
198822
+ join123(outputDir, "extracted", "animations.json"),
198038
198823
  JSON.stringify(leanCatalog, null, 2),
198039
198824
  "utf-8"
198040
198825
  );
@@ -198079,8 +198864,8 @@ ${err.stack}` : normalizeErrorMessage(err);
198079
198864
  ...tokens,
198080
198865
  svgs: tokens.svgs.map(({ outerHTML: _, ...rest }) => rest)
198081
198866
  };
198082
- writeFileSync51(
198083
- join120(outputDir, "extracted", "tokens.json"),
198867
+ writeFileSync53(
198868
+ join123(outputDir, "extracted", "tokens.json"),
198084
198869
  JSON.stringify(tokensForDisk2, null, 2),
198085
198870
  "utf-8"
198086
198871
  );
@@ -198096,12 +198881,12 @@ ${extracted.bodyHtml}
198096
198881
  </body>
198097
198882
  </html>
198098
198883
  `;
198099
- writeFileSync51(join120(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
198884
+ writeFileSync53(join123(outputDir, "extracted", "page.html"), pageHtml, "utf-8");
198100
198885
  } catch (err) {
198101
198886
  warnings.push(`page.html write failed: ${err}`);
198102
198887
  }
198103
198888
  if (visibleTextContent) {
198104
- writeFileSync51(join120(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
198889
+ writeFileSync53(join123(outputDir, "extracted", "visible-text.txt"), visibleTextContent, "utf-8");
198105
198890
  }
198106
198891
  let geminiCaptions = {};
198107
198892
  if (skipVision) {
@@ -198137,8 +198922,8 @@ ${extracted.bodyHtml}
198137
198922
  if (lines.length > 0) {
198138
198923
  const hasVisionKey = !!(!skipVision && (process.env.OPENROUTER_API_KEY || process.env.GEMINI_API_KEY || process.env.GOOGLE_API_KEY));
198139
198924
  const header = hasVisionKey ? "# Asset Descriptions\n\nOne line per file. Read this instead of opening every image individually.\n\nTo find a specific brand or icon, **grep this file for the brand name in the description text** (e.g. `grep -i 'autodesk' asset-descriptions.md`). The Gemini Vision captions identify what's actually in each file \u2014 that's the agent's selector.\n\nThe `logo-<hash>.svg` filename prefix is a cheap structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). It is NOT a content claim \u2014 many `logo-*` files are nav icons or decorative shapes. Trust the captions, not the filename prefix.\n\n" : "# Asset Descriptions\n\n\u26A0\uFE0F GEMINI_API_KEY not set \u2014 descriptions below are catalog-derived (alt text, headings, section context, filename) instead of Vision-generated. To get richer Vision descriptions on the next capture, set GEMINI_API_KEY (or GOOGLE_API_KEY) and re-run.\n\nThe `logo-<hash>.svg` filename prefix is a structural hint (DOM said this SVG was inside a `<header>`, home-link `<a>`, or had an aria-label matching the page brand). To pick the actual brand logo without Vision, open the `logo-*` candidates in a previewer or rasterize them with `sharp` before referencing \u2014 composing a fake logo ships off-brand in the final video.\n\n";
198140
- writeFileSync51(
198141
- join120(outputDir, "extracted", "asset-descriptions.md"),
198925
+ writeFileSync53(
198926
+ join123(outputDir, "extracted", "asset-descriptions.md"),
198142
198927
  header + lines.map((l) => "- " + l).join("\n") + "\n",
198143
198928
  "utf-8"
198144
198929
  );
@@ -198156,8 +198941,8 @@ ${extracted.bodyHtml}
198156
198941
  const { createScrollContactSheet: createScrollContactSheet2, createAssetContactSheet: createAssetContactSheet2, createSvgContactSheet: createSvgContactSheet2 } = await Promise.resolve().then(() => (init_contactSheet(), contactSheet_exports));
198157
198942
  const contactSheetBudget = { remainingMs };
198158
198943
  const scrollSheets = await createScrollContactSheet2(
198159
- join120(outputDir, "screenshots"),
198160
- join120(outputDir, "screenshots", "contact-sheet.jpg"),
198944
+ join123(outputDir, "screenshots"),
198945
+ join123(outputDir, "screenshots", "contact-sheet.jpg"),
198161
198946
  contactSheetBudget
198162
198947
  );
198163
198948
  if (scrollSheets.length > 0)
@@ -198165,11 +198950,11 @@ ${extracted.bodyHtml}
198165
198950
  "design",
198166
198951
  `Screenshot contact sheet generated (${scrollSheets.length} page${scrollSheets.length > 1 ? "s" : ""})`
198167
198952
  );
198168
- const assetsImgDir = join120(outputDir, "assets");
198169
- if (existsSync111(assetsImgDir)) {
198953
+ const assetsImgDir = join123(outputDir, "assets");
198954
+ if (existsSync114(assetsImgDir)) {
198170
198955
  const assetSheets = await createAssetContactSheet2(
198171
198956
  assetsImgDir,
198172
- join120(outputDir, "assets", "contact-sheet.jpg"),
198957
+ join123(outputDir, "assets", "contact-sheet.jpg"),
198173
198958
  contactSheetBudget
198174
198959
  );
198175
198960
  if (assetSheets.length > 0)
@@ -198178,9 +198963,9 @@ ${extracted.bodyHtml}
198178
198963
  `Asset contact sheet generated (${assetSheets.length} page${assetSheets.length > 1 ? "s" : ""})`
198179
198964
  );
198180
198965
  }
198181
- const svgsDir = join120(outputDir, "assets", "svgs");
198182
- const assetsRootDir = join120(outputDir, "assets");
198183
- const svgOutputPath = existsSync111(svgsDir) ? join120(outputDir, "assets", "svgs", "contact-sheet.jpg") : join120(outputDir, "assets", "contact-sheet-svgs.jpg");
198966
+ const svgsDir = join123(outputDir, "assets", "svgs");
198967
+ const assetsRootDir = join123(outputDir, "assets");
198968
+ const svgOutputPath = existsSync114(svgsDir) ? join123(outputDir, "assets", "svgs", "contact-sheet.jpg") : join123(outputDir, "assets", "contact-sheet-svgs.jpg");
198184
198969
  const svgSheets = await createSvgContactSheet2(
198185
198970
  svgsDir,
198186
198971
  svgOutputPath,
@@ -198213,7 +198998,7 @@ ${extracted.bodyHtml}
198213
198998
  animationCatalog,
198214
198999
  screenshots.length > 0,
198215
199000
  discoveredLotties.length > 0,
198216
- existsSync111(join120(outputDir, "extracted", "shaders.json")),
199001
+ existsSync114(join123(outputDir, "extracted", "shaders.json")),
198217
199002
  catalogedAssets,
198218
199003
  progress,
198219
199004
  warnings,
@@ -198391,14 +199176,14 @@ var init_capture2 = __esm({
198391
199176
  let outputName = args.output ?? "capture";
198392
199177
  let outputDir = resolve73(outputName);
198393
199178
  if (isDefaultOutput) {
198394
- const { existsSync: existsSync126 } = await import("fs");
199179
+ const { existsSync: existsSync128 } = await import("fs");
198395
199180
  let n2 = 2;
198396
- while (existsSync126(outputDir) && n2 < 100) {
199181
+ while (existsSync128(outputDir) && n2 < 100) {
198397
199182
  outputName = `capture-${n2}`;
198398
199183
  outputDir = resolve73(outputName);
198399
199184
  n2++;
198400
199185
  }
198401
- if (existsSync126(outputDir)) {
199186
+ if (existsSync128(outputDir)) {
198402
199187
  console.error(`./capture-{2..99} are all taken. Pass -o <name> to pick a directory.`);
198403
199188
  failCommand();
198404
199189
  }
@@ -198487,11 +199272,11 @@ var init_capture2 = __esm({
198487
199272
  } catch (err) {
198488
199273
  const errMsg = normalizeErrorMessage(err);
198489
199274
  try {
198490
- const { mkdirSync: mkdirSync68, writeFileSync: writeFileSync61 } = await import("fs");
198491
- mkdirSync68(outputDir, { recursive: true });
199275
+ const { mkdirSync: mkdirSync70, writeFileSync: writeFileSync63 } = await import("fs");
199276
+ mkdirSync70(outputDir, { recursive: true });
198492
199277
  const isTimeout = /timeout|timed out/i.test(errMsg);
198493
199278
  const reason = isTimeout ? "Page navigation timed out \u2014 the site may be blocking headless browsers or requires authentication." : `Capture failed: ${errMsg}`;
198494
- writeFileSync61(
199279
+ writeFileSync63(
198495
199280
  `${outputDir}/BLOCKED.md`,
198496
199281
  `# Capture Failed
198497
199282
 
@@ -198555,33 +199340,33 @@ __export(state_exports, {
198555
199340
  stateFilePath: () => stateFilePath,
198556
199341
  writeStackOutputs: () => writeStackOutputs
198557
199342
  });
198558
- import { existsSync as existsSync113, mkdirSync as mkdirSync58, readdirSync as readdirSync38, readFileSync as readFileSync77, rmSync as rmSync34, writeFileSync as writeFileSync53 } from "fs";
198559
- import { dirname as dirname56, join as join121 } from "path";
199343
+ import { existsSync as existsSync115, mkdirSync as mkdirSync60, readdirSync as readdirSync38, readFileSync as readFileSync80, rmSync as rmSync34, writeFileSync as writeFileSync54 } from "fs";
199344
+ import { dirname as dirname56, join as join124 } from "path";
198560
199345
  function stateFilePath(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
198561
- return join121(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
199346
+ return join124(cwd, STATE_DIR_NAME, `${STATE_FILE_PREFIX}${stackName}.json`);
198562
199347
  }
198563
199348
  function writeStackOutputs(outputs, cwd = process.cwd()) {
198564
199349
  const path2 = stateFilePath(outputs.stackName, cwd);
198565
- mkdirSync58(dirname56(path2), { recursive: true });
198566
- writeFileSync53(path2, JSON.stringify(outputs, null, 2) + "\n");
199350
+ mkdirSync60(dirname56(path2), { recursive: true });
199351
+ writeFileSync54(path2, JSON.stringify(outputs, null, 2) + "\n");
198567
199352
  return path2;
198568
199353
  }
198569
199354
  function readStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
198570
199355
  const path2 = stateFilePath(stackName, cwd);
198571
- if (!existsSync113(path2)) return null;
199356
+ if (!existsSync115(path2)) return null;
198572
199357
  try {
198573
- return JSON.parse(readFileSync77(path2, "utf-8"));
199358
+ return JSON.parse(readFileSync80(path2, "utf-8"));
198574
199359
  } catch {
198575
199360
  return null;
198576
199361
  }
198577
199362
  }
198578
199363
  function deleteStackOutputs(stackName = DEFAULT_STACK_NAME, cwd = process.cwd()) {
198579
199364
  const path2 = stateFilePath(stackName, cwd);
198580
- if (existsSync113(path2)) rmSync34(path2);
199365
+ if (existsSync115(path2)) rmSync34(path2);
198581
199366
  }
198582
199367
  function listStackNames(cwd = process.cwd()) {
198583
- const dir = join121(cwd, STATE_DIR_NAME);
198584
- if (!existsSync113(dir)) return [];
199368
+ const dir = join124(cwd, STATE_DIR_NAME);
199369
+ if (!existsSync115(dir)) return [];
198585
199370
  return readdirSync38(dir).filter((f3) => f3.startsWith(STATE_FILE_PREFIX) && f3.endsWith(".json")).map((f3) => f3.slice(STATE_FILE_PREFIX.length, -".json".length));
198586
199371
  }
198587
199372
  function requireStack(stackName, cwd = process.cwd()) {
@@ -198612,8 +199397,8 @@ var init_state = __esm({
198612
199397
 
198613
199398
  // src/commands/lambda/sam.ts
198614
199399
  import { execFileSync as execFileSync18, spawnSync as spawnSync4 } from "child_process";
198615
- import { existsSync as existsSync114 } from "fs";
198616
- import { join as join123 } from "path";
199400
+ import { existsSync as existsSync116 } from "fs";
199401
+ import { join as join125 } from "path";
198617
199402
  function assertSamAvailable() {
198618
199403
  try {
198619
199404
  execFileSync18("sam", ["--version"], { stdio: "ignore" });
@@ -198633,8 +199418,8 @@ function assertAwsCliAvailable() {
198633
199418
  }
198634
199419
  }
198635
199420
  function locateSamTemplate(repoRoot2) {
198636
- const candidate = join123(repoRoot2, "examples", "aws-lambda", "template.yaml");
198637
- if (!existsSync114(candidate)) {
199421
+ const candidate = join125(repoRoot2, "examples", "aws-lambda", "template.yaml");
199422
+ if (!existsSync116(candidate)) {
198638
199423
  throw new Error(
198639
199424
  `[lambda] SAM template not found at ${candidate}. If you're running from an installed package, point --sam-template at your local copy of examples/aws-lambda/template.yaml.`
198640
199425
  );
@@ -198667,7 +199452,7 @@ function samDeploy(opts) {
198667
199452
  if (opts.awsProfile) {
198668
199453
  args.push("--profile", opts.awsProfile);
198669
199454
  }
198670
- const samDir = join123(opts.repoRoot, "examples", "aws-lambda");
199455
+ const samDir = join125(opts.repoRoot, "examples", "aws-lambda");
198671
199456
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
198672
199457
  if (result.status !== 0) {
198673
199458
  throw new Error(
@@ -198685,7 +199470,7 @@ function samDelete(opts) {
198685
199470
  if (opts.awsProfile) {
198686
199471
  args.push("--profile", opts.awsProfile);
198687
199472
  }
198688
- const samDir = join123(opts.repoRoot, "examples", "aws-lambda");
199473
+ const samDir = join125(opts.repoRoot, "examples", "aws-lambda");
198689
199474
  const result = spawnSync4("sam", args, { cwd: samDir, stdio: opts.stdio ?? "inherit" });
198690
199475
  if (result.status !== 0) {
198691
199476
  throw new Error(`[lambda] sam delete exited with code ${result.status ?? "unknown"}`);
@@ -198735,17 +199520,17 @@ var init_sam = __esm({
198735
199520
  });
198736
199521
 
198737
199522
  // src/commands/lambda/repoRoot.ts
198738
- import { existsSync as existsSync115 } from "fs";
199523
+ import { existsSync as existsSync117 } from "fs";
198739
199524
  import { dirname as dirname57, resolve as resolve74 } from "path";
198740
199525
  import { fileURLToPath as fileURLToPath15 } from "url";
198741
199526
  function repoRoot() {
198742
199527
  const override = process.env.HYPERFRAMES_REPO_ROOT;
198743
- if (override && existsSync115(resolve74(override, "packages", "aws-lambda", "package.json"))) {
199528
+ if (override && existsSync117(resolve74(override, "packages", "aws-lambda", "package.json"))) {
198744
199529
  return override;
198745
199530
  }
198746
199531
  let dir = dirname57(fileURLToPath15(import.meta.url));
198747
199532
  for (let depth = 0; depth < 12; depth++) {
198748
- if (existsSync115(resolve74(dir, "packages", "aws-lambda", "package.json"))) {
199533
+ if (existsSync117(resolve74(dir, "packages", "aws-lambda", "package.json"))) {
198749
199534
  return dir;
198750
199535
  }
198751
199536
  const parent = dirname57(dir);
@@ -198768,8 +199553,8 @@ __export(deploy_exports, {
198768
199553
  runDeploy: () => runDeploy
198769
199554
  });
198770
199555
  import { spawnSync as spawnSync5 } from "child_process";
198771
- import { existsSync as existsSync116 } from "fs";
198772
- import { join as join124, resolve as resolve75 } from "path";
199556
+ import { existsSync as existsSync118 } from "fs";
199557
+ import { join as join126, resolve as resolve75 } from "path";
198773
199558
  async function runDeploy(args = {}) {
198774
199559
  const resolved2 = {
198775
199560
  stackName: args.stackName ?? DEFAULT_STACK_NAME,
@@ -198786,8 +199571,8 @@ async function runDeploy(args = {}) {
198786
199571
  console.log(c.dim("\u2192 Building handler ZIP"));
198787
199572
  buildHandlerZip(root);
198788
199573
  } else {
198789
- const zip = join124(root, "packages", "aws-lambda", "dist", "handler.zip");
198790
- if (!existsSync116(zip)) {
199574
+ const zip = join126(root, "packages", "aws-lambda", "dist", "handler.zip");
199575
+ if (!existsSync118(zip)) {
198791
199576
  throw new Error(
198792
199577
  `--skip-build set but ${zip} does not exist. Run \`bun run --cwd packages/aws-lambda build:zip\` first or drop --skip-build.`
198793
199578
  );
@@ -198830,7 +199615,7 @@ async function runDeploy(args = {}) {
198830
199615
  function buildHandlerZip(root) {
198831
199616
  const result = spawnSync5(
198832
199617
  "bun",
198833
- ["run", "--cwd", join124(root, "packages", "aws-lambda"), "build:zip"],
199618
+ ["run", "--cwd", join126(root, "packages", "aws-lambda"), "build:zip"],
198834
199619
  { stdio: "inherit" }
198835
199620
  );
198836
199621
  if (result.status !== 0) {
@@ -198899,14 +199684,14 @@ var init_sites = __esm({
198899
199684
  });
198900
199685
 
198901
199686
  // src/commands/lambda/_dimensions.ts
198902
- import { readFileSync as readFileSync78 } from "fs";
198903
- import { join as join125 } from "path";
199687
+ import { readFileSync as readFileSync81 } from "fs";
199688
+ import { join as join127 } from "path";
198904
199689
  function warnOnDimensionMismatch(args) {
198905
199690
  if (args.quiet) return;
198906
199691
  if (args.outputResolution) return;
198907
199692
  let html;
198908
199693
  try {
198909
- html = readFileSync78(join125(args.projectDir, "index.html"), "utf-8");
199694
+ html = readFileSync81(join127(args.projectDir, "index.html"), "utf-8");
198910
199695
  } catch {
198911
199696
  return;
198912
199697
  }
@@ -198935,8 +199720,8 @@ __export(render_exports2, {
198935
199720
  buildLambdaRenderConfig: () => buildLambdaRenderConfig,
198936
199721
  runRender: () => runRender
198937
199722
  });
198938
- import { existsSync as existsSync117 } from "fs";
198939
- import { join as join126, resolve as resolvePath2 } from "path";
199723
+ import { existsSync as existsSync119 } from "fs";
199724
+ import { join as join128, resolve as resolvePath2 } from "path";
198940
199725
  async function loadSDK2() {
198941
199726
  return import("@hyperframes/aws-lambda/sdk");
198942
199727
  }
@@ -198952,8 +199737,8 @@ async function runRender(args) {
198952
199737
  });
198953
199738
  const variables = resolveVariablesArg(args.variables, args.variablesFile);
198954
199739
  if (variables && Object.keys(variables).length > 0) {
198955
- const indexPath2 = join126(projectDir, "index.html");
198956
- if (existsSync117(indexPath2)) {
199740
+ const indexPath2 = join128(projectDir, "index.html");
199741
+ if (existsSync119(indexPath2)) {
198957
199742
  const issues = validateVariablesAgainstProject(indexPath2, variables);
198958
199743
  reportVariableIssues(issues, { strict: args.strictVariables ?? false, quiet: args.json });
198959
199744
  } else if (args.strictVariables && !args.json) {
@@ -199086,8 +199871,8 @@ __export(render_batch_exports, {
199086
199871
  runRenderBatch: () => runRenderBatch,
199087
199872
  runWithConcurrencyLimit: () => runWithConcurrencyLimit
199088
199873
  });
199089
- import { existsSync as existsSync118, readFileSync as readFileSync79 } from "fs";
199090
- import { join as join127, resolve as resolvePath3 } from "path";
199874
+ import { existsSync as existsSync120, readFileSync as readFileSync83 } from "fs";
199875
+ import { join as join129, resolve as resolvePath3 } from "path";
199091
199876
  async function loadSDK3() {
199092
199877
  return import("@hyperframes/aws-lambda/sdk");
199093
199878
  }
@@ -199095,7 +199880,7 @@ async function runRenderBatch(args) {
199095
199880
  const projectDir = resolvePath3(args.projectDir);
199096
199881
  const stack = requireStack(args.stackName);
199097
199882
  const batchPath = resolvePath3(args.batch);
199098
- if (!existsSync118(batchPath)) {
199883
+ if (!existsSync120(batchPath)) {
199099
199884
  errorBox("Batch file not found", `No such file: ${batchPath}`);
199100
199885
  failCommand();
199101
199886
  }
@@ -199111,7 +199896,7 @@ async function runRenderBatch(args) {
199111
199896
  outputResolution: args.outputResolution,
199112
199897
  quiet: args.json
199113
199898
  });
199114
- const schema = loadProjectVariableSchema(join127(projectDir, "index.html"));
199899
+ const schema = loadProjectVariableSchema(join129(projectDir, "index.html"));
199115
199900
  const strict = args.strictVariables ?? false;
199116
199901
  let hadStrictIssue = false;
199117
199902
  for (const { entry, lineNumber } of entries2) {
@@ -199246,7 +200031,7 @@ function buildLambdaBatchRenderConfig(args) {
199246
200031
  return config;
199247
200032
  }
199248
200033
  function parseBatchFile(path2) {
199249
- const raw = readFileSync79(path2, "utf8");
200034
+ const raw = readFileSync83(path2, "utf8");
199250
200035
  const lines = raw.split(/\r?\n/);
199251
200036
  const out = [];
199252
200037
  for (let i2 = 0; i2 < lines.length; i2++) {
@@ -199440,7 +200225,7 @@ __export(policies_exports, {
199440
200225
  runPolicies: () => runPolicies,
199441
200226
  validatePolicy: () => validatePolicy
199442
200227
  });
199443
- import { readFileSync as readFileSync80 } from "fs";
200228
+ import { readFileSync as readFileSync84 } from "fs";
199444
200229
  function allRequiredActions() {
199445
200230
  const set = /* @__PURE__ */ new Set();
199446
200231
  for (const group of Object.values(REQUIRED_ACTIONS)) {
@@ -199546,7 +200331,7 @@ async function runPolicies(args) {
199546
200331
  }
199547
200332
  }
199548
200333
  function validatePolicy(policyPath) {
199549
- const raw = readFileSync80(policyPath, "utf-8");
200334
+ const raw = readFileSync84(policyPath, "utf-8");
199550
200335
  const parsed = JSON.parse(raw);
199551
200336
  const statements = Array.isArray(parsed.Statement) ? parsed.Statement : parsed.Statement ? [
199552
200337
  parsed.Statement
@@ -200157,9 +200942,9 @@ __export(cloudrun_exports, {
200157
200942
  missingCloudRunAdapterMessage: () => missingCloudRunAdapterMessage
200158
200943
  });
200159
200944
  import { spawnSync as spawnSync6 } from "child_process";
200160
- import { existsSync as existsSync119, mkdirSync as mkdirSync59, readFileSync as readFileSync81, writeFileSync as writeFileSync54 } from "fs";
200161
- import { homedir as homedir20 } from "os";
200162
- import { join as join128, resolve as resolve76 } from "path";
200945
+ import { existsSync as existsSync121, mkdirSync as mkdirSync61, readFileSync as readFileSync85, writeFileSync as writeFileSync55 } from "fs";
200946
+ import { homedir as homedir22 } from "os";
200947
+ import { join as join130, resolve as resolve76 } from "path";
200163
200948
  function loadCloudRunAdapter() {
200164
200949
  cloudRunAdapterPromise ??= Promise.all([
200165
200950
  import("@hyperframes/gcp-cloud-run/sdk"),
@@ -200178,14 +200963,14 @@ Or, for an opt-in project setup:
200178
200963
  ${c.accent("npm install @hyperframes/gcp-cloud-run")}`;
200179
200964
  }
200180
200965
  function stateDir() {
200181
- return join128(homedir20(), ".hyperframes");
200966
+ return join130(homedir22(), ".hyperframes");
200182
200967
  }
200183
200968
  function statePath() {
200184
- return join128(stateDir(), "cloudrun-state.json");
200969
+ return join130(stateDir(), "cloudrun-state.json");
200185
200970
  }
200186
200971
  function writeState(state) {
200187
- mkdirSync59(stateDir(), { recursive: true });
200188
- writeFileSync54(statePath(), JSON.stringify(state, null, 2));
200972
+ mkdirSync61(stateDir(), { recursive: true });
200973
+ writeFileSync55(statePath(), JSON.stringify(state, null, 2));
200189
200974
  }
200190
200975
  function readState(args) {
200191
200976
  const overrides = {
@@ -200193,9 +200978,9 @@ function readState(args) {
200193
200978
  region: args.region
200194
200979
  };
200195
200980
  let base2 = {};
200196
- if (existsSync119(statePath())) {
200981
+ if (existsSync121(statePath())) {
200197
200982
  try {
200198
- base2 = JSON.parse(readFileSync81(statePath(), "utf8"));
200983
+ base2 = JSON.parse(readFileSync85(statePath(), "utf8"));
200199
200984
  } catch {
200200
200985
  }
200201
200986
  }
@@ -200338,13 +201123,13 @@ function machineVars(args, project, region, image) {
200338
201123
  }
200339
201124
  function findRepoRoot(tfDir) {
200340
201125
  const candidate = resolve76(tfDir, "..", "..", "..");
200341
- if (existsSync119(join128(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
201126
+ if (existsSync121(join130(candidate, "packages", "gcp-cloud-run", "Dockerfile"))) return candidate;
200342
201127
  return null;
200343
201128
  }
200344
201129
  function writeCloudBuildConfig(image) {
200345
- const cfgPath = join128(stateDir(), "cloudrun-cloudbuild.yaml");
200346
- mkdirSync59(stateDir(), { recursive: true });
200347
- writeFileSync54(
201130
+ const cfgPath = join130(stateDir(), "cloudrun-cloudbuild.yaml");
201131
+ mkdirSync61(stateDir(), { recursive: true });
201132
+ writeFileSync55(
200348
201133
  cfgPath,
200349
201134
  [
200350
201135
  "steps:",
@@ -200487,7 +201272,7 @@ async function runRenderBatch2(args) {
200487
201272
  failCommand();
200488
201273
  }
200489
201274
  const fps = resolveCloudRunFps(args, projectDir, "render-batch");
200490
- if (!existsSync119(resolve76(batchPath))) {
201275
+ if (!existsSync121(resolve76(batchPath))) {
200491
201276
  console.error(`[cloudrun render-batch] batch file not found: ${batchPath}`);
200492
201277
  failCommand();
200493
201278
  }
@@ -200554,7 +201339,7 @@ async function runRenderBatch2(args) {
200554
201339
  if (failed.length > 0) failCommand();
200555
201340
  }
200556
201341
  function parseBatchFile2(path2) {
200557
- const lines = readFileSync81(path2, "utf8").split(/\r?\n/);
201342
+ const lines = readFileSync85(path2, "utf8").split(/\r?\n/);
200558
201343
  const entries2 = [];
200559
201344
  lines.forEach((line2, idx) => {
200560
201345
  const trimmed = line2.trim();
@@ -200579,7 +201364,7 @@ function parseBatchFile2(path2) {
200579
201364
  async function runDestroy2(args) {
200580
201365
  const { getTerraformModuleDir } = await loadCloudRunAdapter();
200581
201366
  const tfDir = getTerraformModuleDir();
200582
- const state = existsSync119(statePath()) ? JSON.parse(readFileSync81(statePath(), "utf8")) : {};
201367
+ const state = existsSync121(statePath()) ? JSON.parse(readFileSync85(statePath(), "utf8")) : {};
200583
201368
  const project = args.project ?? state.projectId;
200584
201369
  const region = args.region ?? state.region ?? "us-central1";
200585
201370
  const image = args.image ?? "unused:latest";
@@ -200634,8 +201419,8 @@ function resolveAndValidateVariables(args, projectDir) {
200634
201419
  args["variables-file"]
200635
201420
  );
200636
201421
  if (variables && Object.keys(variables).length > 0) {
200637
- const indexPath2 = join128(projectDir, "index.html");
200638
- if (existsSync119(indexPath2)) {
201422
+ const indexPath2 = join130(projectDir, "index.html");
201423
+ if (existsSync121(indexPath2)) {
200639
201424
  const issues = validateVariablesAgainstProject(indexPath2, variables);
200640
201425
  reportVariableIssues(issues, {
200641
201426
  strict: Boolean(args["strict-variables"]),
@@ -200881,7 +201666,7 @@ ${HELP2}`);
200881
201666
  });
200882
201667
 
200883
201668
  // src/cloud/detectAspectRatio.ts
200884
- import { readFileSync as readFileSync83 } from "fs";
201669
+ import { readFileSync as readFileSync86 } from "fs";
200885
201670
  function extractAttributeNumber(tag, re2) {
200886
201671
  const match = tag.match(re2);
200887
201672
  if (!match) return null;
@@ -200893,7 +201678,7 @@ function extractAttributeNumber(tag, re2) {
200893
201678
  function detectAspectRatioFromHtml(entryHtmlPath) {
200894
201679
  let html;
200895
201680
  try {
200896
- html = readFileSync83(entryHtmlPath, "utf-8");
201681
+ html = readFileSync86(entryHtmlPath, "utf-8");
200897
201682
  } catch (err) {
200898
201683
  return { kind: "read-error", error: normalizeErrorMessage(err) };
200899
201684
  }
@@ -200996,7 +201781,7 @@ var init_poll = __esm({
200996
201781
  });
200997
201782
 
200998
201783
  // src/cloud/download.ts
200999
- import { createWriteStream as createWriteStream5, mkdirSync as mkdirSync60, unlinkSync as unlinkSync11 } from "fs";
201784
+ import { createWriteStream as createWriteStream5, mkdirSync as mkdirSync63, unlinkSync as unlinkSync12 } from "fs";
201000
201785
  import { dirname as dirname58 } from "path";
201001
201786
  async function downloadToFile(url, destPath, options = {}) {
201002
201787
  const fetchImpl = options.fetchImpl ?? fetch;
@@ -201007,7 +201792,7 @@ async function downloadToFile(url, destPath, options = {}) {
201007
201792
  if (!res.body) {
201008
201793
  throw new Error(`Failed to download ${url}: empty response body`);
201009
201794
  }
201010
- mkdirSync60(dirname58(destPath), { recursive: true });
201795
+ mkdirSync63(dirname58(destPath), { recursive: true });
201011
201796
  const totalHeader = res.headers.get("content-length");
201012
201797
  const total = totalHeader ? Number.parseInt(totalHeader, 10) : void 0;
201013
201798
  const totalOpt = total !== void 0 && Number.isFinite(total) ? total : void 0;
@@ -201037,7 +201822,7 @@ async function downloadToFile(url, destPath, options = {}) {
201037
201822
  await closeFile(file);
201038
201823
  if (errored) {
201039
201824
  try {
201040
- unlinkSync11(destPath);
201825
+ unlinkSync12(destPath);
201041
201826
  } catch {
201042
201827
  }
201043
201828
  }
@@ -201487,9 +202272,9 @@ var init_parsing = __esm({
201487
202272
  });
201488
202273
 
201489
202274
  // src/cloud/upload.ts
201490
- import { createHash as createHash20 } from "crypto";
202275
+ import { createHash as createHash21 } from "crypto";
201491
202276
  function sha256Hex2(bytes) {
201492
- return createHash20("sha256").update(bytes).digest("hex");
202277
+ return createHash21("sha256").update(bytes).digest("hex");
201493
202278
  }
201494
202279
  function sleep4(ms) {
201495
202280
  return new Promise((r2) => setTimeout(r2, ms));
@@ -201601,7 +202386,7 @@ __export(render_exports3, {
201601
202386
  validateResolutionFormatCombo: () => validateResolutionFormatCombo
201602
202387
  });
201603
202388
  import { isAbsolute as isAbsolute17, relative as relative27, resolve as resolvePath4 } from "path";
201604
- import { existsSync as existsSync120 } from "fs";
202389
+ import { existsSync as existsSync122 } from "fs";
201605
202390
  function parsePollIntervalMs(raw) {
201606
202391
  const n2 = parseNumericFlag(raw, { flag: "--poll-interval", min: 1 });
201607
202392
  return n2 === void 0 ? DEFAULT_POLL_INTERVAL_MS : Math.round(n2 * 1e3);
@@ -201651,7 +202436,7 @@ function resolveAspectRatioForSubmit(project, compositionArg, explicit, asJson)
201651
202436
  const dir = project.dir ?? ".";
201652
202437
  const entryRelative = compositionArg ?? "index.html";
201653
202438
  const entryPath = resolvePath4(dir, entryRelative);
201654
- if (!existsSync120(entryPath)) {
202439
+ if (!existsSync122(entryPath)) {
201655
202440
  errorBox(
201656
202441
  "Composition not found",
201657
202442
  `Entry file "${entryRelative}" does not exist in ${dir}.`,
@@ -203682,7 +204467,7 @@ var init_parseFigmaRef = __esm({
203682
204467
  });
203683
204468
 
203684
204469
  // ../core/dist/figma/freeze.js
203685
- import { copyFileSync as copyFileSync11, mkdirSync as mkdirSync61, rmSync as rmSync35, statSync as statSync39, writeFileSync as writeFileSync55 } from "fs";
204470
+ import { copyFileSync as copyFileSync11, mkdirSync as mkdirSync64, rmSync as rmSync35, statSync as statSync39, writeFileSync as writeFileSync56 } from "fs";
203686
204471
  import { dirname as dirname59 } from "path";
203687
204472
  function exceedsFreezeCap(byteLength) {
203688
204473
  return byteLength > MAX_FREEZE_BYTES;
@@ -203692,14 +204477,14 @@ function freezeBytes(bytes, destPath) {
203692
204477
  throw new Error("freeze failed: empty bytes");
203693
204478
  if (exceedsFreezeCap(bytes.length))
203694
204479
  throw new Error(`freeze failed: ${bytes.length} bytes exceeds ${MAX_FREEZE_BYTES} cap`);
203695
- mkdirSync61(dirname59(destPath), { recursive: true });
204480
+ mkdirSync64(dirname59(destPath), { recursive: true });
203696
204481
  try {
203697
- writeFileSync55(destPath, bytes, { flag: "wx" });
204482
+ writeFileSync56(destPath, bytes, { flag: "wx" });
203698
204483
  } catch (err) {
203699
204484
  if (err.code !== "EEXIST")
203700
204485
  throw err;
203701
204486
  rmSync35(destPath);
203702
- writeFileSync55(destPath, bytes, { flag: "wx" });
204487
+ writeFileSync56(destPath, bytes, { flag: "wx" });
203703
204488
  }
203704
204489
  return bytes.length;
203705
204490
  }
@@ -203712,12 +204497,12 @@ var init_freeze = __esm({
203712
204497
  });
203713
204498
 
203714
204499
  // ../core/dist/figma/jsonl.js
203715
- import { existsSync as existsSync121, readFileSync as readFileSync84 } from "fs";
204500
+ import { existsSync as existsSync123, readFileSync as readFileSync87 } from "fs";
203716
204501
  function readJsonlValues(path2) {
203717
- if (!existsSync121(path2))
204502
+ if (!existsSync123(path2))
203718
204503
  return [];
203719
204504
  const out = [];
203720
- for (const line2 of readFileSync84(path2, "utf8").split(/\r?\n/)) {
204505
+ for (const line2 of readFileSync87(path2, "utf8").split(/\r?\n/)) {
203721
204506
  const trimmed = line2.trim();
203722
204507
  if (trimmed.length === 0)
203723
204508
  continue;
@@ -203736,16 +204521,16 @@ var init_jsonl = __esm({
203736
204521
  });
203737
204522
 
203738
204523
  // ../core/dist/figma/manifest.js
203739
- import { appendFileSync as appendFileSync2, existsSync as existsSync122, mkdirSync as mkdirSync63, readFileSync as readFileSync85, writeFileSync as writeFileSync56 } from "fs";
203740
- import { join as join129 } from "path";
204524
+ import { appendFileSync as appendFileSync2, existsSync as existsSync124, mkdirSync as mkdirSync65, readFileSync as readFileSync88, writeFileSync as writeFileSync57 } from "fs";
204525
+ import { join as join131 } from "path";
203741
204526
  function mediaDir(projectDir) {
203742
- return join129(projectDir, ".media");
204527
+ return join131(projectDir, ".media");
203743
204528
  }
203744
204529
  function manifestPath(projectDir) {
203745
- return join129(mediaDir(projectDir), MANIFEST_FILE2);
204530
+ return join131(mediaDir(projectDir), MANIFEST_FILE2);
203746
204531
  }
203747
204532
  function typeDirPath(projectDir, type) {
203748
- return join129(mediaDir(projectDir), TYPE_DIRS[type]);
204533
+ return join131(mediaDir(projectDir), TYPE_DIRS[type]);
203749
204534
  }
203750
204535
  function isFigmaManifestRecord(value) {
203751
204536
  if (typeof value !== "object" || value === null)
@@ -203769,7 +204554,7 @@ function readManifest(projectDir) {
203769
204554
  return readJsonlValues(manifestPath(projectDir)).filter(isFigmaManifestRecord);
203770
204555
  }
203771
204556
  function appendRecord(projectDir, record) {
203772
- mkdirSync63(typeDirPath(projectDir, record.type), { recursive: true });
204557
+ mkdirSync65(typeDirPath(projectDir, record.type), { recursive: true });
203773
204558
  appendFileSync2(manifestPath(projectDir), JSON.stringify(record) + "\n");
203774
204559
  }
203775
204560
  function findAllByFigmaNode(projectDir, fileKey, nodeId) {
@@ -203777,7 +204562,7 @@ function findAllByFigmaNode(projectDir, fileKey, nodeId) {
203777
204562
  }
203778
204563
  function updateRecord(projectDir, record) {
203779
204564
  const p2 = manifestPath(projectDir);
203780
- const lines = readFileSync85(p2, "utf8").split(/\r?\n/);
204565
+ const lines = readFileSync88(p2, "utf8").split(/\r?\n/);
203781
204566
  const out = lines.map((line2) => {
203782
204567
  const trimmed = line2.trim();
203783
204568
  if (trimmed.length === 0)
@@ -203790,15 +204575,15 @@ function updateRecord(projectDir, record) {
203790
204575
  }
203791
204576
  return line2;
203792
204577
  });
203793
- writeFileSync56(p2, out.join("\n"));
204578
+ writeFileSync57(p2, out.join("\n"));
203794
204579
  }
203795
204580
  function nextId(projectDir, type) {
203796
204581
  const re2 = new RegExp(`^${type}_(\\d+)$`);
203797
204582
  let max = 0;
203798
204583
  const p2 = manifestPath(projectDir);
203799
- if (!existsSync122(p2))
204584
+ if (!existsSync124(p2))
203800
204585
  return `${type}_001`;
203801
- for (const line2 of readFileSync85(p2, "utf8").split(/\r?\n/)) {
204586
+ for (const line2 of readFileSync88(p2, "utf8").split(/\r?\n/)) {
203802
204587
  const trimmed = line2.trim();
203803
204588
  if (trimmed.length === 0)
203804
204589
  continue;
@@ -203831,13 +204616,13 @@ var init_manifest = __esm({
203831
204616
  });
203832
204617
 
203833
204618
  // ../core/dist/figma/mediaIndex.js
203834
- import { mkdirSync as mkdirSync64, writeFileSync as writeFileSync57 } from "fs";
203835
- import { dirname as dirname60, join as join130 } from "path";
204619
+ import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync58 } from "fs";
204620
+ import { dirname as dirname60, join as join133 } from "path";
203836
204621
  function isRow(value) {
203837
204622
  return typeof value === "object" && value !== null;
203838
204623
  }
203839
204624
  function indexPath(projectDir) {
203840
- return join130(mediaDir(projectDir), "index.md");
204625
+ return join133(mediaDir(projectDir), "index.md");
203841
204626
  }
203842
204627
  function pad(str, len2) {
203843
204628
  return String(str ?? "").padEnd(len2);
@@ -203882,8 +204667,8 @@ function regenerateIndex(projectDir) {
203882
204667
  const records = readJsonlValues(manifestPath(projectDir)).filter(isRow);
203883
204668
  const content = generateIndexContent(records);
203884
204669
  const p2 = indexPath(projectDir);
203885
- mkdirSync64(dirname60(p2), { recursive: true });
203886
- writeFileSync57(p2, content);
204670
+ mkdirSync66(dirname60(p2), { recursive: true });
204671
+ writeFileSync58(p2, content);
203887
204672
  return content;
203888
204673
  }
203889
204674
  var init_mediaIndex = __esm({
@@ -203948,10 +204733,10 @@ var init_sanitizeSvg = __esm({
203948
204733
  });
203949
204734
 
203950
204735
  // ../core/dist/figma/bindings.js
203951
- import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync65, writeFileSync as writeFileSync58 } from "fs";
203952
- import { join as join131 } from "path";
204736
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync67, writeFileSync as writeFileSync59 } from "fs";
204737
+ import { join as join134 } from "path";
203953
204738
  function bindingsPath(projectDir) {
203954
- return join131(mediaDir(projectDir), BINDINGS_FILE);
204739
+ return join134(mediaDir(projectDir), BINDINGS_FILE);
203955
204740
  }
203956
204741
  function isRecord15(value) {
203957
204742
  return typeof value === "object" && value !== null;
@@ -203968,9 +204753,9 @@ function readBindings(projectDir) {
203968
204753
  function upsertBindings(projectDir, records) {
203969
204754
  const incoming = new Set(records.map((r2) => r2.figmaId));
203970
204755
  const survivors = readLines(projectDir).filter((line2) => !(isBindingRecord(line2) && incoming.has(line2.figmaId)));
203971
- mkdirSync65(mediaDir(projectDir), { recursive: true });
204756
+ mkdirSync67(mediaDir(projectDir), { recursive: true });
203972
204757
  const lines = [...survivors, ...records].map((r2) => JSON.stringify(r2)).join("\n");
203973
- writeFileSync58(bindingsPath(projectDir), lines.length > 0 ? lines + "\n" : "");
204758
+ writeFileSync59(bindingsPath(projectDir), lines.length > 0 ? lines + "\n" : "");
203974
204759
  }
203975
204760
  var BINDINGS_FILE;
203976
204761
  var init_bindings = __esm({
@@ -204551,8 +205336,8 @@ __export(asset_exports, {
204551
205336
  runAssetImport: () => runAssetImport,
204552
205337
  runAssetImportMany: () => runAssetImportMany
204553
205338
  });
204554
- import { existsSync as existsSync123 } from "fs";
204555
- import { join as join133, relative as relative28 } from "path";
205339
+ import { existsSync as existsSync125 } from "fs";
205340
+ import { join as join135, relative as relative28 } from "path";
204556
205341
  function gatherAssetRefs(positionals) {
204557
205342
  return positionals.flatMap((r2) => /^https?:/i.test(r2.trim()) ? [r2] : r2.split(",")).map((r2) => r2.trim()).filter((r2) => r2.length > 0);
204558
205343
  }
@@ -204566,7 +205351,7 @@ function requireNodeRef(refInput) {
204566
205351
  }
204567
205352
  function reuseExisting(fileKey, nodeId, opts, version2, deps, description, entity) {
204568
205353
  const existing = findAllByFigmaNode(deps.projectDir, fileKey, nodeId).find(
204569
- (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync123(join133(deps.projectDir, r2.path))
205354
+ (r2) => r2.provenance.format === opts.format && (r2.provenance.scale ?? 1) === (opts.scale ?? 1) && r2.provenance.version === version2 && existsSync125(join135(deps.projectDir, r2.path))
204570
205355
  );
204571
205356
  if (!existing) return null;
204572
205357
  let record = existing;
@@ -204589,7 +205374,7 @@ async function freezeAndRecord(fileKey, nodeId, url, ext, opts, version2, deps,
204589
205374
  bytes = new TextEncoder().encode(sanitizeSvg(new TextDecoder().decode(bytes)));
204590
205375
  }
204591
205376
  const id = nextId(deps.projectDir, "image");
204592
- const destAbs = join133(typeDirPath(deps.projectDir, "image"), `${id}.${ext}`);
205377
+ const destAbs = join135(typeDirPath(deps.projectDir, "image"), `${id}.${ext}`);
204593
205378
  freezeBytes(bytes, destAbs);
204594
205379
  const record = {
204595
205380
  id,
@@ -204758,12 +205543,12 @@ __export(tokens_exports, {
204758
205543
  default: () => tokens_default,
204759
205544
  runTokensImport: () => runTokensImport
204760
205545
  });
204761
- import { writeFileSync as writeFileSync59 } from "fs";
204762
- import { join as join134 } from "path";
205546
+ import { writeFileSync as writeFileSync60 } from "fs";
205547
+ import { join as join136 } from "path";
204763
205548
  async function runTokensImport(refInput, deps) {
204764
205549
  const { fileKey } = parseFigmaRef(refInput);
204765
205550
  const { version: version2 } = await deps.client.fileVersion(fileKey);
204766
- const sidecarPath = join134(deps.projectDir, "figma-tokens.json");
205551
+ const sidecarPath = join136(deps.projectDir, "figma-tokens.json");
204767
205552
  let vars = null;
204768
205553
  try {
204769
205554
  vars = await deps.client.variables(fileKey);
@@ -204773,7 +205558,7 @@ async function runTokensImport(refInput, deps) {
204773
205558
  if (vars !== null) {
204774
205559
  const out = tokensToVariables(vars, { fileKey, version: version2 });
204775
205560
  upsertBindings(deps.projectDir, out.bindings);
204776
- writeFileSync59(sidecarPath, JSON.stringify(out.sidecar, null, 2) + "\n");
205561
+ writeFileSync60(sidecarPath, JSON.stringify(out.sidecar, null, 2) + "\n");
204777
205562
  return { mode: "variables", entries: out.entries, sidecarPath };
204778
205563
  }
204779
205564
  const styles = await deps.client.styles(fileKey);
@@ -204787,7 +205572,7 @@ async function runTokensImport(refInput, deps) {
204787
205572
  value: null
204788
205573
  }))
204789
205574
  };
204790
- writeFileSync59(sidecarPath, JSON.stringify(sidecar, null, 2) + "\n");
205575
+ writeFileSync60(sidecarPath, JSON.stringify(sidecar, null, 2) + "\n");
204791
205576
  return { mode: "styles", entries: [], sidecarPath, styleCount: styles.length };
204792
205577
  }
204793
205578
  var tokens_default;
@@ -204837,8 +205622,8 @@ __export(component_exports, {
204837
205622
  default: () => component_default,
204838
205623
  runComponentImport: () => runComponentImport
204839
205624
  });
204840
- import { existsSync as existsSync124, mkdirSync as mkdirSync66, writeFileSync as writeFileSync60 } from "fs";
204841
- import { join as join135, relative as relative29 } from "path";
205625
+ import { existsSync as existsSync126, mkdirSync as mkdirSync68, writeFileSync as writeFileSync61 } from "fs";
205626
+ import { join as join137, relative as relative29 } from "path";
204842
205627
  function escapeAttr2(value) {
204843
205628
  return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
204844
205629
  }
@@ -204849,20 +205634,20 @@ async function runComponentImport(refInput, deps) {
204849
205634
  const bindings = resolveBindings(tree, readBindings(deps.projectDir));
204850
205635
  const mapped = nodeToHtml(tree, bindings, { rootName: deps.name });
204851
205636
  const name = slugify(deps.name ?? tree.name);
204852
- const componentDir = join135(deps.projectDir, "compositions", "components", name);
204853
- if (existsSync124(componentDir))
205637
+ const componentDir = join137(deps.projectDir, "compositions", "components", name);
205638
+ if (existsSync126(componentDir))
204854
205639
  console.warn(
204855
205640
  `component dir compositions/components/${name} already exists \u2014 overwriting (rename the figma frame for a separate import)`
204856
205641
  );
204857
- mkdirSync66(componentDir, { recursive: true });
205642
+ mkdirSync68(componentDir, { recursive: true });
204858
205643
  const { html, frozenAssets, failedRasterize } = await rasterizeFallback(
204859
205644
  mapped,
204860
205645
  ref2.fileKey,
204861
205646
  componentDir,
204862
205647
  deps
204863
205648
  );
204864
- const htmlFile = join135(componentDir, `${name}.html`);
204865
- writeFileSync60(htmlFile, html + "\n");
205649
+ const htmlFile = join137(componentDir, `${name}.html`);
205650
+ writeFileSync61(htmlFile, html + "\n");
204866
205651
  const registryItem = {
204867
205652
  name,
204868
205653
  type: "hyperframes:component",
@@ -204882,8 +205667,8 @@ async function runComponentImport(refInput, deps) {
204882
205667
  }))
204883
205668
  ]
204884
205669
  };
204885
- writeFileSync60(
204886
- join135(componentDir, "registry-item.json"),
205670
+ writeFileSync61(
205671
+ join137(componentDir, "registry-item.json"),
204887
205672
  JSON.stringify(registryItem, null, 2) + "\n"
204888
205673
  );
204889
205674
  return {
@@ -204908,7 +205693,7 @@ async function rasterizeFallback(mapped, fileKey, componentDir, deps) {
204908
205693
  continue;
204909
205694
  }
204910
205695
  frozenAssets.push(asset.record.path);
204911
- const srcRel = relative29(componentDir, join135(deps.projectDir, asset.record.path)).replaceAll(
205696
+ const srcRel = relative29(componentDir, join137(deps.projectDir, asset.record.path)).replaceAll(
204912
205697
  "\\",
204913
205698
  "/"
204914
205699
  );
@@ -205055,9 +205840,9 @@ __export(autoUpdate_exports, {
205055
205840
  scheduleBackgroundInstall: () => scheduleBackgroundInstall
205056
205841
  });
205057
205842
  import { spawn as spawn16 } from "child_process";
205058
- import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync67, openSync as openSync8 } from "fs";
205059
- import { homedir as homedir21 } from "os";
205060
- import { join as join136 } from "path";
205843
+ import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync69, openSync as openSync8 } from "fs";
205844
+ import { homedir as homedir23 } from "os";
205845
+ import { join as join138 } from "path";
205061
205846
  import { compareVersions as compareVersions3 } from "compare-versions";
205062
205847
  function isAutoInstallDisabled() {
205063
205848
  if (isDevMode()) return true;
@@ -205072,15 +205857,15 @@ function majorOf(version2) {
205072
205857
  }
205073
205858
  function log(line2) {
205074
205859
  try {
205075
- mkdirSync67(CONFIG_DIR3, { recursive: true, mode: 448 });
205860
+ mkdirSync69(CONFIG_DIR3, { recursive: true, mode: 448 });
205076
205861
  appendFileSync4(LOG_FILE, `${(/* @__PURE__ */ new Date()).toISOString()} ${line2}
205077
205862
  `, { mode: 384 });
205078
205863
  } catch {
205079
205864
  }
205080
205865
  }
205081
205866
  function launchDetachedInstall(invocation, displayCommand, version2) {
205082
- mkdirSync67(CONFIG_DIR3, { recursive: true, mode: 448 });
205083
- const configFile = join136(CONFIG_DIR3, "config.json");
205867
+ mkdirSync69(CONFIG_DIR3, { recursive: true, mode: 448 });
205868
+ const configFile = join138(CONFIG_DIR3, "config.json");
205084
205869
  const nodeScript = `
205085
205870
  const { execFile } = require("node:child_process");
205086
205871
  const { readFileSync, renameSync, writeFileSync } = require("node:fs");
@@ -205201,8 +205986,8 @@ var init_autoUpdate = __esm({
205201
205986
  init_config();
205202
205987
  init_env();
205203
205988
  init_installerDetection();
205204
- CONFIG_DIR3 = join136(homedir21(), ".hyperframes");
205205
- LOG_FILE = join136(CONFIG_DIR3, "auto-update.log");
205989
+ CONFIG_DIR3 = join138(homedir23(), ".hyperframes");
205990
+ LOG_FILE = join138(CONFIG_DIR3, "auto-update.log");
205206
205991
  PENDING_TIMEOUT_MS = 10 * 60 * 1e3;
205207
205992
  }
205208
205993
  });
@@ -205393,9 +206178,9 @@ var init_help = __esm({
205393
206178
  init_version();
205394
206179
  init_dist();
205395
206180
  init_runId();
205396
- import { dirname as dirname61, join as join137 } from "path";
206181
+ import { dirname as dirname61, join as join139 } from "path";
205397
206182
  import { fileURLToPath as fileURLToPath16 } from "url";
205398
- import { existsSync as existsSync125 } from "fs";
206183
+ import { existsSync as existsSync127 } from "fs";
205399
206184
 
205400
206185
  // src/utils/reject-unknown-flags.ts
205401
206186
  var ALWAYS_KNOWN = /* @__PURE__ */ new Set(["help", "h", "version", "v", "json"]);
@@ -205512,8 +206297,8 @@ for (const stream of [process.stdout, process.stderr]) {
205512
206297
  }
205513
206298
  (() => {
205514
206299
  const here = dirname61(fileURLToPath16(import.meta.url));
205515
- const shader = join137(here, "shaderTransitionWorker.js");
205516
- if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync125(shader)) {
206300
+ const shader = join139(here, "shaderTransitionWorker.js");
206301
+ if (!process.env.HF_SHADER_WORKER_ENTRY && existsSync127(shader)) {
205517
206302
  process.env.HF_SHADER_WORKER_ENTRY = shader;
205518
206303
  }
205519
206304
  })();
@@ -205525,10 +206310,10 @@ if (rootVersionRequested) {
205525
206310
  process.exit(0);
205526
206311
  }
205527
206312
  try {
205528
- const { readFileSync: readFileSync86 } = await import("fs");
206313
+ const { readFileSync: readFileSync89 } = await import("fs");
205529
206314
  const { resolve: resolve77 } = await import("path");
205530
206315
  const envPath = resolve77(process.cwd(), ".env");
205531
- const envContent = readFileSync86(envPath, "utf-8");
206316
+ const envContent = readFileSync89(envPath, "utf-8");
205532
206317
  for (const rawLine of envContent.split("\n")) {
205533
206318
  let line2 = rawLine.trim();
205534
206319
  if (!line2 || line2.startsWith("#")) continue;