hyperframes 0.8.59 → 0.8.61

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.8.59" : "0.0.0-dev";
53
+ VERSION = true ? "0.8.61" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -93100,17 +93100,34 @@ function* riffChunks(buffer) {
93100
93100
  offset2 += 8 + size + size % 2;
93101
93101
  }
93102
93102
  }
93103
+ function extensibleFormatTag(fmt) {
93104
+ const extraSize = fmt.readUInt16LE(16);
93105
+ if (extraSize < 22 || 18 + extraSize > fmt.length) return null;
93106
+ return EXTENSIBLE_FORMATS.get(fmt.toString("hex", 24, 40)) ?? null;
93107
+ }
93108
+ function wavFormatTag(buffer, body, size) {
93109
+ const fmt = buffer.subarray(body, body + size);
93110
+ if (fmt.length < 16) return null;
93111
+ const tag = fmt.readUInt16LE(0);
93112
+ if (tag !== 65534) return tag;
93113
+ return fmt.length < 40 ? null : extensibleFormatTag(fmt);
93114
+ }
93115
+ var EXTENSIBLE_FORMATS;
93103
93116
  var init_wavChunks = __esm({
93104
93117
  "../engine/src/services/wavChunks.ts"() {
93105
93118
  "use strict";
93119
+ EXTENSIBLE_FORMATS = /* @__PURE__ */ new Map([
93120
+ ["0100000000001000800000aa00389b71", 1],
93121
+ ["0300000000001000800000aa00389b71", 3]
93122
+ ]);
93106
93123
  }
93107
93124
  });
93108
93125
 
93109
93126
  // ../engine/src/services/audioVolumeEnvelope.ts
93110
93127
  import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync7, renameSync as renameSync3, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
93111
93128
  import { dirname as dirname10, join as join15 } from "path";
93112
- function readFmtChunk(buffer, body) {
93113
- const format = buffer.readUInt16LE(body);
93129
+ function readFmtChunk(buffer, body, size) {
93130
+ const format = wavFormatTag(buffer, body, size);
93114
93131
  const bits = buffer.readUInt16LE(body + 14);
93115
93132
  const float = format === FLOAT_FORMAT;
93116
93133
  if (!float && format !== PCM_FORMAT) return null;
@@ -93128,7 +93145,7 @@ function parseWavLayout(buffer) {
93128
93145
  let data2 = null;
93129
93146
  for (const { id, body, size } of riffChunks(buffer)) {
93130
93147
  if (id === "fmt " && body + 16 <= buffer.length) {
93131
- fmt = readFmtChunk(buffer, body);
93148
+ fmt = readFmtChunk(buffer, body, size);
93132
93149
  } else if (id === "data") {
93133
93150
  data2 = { offset: body, size: Math.min(size, buffer.length - body) };
93134
93151
  }
@@ -93346,7 +93363,9 @@ function readWavChunks(buf) {
93346
93363
  let data2;
93347
93364
  for (const { id, body, size } of riffChunks(buf)) {
93348
93365
  if (id === "fmt ") {
93349
- head.format = buf.readUInt16LE(body);
93366
+ const format = wavFormatTag(buf, body, size);
93367
+ if (format === null) throw new AudioFxRenderError("Invalid or unsupported WAV format header");
93368
+ head.format = format;
93350
93369
  head.channels = buf.readUInt16LE(body + 2);
93351
93370
  head.sampleRate = buf.readUInt32LE(body + 4);
93352
93371
  head.bits = buf.readUInt16LE(body + 14);
@@ -96222,10 +96241,10 @@ var init_shaderTransitions = __esm({
96222
96241
  const dist = Math.sqrt(uvx * uvx + uvy * uvy);
96223
96242
  const warp = fbm(ux * 4, uy * 4) * 0.5;
96224
96243
  const fromAng = p2 * (1 - dist) * 10 + warp * p2 * 3;
96225
- const fs3 = Math.sin(fromAng);
96244
+ const fs4 = Math.sin(fromAng);
96226
96245
  const fc = Math.cos(fromAng);
96227
- const fromUx = Math.max(0, Math.min(1, uvx * fc - uvy * fs3 + 0.5));
96228
- const fromUy = Math.max(0, Math.min(1, uvx * fs3 + uvy * fc + 0.5));
96246
+ const fromUx = Math.max(0, Math.min(1, uvx * fc - uvy * fs4 + 0.5));
96247
+ const fromUy = Math.max(0, Math.min(1, uvx * fs4 + uvy * fc + 0.5));
96229
96248
  const toAng = -(1 - p2) * (1 - dist) * 10 - warp * (1 - p2) * 3;
96230
96249
  const ts = Math.sin(toAng);
96231
96250
  const tc = Math.cos(toAng);
@@ -121535,19 +121554,21 @@ import { bodyLimit } from "hono/body-limit";
121535
121554
  import {
121536
121555
  closeSync as closeSync8,
121537
121556
  existsSync as existsSync37,
121538
- ftruncateSync as ftruncateSync2,
121539
121557
  openSync as openSync8,
121540
121558
  readFileSync as readFileSync52,
121541
- writeFileSync as writeFileSync52,
121559
+ writeFileSync as writeFileSync42,
121542
121560
  writeSync as writeSync2,
121543
121561
  mkdirSync as mkdirSync32,
121544
121562
  unlinkSync as unlinkSync23,
121545
121563
  rmSync as rmSync32,
121546
- statSync as statSync23,
121564
+ statSync as statSync32,
121565
+ fstatSync as fstatSync4,
121547
121566
  renameSync as renameSync22,
121548
121567
  readdirSync as readdirSync42
121549
121568
  } from "fs";
121550
121569
  import { resolve as resolve32, dirname as dirname32, join as join62 } from "path";
121570
+ import * as fs2 from "fs";
121571
+ import { randomUUID as randomUUID9 } from "crypto";
121551
121572
  import { spawn as spawn11 } from "child_process";
121552
121573
  import {
121553
121574
  existsSync as existsSync38,
@@ -121567,31 +121588,22 @@ import { basename as basename8, join as join42 } from "path";
121567
121588
  import { mkdirSync as mkdirSync22, readdirSync as readdirSync32, readFileSync as readFileSync26, unlinkSync as unlinkSync5, writeFileSync as writeFileSync32 } from "fs";
121568
121589
  import { Buffer as Buffer2 } from "buffer";
121569
121590
  import { join as join52, relative as relative22 } from "path";
121570
- import { createHash as createHash22, randomUUID as randomUUID9 } from "crypto";
121571
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync42 } from "fs";
121591
+ import { createHash as createHash22, randomUUID as randomUUID22 } from "crypto";
121592
+ import { readFileSync as readFileSync32, statSync as statSync23 } from "fs";
121572
121593
  import { existsSync as existsSync211, readFileSync as readFileSync42, realpathSync as realpathSync8 } from "fs";
121573
- import { randomUUID as randomUUID22 } from "crypto";
121594
+ import { randomUUID as randomUUID32 } from "crypto";
121574
121595
  import { dirname as dirname22, relative as relative32, resolve as resolve24, sep as sep22 } from "path";
121575
- import { createReadStream as createReadStream3, existsSync as existsSync52, readFileSync as readFileSync82, statSync as statSync32 } from "fs";
121596
+ import { createReadStream as createReadStream3, existsSync as existsSync52, readFileSync as readFileSync82, statSync as statSync52 } from "fs";
121576
121597
  import { Readable as Readable2 } from "stream";
121577
121598
  import { join as join82, resolve as resolve42 } from "path";
121578
121599
  import { createHash as createHash32 } from "crypto";
121579
121600
  import { existsSync as existsSync42, readFileSync as readFileSync62 } from "fs";
121580
121601
  import { join as join72 } from "path";
121581
- import {
121582
- closeSync as closeSync22,
121583
- constants as constants4,
121584
- fstatSync as fstatSync4,
121585
- ftruncateSync as ftruncateSync22,
121586
- openSync as openSync22,
121587
- readFileSync as readFileSync72,
121588
- writeFileSync as writeFileSync62,
121589
- writeSync as writeSync22
121590
- } from "fs";
121602
+ import { closeSync as closeSync22, constants as constants4, fstatSync as fstatSync22, openSync as openSync22, readFileSync as readFileSync72, statSync as statSync42 } from "fs";
121591
121603
  import { readFileSync as readFileSync92 } from "fs";
121592
121604
  import { join as join92 } from "path";
121593
121605
  import { streamSSE } from "hono/streaming";
121594
- import { existsSync as existsSync62, readFileSync as readFileSync102, mkdirSync as mkdirSync42, unlinkSync as unlinkSync32, readdirSync as readdirSync52, statSync as statSync42 } from "fs";
121606
+ import { existsSync as existsSync62, readFileSync as readFileSync102, mkdirSync as mkdirSync42, unlinkSync as unlinkSync32, readdirSync as readdirSync52, statSync as statSync62 } from "fs";
121595
121607
  import { join as join102 } from "path";
121596
121608
  import {
121597
121609
  existsSync as existsSync72,
@@ -121600,15 +121612,15 @@ import {
121600
121612
  readdirSync as readdirSync62,
121601
121613
  renameSync as renameSync32,
121602
121614
  rmSync as rmSync42,
121603
- statSync as statSync52,
121615
+ statSync as statSync72,
121604
121616
  unlinkSync as unlinkSync42,
121605
- writeFileSync as writeFileSync72
121617
+ writeFileSync as writeFileSync52
121606
121618
  } from "fs";
121607
121619
  import { join as join112 } from "path";
121608
- import { createHash as createHash42, randomUUID as randomUUID32 } from "crypto";
121609
- import { existsSync as existsSync82, readFileSync as readFileSync122, statSync as statSync62 } from "fs";
121620
+ import { createHash as createHash42, randomUUID as randomUUID42 } from "crypto";
121621
+ import { existsSync as existsSync82, readFileSync as readFileSync122, statSync as statSync82 } from "fs";
121610
121622
  import { join as join122 } from "path";
121611
- import { closeSync as closeSync32, constants as constants22, fstatSync as fstatSync22, openSync as openSync32, readSync as readSync2 } from "fs";
121623
+ import { closeSync as closeSync32, constants as constants22, fstatSync as fstatSync32, openSync as openSync32, readSync as readSync2 } from "fs";
121612
121624
  import { streamSSE as streamSSE2 } from "hono/streaming";
121613
121625
  import { existsSync as existsSync92, mkdirSync as mkdirSync62 } from "fs";
121614
121626
  import { basename as basename22, dirname as dirname42, extname as extname22, join as join132 } from "path";
@@ -121807,6 +121819,20 @@ function getMimeType(path) {
121807
121819
  function isAudioFile2(name) {
121808
121820
  return (getMimeType(name) ?? "").startsWith("audio/");
121809
121821
  }
121822
+ function replaceFileAtomically(filePath, content, mode, operations = fs2) {
121823
+ const tempPath = `${filePath}.${process.pid}.${randomUUID9()}.tmp`;
121824
+ try {
121825
+ operations.writeFileSync(tempPath, content, { encoding: "utf-8", mode });
121826
+ operations.chmodSync(tempPath, mode);
121827
+ operations.renameSync(tempPath, filePath);
121828
+ } catch (error) {
121829
+ try {
121830
+ operations.unlinkSync(tempPath);
121831
+ } catch {
121832
+ }
121833
+ throw error;
121834
+ }
121835
+ }
121810
121836
  function buildWaveformCacheKey(assetPath, fingerprint) {
121811
121837
  const name = assetPath.replace(/[/\\]/g, "_");
121812
121838
  if (!fingerprint) return `${WAVEFORM_CACHE_VERSION}_${name}.json`;
@@ -122013,7 +122039,7 @@ function fileContentVersion(content) {
122013
122039
  }
122014
122040
  function createWriteToken(requestToken) {
122015
122041
  const token = requestToken?.trim();
122016
- return token && token.length <= 200 ? token : randomUUID9();
122042
+ return token && token.length <= 200 ? token : randomUUID22();
122017
122043
  }
122018
122044
  function recordFileWriteReceipt(absPath, receipt) {
122019
122045
  const now = Date.now();
@@ -122045,7 +122071,7 @@ function identifyFileWrite(absPath, expectedVersion) {
122045
122071
  const { path, version: version2, writeToken } = receipt;
122046
122072
  return { path, version: version2, writeToken };
122047
122073
  }
122048
- function applyFileMutations(projectDir, mutations, requestToken, writeFile3 = writeFileSync42) {
122074
+ function applyFileMutations(projectDir, mutations, requestToken, writeFile3 = (path, content) => replaceFileAtomically(path, content, statSync23(path).mode)) {
122049
122075
  const prepared = mutations.map((mutation) => ({
122050
122076
  ...mutation,
122051
122077
  before: mutation.before ?? readFileSync32(mutation.absPath, "utf-8")
@@ -122269,7 +122295,7 @@ function insertCompositionIntoSource(input2) {
122269
122295
  const host = document2.createElement("div");
122270
122296
  host.id = hostId;
122271
122297
  host.className = "clip";
122272
- host.setAttribute("data-hf-id", `hf-${randomUUID22()}`);
122298
+ host.setAttribute("data-hf-id", `hf-${randomUUID32()}`);
122273
122299
  host.setAttribute("data-composition-id", hostId);
122274
122300
  host.setAttribute("data-composition-src", relativeSourcePath(targetAbs, sourceAbs));
122275
122301
  host.setAttribute("data-start", String(Math.round(input2.start * 100) / 100));
@@ -122303,13 +122329,18 @@ async function resolveProjectPath(c3, adapter2, pathPrefix, opts) {
122303
122329
  if (!project) {
122304
122330
  return { error: c3.json({ error: "not found" }, 404) };
122305
122331
  }
122332
+ if (!existsSync37(project.dir)) {
122333
+ return {
122334
+ error: c3.json({ error: "not found", why: "project_dir_missing" }, 404)
122335
+ };
122336
+ }
122306
122337
  const filePath = decodeURIComponent(c3.req.path.replace(pathPrefix(project.id), ""));
122307
122338
  if (filePath.includes("\0")) {
122308
- return { error: c3.json({ error: "forbidden" }, 403) };
122339
+ return { error: c3.json({ error: "forbidden", why: "nul" }, 403) };
122309
122340
  }
122310
122341
  const absPath = resolveWithinProject(project.dir, filePath);
122311
122342
  if (!absPath) {
122312
- return { error: c3.json({ error: "forbidden" }, 403) };
122343
+ return { error: c3.json({ error: "forbidden", why: "outside_project" }, 403) };
122313
122344
  }
122314
122345
  if (opts?.mustExist && !existsSync37(absPath)) {
122315
122346
  return { error: c3.json({ error: "not found" }, 404) };
@@ -122368,7 +122399,7 @@ function foldElementPatches(originalContent, patches) {
122368
122399
  }
122369
122400
  return { content, matched };
122370
122401
  }
122371
- function commitElementPatchBatches(projectDir, batches, writeFile3 = writeFileSync52, requestToken) {
122402
+ function commitElementPatchBatches(projectDir, batches, writeFile3 = (path, content) => replaceFileAtomically(path, content, statSync32(path).mode), requestToken) {
122372
122403
  const resolvedPaths = /* @__PURE__ */ new Set();
122373
122404
  const prepared = [];
122374
122405
  for (const batch of batches) {
@@ -122429,7 +122460,7 @@ function commitElementPatchBatchesWithReceipts(c3, projectDir, batches) {
122429
122460
  return commitElementPatchBatches(
122430
122461
  projectDir,
122431
122462
  batches,
122432
- writeFileSync52,
122463
+ writeFileSync42,
122433
122464
  c3.req.header("X-Hyperframes-Write-Token")
122434
122465
  );
122435
122466
  }
@@ -122440,7 +122471,7 @@ function recordMutationReceipt(c3, filePath, absPath, html) {
122440
122471
  return { version: version2, writeToken };
122441
122472
  }
122442
122473
  function writeFileWithReceipt(c3, filePath, absPath, html) {
122443
- writeFileSync52(absPath, html, "utf-8");
122474
+ replaceFileAtomically(absPath, html, statSync32(absPath).mode);
122444
122475
  return recordMutationReceipt(c3, filePath, absPath, html);
122445
122476
  }
122446
122477
  function writeMutationResult(c3, projectDir, filePath, absPath, html) {
@@ -122529,7 +122560,7 @@ function updateReferences(projectDir, oldPath, newPath) {
122529
122560
  if (!content.includes(oldPath)) continue;
122530
122561
  const updated = content.split(oldPath).join(newPath);
122531
122562
  if (updated !== content) {
122532
- writeFileSync52(file, updated, "utf-8");
122563
+ replaceFileAtomically(file, updated, statSync32(file).mode);
122533
122564
  updatedCount++;
122534
122565
  }
122535
122566
  }
@@ -123618,7 +123649,7 @@ async function processUploadedFiles(formData, targetDir, projectDir) {
123618
123649
  try {
123619
123650
  const fd = openSync8(finalPath, "wx");
123620
123651
  try {
123621
- writeFileSync52(fd, buffer);
123652
+ writeFileSync42(fd, buffer);
123622
123653
  } finally {
123623
123654
  closeSync8(fd);
123624
123655
  }
@@ -123746,10 +123777,12 @@ function registerFileRoutes(api, adapter2) {
123746
123777
  }
123747
123778
  backup = snapshotBeforeWrite(res.project.dir, res.absPath);
123748
123779
  if (backup.error) return c3.json({ error: `backup failed: ${backup.error}` }, 500);
123749
- ftruncateSync2(fd, 0);
123750
- writeSync2(fd, body, 0, body.length, 0);
123751
- } finally {
123780
+ const mode = fstatSync4(fd).mode;
123752
123781
  closeSync8(fd);
123782
+ fd = null;
123783
+ replaceFileAtomically(res.absPath, body, mode);
123784
+ } finally {
123785
+ if (fd !== null) closeSync8(fd);
123753
123786
  }
123754
123787
  }
123755
123788
  const version2 = fileContentVersion(body);
@@ -123770,7 +123803,7 @@ function registerFileRoutes(api, adapter2) {
123770
123803
  ensureDir(res.absPath);
123771
123804
  const body = Buffer.from(await c3.req.arrayBuffer());
123772
123805
  try {
123773
- writeFileSync52(res.absPath, body, { flag: "wx" });
123806
+ writeFileSync42(res.absPath, body, { flag: "wx" });
123774
123807
  } catch (error) {
123775
123808
  if (!error || typeof error !== "object" || !("code" in error) || error.code !== "EEXIST") {
123776
123809
  throw error;
@@ -123782,7 +123815,7 @@ function registerFileRoutes(api, adapter2) {
123782
123815
  api.delete("/projects/:id/files/*", async (c3) => {
123783
123816
  const res = await resolveProjectFile(c3, adapter2, { mustExist: true });
123784
123817
  if ("error" in res) return res.error;
123785
- const stat = statSync23(res.absPath);
123818
+ const stat = statSync32(res.absPath);
123786
123819
  const backup = snapshotBeforeWrite(res.project.dir, res.absPath);
123787
123820
  if (backup.error) return c3.json({ error: `backup failed: ${backup.error}` }, 500);
123788
123821
  if (stat.isDirectory()) {
@@ -123972,7 +124005,7 @@ function registerFileRoutes(api, adapter2) {
123972
124005
  const written = [];
123973
124006
  try {
123974
124007
  for (const file of prepared) {
123975
- writeFileSync52(file.absPath, file.after, "utf-8");
124008
+ replaceFileAtomically(file.absPath, file.after, statSync32(file.absPath).mode);
123976
124009
  written.push(file);
123977
124010
  recordFileWriteReceipt(file.absPath, {
123978
124011
  path: file.path,
@@ -123989,7 +124022,7 @@ function registerFileRoutes(api, adapter2) {
123989
124022
  conflicts.push(file.path);
123990
124023
  continue;
123991
124024
  }
123992
- writeFileSync52(file.absPath, file.before, "utf-8");
124025
+ replaceFileAtomically(file.absPath, file.before, statSync32(file.absPath).mode);
123993
124026
  recordFileWriteReceipt(file.absPath, {
123994
124027
  path: file.path,
123995
124028
  version: fileContentVersion(file.before),
@@ -124316,7 +124349,7 @@ function registerFileRoutes(api, adapter2) {
124316
124349
  return c3.json({ error: "forbidden" }, 403);
124317
124350
  }
124318
124351
  ensureDir(destAbs);
124319
- writeFileSync52(destAbs, readFileSync52(srcAbs));
124352
+ writeFileSync42(destAbs, readFileSync52(srcAbs));
124320
124353
  return c3.json({ ok: true, path: copyPath }, 201);
124321
124354
  });
124322
124355
  const MAX_UPLOAD_BYTES = 500 * 1024 * 1024;
@@ -124409,7 +124442,7 @@ function registerFileRoutes(api, adapter2) {
124409
124442
  if (current2 !== body.expected) {
124410
124443
  return c3.json({ ok: true, restored: false, conflict: true });
124411
124444
  }
124412
- writeFileSync52(res.absPath, body.restore, "utf-8");
124445
+ replaceFileAtomically(res.absPath, body.restore, statSync32(res.absPath).mode);
124413
124446
  return c3.json({ ok: true, restored: true, conflict: false });
124414
124447
  });
124415
124448
  }
@@ -124587,7 +124620,7 @@ function persistHfIdsIfNeeded(filePath, html) {
124587
124620
  try {
124588
124621
  const current2 = readFileSync72(filePath, "utf-8");
124589
124622
  if (current2 === html) {
124590
- writeFileSync62(filePath, normalized2, "utf-8");
124623
+ replaceFileAtomically(filePath, normalized2, statSync42(filePath).mode);
124591
124624
  }
124592
124625
  } catch (err) {
124593
124626
  console.warn("[hyperframes] persistHfIdsIfNeeded: failed to write ids to disk:", err);
@@ -124612,21 +124645,23 @@ function stampFileHfIds(filePath) {
124612
124645
  }
124613
124646
  if (fd === null) return null;
124614
124647
  try {
124615
- if (!fstatSync4(fd).isFile()) return null;
124648
+ if (!fstatSync22(fd).isFile()) return null;
124616
124649
  const html = readFileSync72(fd, "utf-8");
124617
124650
  const normalized2 = ensureHfIds(html);
124618
124651
  const idsBefore = (html.match(/\bdata-hf-id=/g) ?? []).length;
124619
124652
  const idsAfter = (normalized2.match(/\bdata-hf-id=/g) ?? []).length;
124620
124653
  if (writable && idsAfter > idsBefore) {
124621
- ftruncateSync22(fd, 0);
124622
- writeSync22(fd, normalized2, 0, "utf-8");
124654
+ const mode = fstatSync22(fd).mode;
124655
+ closeSync22(fd);
124656
+ fd = null;
124657
+ replaceFileAtomically(filePath, normalized2, mode);
124623
124658
  }
124624
124659
  return normalized2;
124625
124660
  } catch (err) {
124626
124661
  console.warn("[hyperframes] stampFileHfIds: failed to stamp ids:", err);
124627
124662
  return null;
124628
124663
  } finally {
124629
- closeSync22(fd);
124664
+ if (fd !== null) closeSync22(fd);
124630
124665
  }
124631
124666
  }
124632
124667
  function isVariablesPayload(value) {
@@ -124901,7 +124936,7 @@ ${runtimeTag}`;
124901
124936
  c3.req.path.replace(`/projects/${project.id}/preview/comp/`, "").split("?")[0] ?? ""
124902
124937
  );
124903
124938
  const compFile = resolveWithinProject(project.dir, compPath);
124904
- if (!compFile || !existsSync52(compFile) || !statSync32(compFile).isFile()) {
124939
+ if (!compFile || !existsSync52(compFile) || !statSync52(compFile).isFile()) {
124905
124940
  return c3.text("not found", 404);
124906
124941
  }
124907
124942
  const compPathHash = createHash32("sha1").update(compPath).digest("hex");
@@ -124941,7 +124976,7 @@ ${runtimeTag}`;
124941
124976
  if (!file) {
124942
124977
  return c3.text("not found", 404);
124943
124978
  }
124944
- const stat = existsSync52(file) ? statSync32(file) : null;
124979
+ const stat = existsSync52(file) ? statSync52(file) : null;
124945
124980
  if (!stat?.isFile()) {
124946
124981
  return c3.text("not found", 404);
124947
124982
  }
@@ -124991,7 +125026,7 @@ ${runtimeTag}`;
124991
125026
  servedContentType = PROXY_VARIANT_CONFIG[proxyVariant].contentType;
124992
125027
  }
124993
125028
  const textBuffer = isText2 ? Buffer.from(readFileSync82(file, "utf-8"), "utf-8") : null;
124994
- const totalSize2 = textBuffer ? textBuffer.length : statSync32(servedPath).size;
125029
+ const totalSize2 = textBuffer ? textBuffer.length : statSync52(servedPath).size;
124995
125030
  const bodyFor = (start, end) => textBuffer ? new Uint8Array(textBuffer.subarray(start, end + 1)) : (
124996
125031
  // Node's web stream type and the DOM one do not overlap for tsc on
124997
125032
  // every platform's lib set; the double cast is the documented bridge.
@@ -125280,7 +125315,7 @@ function registerRenderRoutes(api, adapter2) {
125280
125315
  if (!existsSync62(rendersDir)) return c3.json({ renders: [] });
125281
125316
  const files = readdirSync52(rendersDir).filter((f) => f.endsWith(".mp4") || f.endsWith(".webm") || f.endsWith(".mov")).map((f) => {
125282
125317
  const fp = join102(rendersDir, f);
125283
- const stat = statSync42(fp);
125318
+ const stat = statSync62(fp);
125284
125319
  const rid = f.replace(/\.(mp4|webm|mov)$/, "");
125285
125320
  const metaPath = join102(rendersDir, `${rid}.meta.json`);
125286
125321
  let status = "complete";
@@ -125322,7 +125357,7 @@ function pruneThumbnailCache(cacheDir, protectedPaths, now = Date.now()) {
125322
125357
  if (!entry.isFile()) return [];
125323
125358
  const path = join112(cacheDir, entry.name);
125324
125359
  try {
125325
- const stats = statSync52(path);
125360
+ const stats = statSync72(path);
125326
125361
  return [{ path, bytes: stats.size, mtimeMs: stats.mtimeMs }];
125327
125362
  } catch {
125328
125363
  return [];
@@ -125348,9 +125383,9 @@ function pruneThumbnailCache(cacheDir, protectedPaths, now = Date.now()) {
125348
125383
  }
125349
125384
  }
125350
125385
  function writeThumbnailAtomically(path, buffer) {
125351
- const temporaryPath = `${path}.${process.pid}.${randomUUID32()}.tmp`;
125386
+ const temporaryPath = `${path}.${process.pid}.${randomUUID42()}.tmp`;
125352
125387
  try {
125353
- writeFileSync72(temporaryPath, buffer, { flag: "wx" });
125388
+ writeFileSync52(temporaryPath, buffer, { flag: "wx" });
125354
125389
  renameSync32(temporaryPath, path);
125355
125390
  } finally {
125356
125391
  rmSync42(temporaryPath, { force: true });
@@ -125390,7 +125425,7 @@ function registerThumbnailRoutes(api, adapter2) {
125390
125425
  if (existsSync72(htmlFile)) {
125391
125426
  const html = readFileSync112(htmlFile, "utf-8");
125392
125427
  sourceKey = `_${createHash42("sha1").update(html).digest("hex").slice(0, 16)}`;
125393
- sourceMtime = Math.round(statSync52(htmlFile).mtimeMs);
125428
+ sourceMtime = Math.round(statSync72(htmlFile).mtimeMs);
125394
125429
  if (!vpWidth) {
125395
125430
  const wMatch = html.match(/data-width=["'](\d+)["']/);
125396
125431
  const hMatch = html.match(/data-height=["'](\d+)["']/);
@@ -125403,14 +125438,14 @@ function registerThumbnailRoutes(api, adapter2) {
125403
125438
  if (existsSync72(manualEditsFile)) {
125404
125439
  const manualEditsContent = readFileSync112(manualEditsFile, "utf-8");
125405
125440
  manualEditsKey = `_${createHash42("sha1").update(manualEditsContent).digest("hex").slice(0, 16)}`;
125406
- sourceMtime = Math.max(sourceMtime, Math.round(statSync52(manualEditsFile).mtimeMs));
125441
+ sourceMtime = Math.max(sourceMtime, Math.round(statSync72(manualEditsFile).mtimeMs));
125407
125442
  }
125408
125443
  const motionFile = join112(project.dir, STUDIO_MOTION_PATH);
125409
125444
  let motionKey = "";
125410
125445
  if (existsSync72(motionFile)) {
125411
125446
  const motionContent = readFileSync112(motionFile, "utf-8");
125412
125447
  motionKey = `_${createHash42("sha1").update(motionContent).digest("hex").slice(0, 16)}`;
125413
- sourceMtime = Math.max(sourceMtime, Math.round(statSync52(motionFile).mtimeMs));
125448
+ sourceMtime = Math.max(sourceMtime, Math.round(statSync72(motionFile).mtimeMs));
125414
125449
  }
125415
125450
  const previewUrl = compPath === "index.html" ? `http://${c3.req.header("host")}/api/projects/${project.id}/preview` : `http://${c3.req.header("host")}/api/projects/${project.id}/preview/comp/${compPath}`;
125416
125451
  const cacheDir = join112(project.dir, ".thumbnails");
@@ -125491,7 +125526,7 @@ function registerWaveformRoutes(api, adapter2) {
125491
125526
  c3.req.path.replace(`/projects/${project.id}/waveform/`, "").split("?")[0] ?? ""
125492
125527
  );
125493
125528
  const audioPath = join122(project.dir, assetPath);
125494
- const stats = statSync62(audioPath, { throwIfNoEntry: false });
125529
+ const stats = statSync82(audioPath, { throwIfNoEntry: false });
125495
125530
  if (!stats) return c3.json({ error: "file not found" }, 404);
125496
125531
  const cacheDir = join122(project.dir, ".waveform-cache");
125497
125532
  const cachePath2 = join122(cacheDir, buildWaveformCacheKey(assetPath, stats));
@@ -125592,7 +125627,7 @@ function registerFontRoutes(api) {
125592
125627
  return c3.json({ error: "font file not accessible" }, 404);
125593
125628
  }
125594
125629
  try {
125595
- const stat = fstatSync22(fd);
125630
+ const stat = fstatSync32(fd);
125596
125631
  if (stat.size > SYSTEM_FONT_SIZE_LIMIT) {
125597
125632
  return c3.json({ error: "font file too large" }, 413);
125598
125633
  }
@@ -151841,7 +151876,10 @@ function createStudioServer(options) {
151841
151876
  } catch {
151842
151877
  }
151843
151878
  const receipt = version2 ? identifyFileWrite(absPath, version2) : null;
151844
- stream.writeSSE({ event: "file-change", data: JSON.stringify({ path, version: version2, ...receipt }) }).catch(() => {
151879
+ stream.writeSSE({
151880
+ event: "file-change",
151881
+ data: JSON.stringify({ path, version: version2, projectId: project.id, ...receipt })
151882
+ }).catch(() => {
151845
151883
  });
151846
151884
  };
151847
151885
  const wrappedListener = (changedPath) => {
@@ -156607,12 +156645,12 @@ var init_paths2 = __esm({
156607
156645
  });
156608
156646
 
156609
156647
  // src/auth/store.ts
156610
- import { promises as fs2 } from "fs";
156648
+ import { promises as fs3 } from "fs";
156611
156649
  import { dirname as dirname43 } from "path";
156612
156650
  async function readStore(path = credentialPath()) {
156613
156651
  let raw;
156614
156652
  try {
156615
- raw = await fs2.readFile(path, "utf8");
156653
+ raw = await fs3.readFile(path, "utf8");
156616
156654
  } catch (err) {
156617
156655
  if (err.code === "ENOENT") {
156618
156656
  return { credentials: {}, source: "absent" };
@@ -156633,14 +156671,14 @@ async function writeStore(credentials, path = credentialPath()) {
156633
156671
  await ensureDir2(dirname43(path));
156634
156672
  const body = JSON.stringify(serializeCredentials(credentials), null, 2);
156635
156673
  const tmp = `${path}.${process.pid}.${Date.now()}.tmp`;
156636
- await fs2.writeFile(tmp, `${body}
156674
+ await fs3.writeFile(tmp, `${body}
156637
156675
  `, { mode: FILE_MODE, encoding: "utf8" });
156638
- await fs2.chmod(tmp, FILE_MODE);
156639
- await fs2.rename(tmp, path);
156676
+ await fs3.chmod(tmp, FILE_MODE);
156677
+ await fs3.rename(tmp, path);
156640
156678
  }
156641
156679
  async function deleteStore(path = credentialPath()) {
156642
156680
  try {
156643
- await fs2.unlink(path);
156681
+ await fs3.unlink(path);
156644
156682
  } catch (err) {
156645
156683
  if (err.code === "ENOENT") return;
156646
156684
  throw err;
@@ -156668,16 +156706,16 @@ async function clearOAuth(path = credentialPath()) {
156668
156706
  }
156669
156707
  async function ensureDir2(dir) {
156670
156708
  try {
156671
- const stat = await fs2.stat(dir);
156709
+ const stat = await fs3.stat(dir);
156672
156710
  if (!stat.isDirectory()) {
156673
156711
  throw ErrInvalidStore(`${dir} exists and is not a directory`);
156674
156712
  }
156675
156713
  } catch (err) {
156676
156714
  if (err.code !== "ENOENT") throw err;
156677
- await fs2.mkdir(dir, { recursive: true, mode: DIR_MODE });
156715
+ await fs3.mkdir(dir, { recursive: true, mode: DIR_MODE });
156678
156716
  }
156679
156717
  try {
156680
- await fs2.chmod(dir, DIR_MODE);
156718
+ await fs3.chmod(dir, DIR_MODE);
156681
156719
  } catch {
156682
156720
  }
156683
156721
  }
@@ -174171,11 +174209,11 @@ function lintFeedbackComment(input2) {
174171
174209
  if (!trimmed) return [];
174172
174210
  const upperTrimmed = trimmed.toUpperCase();
174173
174211
  const warnings = [];
174174
- if (!upperTrimmed.includes(REPRO_MARKER)) {
174212
+ if (!hasReproCommandBody(trimmed)) {
174175
174213
  warnings.push({
174176
174214
  code: "missing-repro-command",
174177
174215
  message: [
174178
- `Comment on a ${rating}/${FEEDBACK_RATING_SCALE} report is missing a "${REPRO_MARKER}" block \u2014`,
174216
+ `Comment on a ${rating}/${FEEDBACK_RATING_SCALE} report is missing a non-empty "${REPRO_MARKER}" block \u2014`,
174179
174217
  "maintainers can't rerun the failure from a symptom summary alone.",
174180
174218
  "See `references/preview-render.md` \u2192 feedback for the required packet shape."
174181
174219
  ].join(" ")
@@ -174194,13 +174232,29 @@ function lintFeedbackComment(input2) {
174194
174232
  }
174195
174233
  return warnings;
174196
174234
  }
174235
+ function hasReproCommandBody(comment) {
174236
+ const lines = comment.split(/\r?\n/);
174237
+ return lines.some((line3, index) => {
174238
+ const markerIndex = line3.toUpperCase().indexOf(REPRO_MARKER);
174239
+ if (markerIndex === -1) return false;
174240
+ const inlineBody = line3.slice(markerIndex + REPRO_MARKER.length).trim();
174241
+ if (inlineBody) return !startsWithFeedbackPacketMarker(inlineBody);
174242
+ const nextContentLine = lines.slice(index + 1).find((candidate) => candidate.trim());
174243
+ if (!nextContentLine) return false;
174244
+ return !startsWithFeedbackPacketMarker(nextContentLine.trimStart());
174245
+ });
174246
+ }
174247
+ function startsWithFeedbackPacketMarker(value) {
174248
+ const upperValue = value.toUpperCase();
174249
+ return FEEDBACK_PACKET_MARKERS.some((marker) => upperValue.startsWith(marker));
174250
+ }
174197
174251
  function escapeRegex3(input2) {
174198
174252
  return input2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
174199
174253
  }
174200
174254
  function mentionsVisualDefect(comment) {
174201
174255
  return VISUAL_DEFECT_REGEX.test(comment);
174202
174256
  }
174203
- var VISUAL_DEFECT_KEYWORDS, COMPOSITION_STRUCTURE_RATING_CEILING, REPRO_MARKER, STRUCTURE_MARKER, VISUAL_DEFECT_REGEX;
174257
+ var VISUAL_DEFECT_KEYWORDS, COMPOSITION_STRUCTURE_RATING_CEILING, REPRO_MARKER, STRUCTURE_MARKER, FEEDBACK_PACKET_MARKERS, VISUAL_DEFECT_REGEX;
174204
174258
  var init_feedbackLint = __esm({
174205
174259
  "src/utils/feedbackLint.ts"() {
174206
174260
  "use strict";
@@ -174216,6 +174270,14 @@ var init_feedbackLint = __esm({
174216
174270
  COMPOSITION_STRUCTURE_RATING_CEILING = 7;
174217
174271
  REPRO_MARKER = "REPRO COMMAND:";
174218
174272
  STRUCTURE_MARKER = "COMPOSITION_STRUCTURE:";
174273
+ FEEDBACK_PACKET_MARKERS = [
174274
+ REPRO_MARKER,
174275
+ "EXPECTED / ACTUAL:",
174276
+ "EXACT ERROR:",
174277
+ "OUTCOME:",
174278
+ "WORKAROUND:",
174279
+ STRUCTURE_MARKER
174280
+ ];
174219
174281
  VISUAL_DEFECT_REGEX = new RegExp(
174220
174282
  `(^|[^A-Za-z0-9_])(?:${VISUAL_DEFECT_KEYWORDS.map(escapeRegex3).join("|")})(?![A-Za-z0-9_])`,
174221
174283
  "i"
@@ -80176,17 +80176,34 @@ function* riffChunks(buffer) {
80176
80176
  offset2 += 8 + size + size % 2;
80177
80177
  }
80178
80178
  }
80179
+ function extensibleFormatTag(fmt) {
80180
+ const extraSize = fmt.readUInt16LE(16);
80181
+ if (extraSize < 22 || 18 + extraSize > fmt.length) return null;
80182
+ return EXTENSIBLE_FORMATS.get(fmt.toString("hex", 24, 40)) ?? null;
80183
+ }
80184
+ function wavFormatTag(buffer, body, size) {
80185
+ const fmt = buffer.subarray(body, body + size);
80186
+ if (fmt.length < 16) return null;
80187
+ const tag = fmt.readUInt16LE(0);
80188
+ if (tag !== 65534) return tag;
80189
+ return fmt.length < 40 ? null : extensibleFormatTag(fmt);
80190
+ }
80191
+ var EXTENSIBLE_FORMATS;
80179
80192
  var init_wavChunks = __esm({
80180
80193
  "../engine/src/services/wavChunks.ts"() {
80181
80194
  "use strict";
80195
+ EXTENSIBLE_FORMATS = /* @__PURE__ */ new Map([
80196
+ ["0100000000001000800000aa00389b71", 1],
80197
+ ["0300000000001000800000aa00389b71", 3]
80198
+ ]);
80182
80199
  }
80183
80200
  });
80184
80201
 
80185
80202
  // ../engine/src/services/audioVolumeEnvelope.ts
80186
80203
  import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync4, renameSync as renameSync2, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "fs";
80187
80204
  import { dirname as dirname8, join as join13 } from "path";
80188
- function readFmtChunk(buffer, body) {
80189
- const format = buffer.readUInt16LE(body);
80205
+ function readFmtChunk(buffer, body, size) {
80206
+ const format = wavFormatTag(buffer, body, size);
80190
80207
  const bits = buffer.readUInt16LE(body + 14);
80191
80208
  const float = format === FLOAT_FORMAT;
80192
80209
  if (!float && format !== PCM_FORMAT) return null;
@@ -80204,7 +80221,7 @@ function parseWavLayout(buffer) {
80204
80221
  let data2 = null;
80205
80222
  for (const { id, body, size } of riffChunks(buffer)) {
80206
80223
  if (id === "fmt " && body + 16 <= buffer.length) {
80207
- fmt = readFmtChunk(buffer, body);
80224
+ fmt = readFmtChunk(buffer, body, size);
80208
80225
  } else if (id === "data") {
80209
80226
  data2 = { offset: body, size: Math.min(size, buffer.length - body) };
80210
80227
  }
@@ -80367,7 +80384,9 @@ function readWavChunks(buf) {
80367
80384
  let data2;
80368
80385
  for (const { id, body, size } of riffChunks(buf)) {
80369
80386
  if (id === "fmt ") {
80370
- head.format = buf.readUInt16LE(body);
80387
+ const format = wavFormatTag(buf, body, size);
80388
+ if (format === null) throw new AudioFxRenderError("Invalid or unsupported WAV format header");
80389
+ head.format = format;
80371
80390
  head.channels = buf.readUInt16LE(body + 2);
80372
80391
  head.sampleRate = buf.readUInt32LE(body + 4);
80373
80392
  head.bits = buf.readUInt16LE(body + 14);
@@ -102729,8 +102748,8 @@ async function runFontLocalize(io, localize) {
102729
102748
  }
102730
102749
 
102731
102750
  // src/version.ts
102732
- var VERSION = true ? "0.8.59" : "0.0.0-dev";
102733
- var PRODUCER_VERSION = true ? "0.8.59" : "0.0.0-dev";
102751
+ var VERSION = true ? "0.8.61" : "0.0.0-dev";
102752
+ var PRODUCER_VERSION = true ? "0.8.61" : "0.0.0-dev";
102734
102753
 
102735
102754
  // src/fontLocalizeCli.ts
102736
102755
  async function readStdin() {