hyperframes 0.8.34 → 0.8.35

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.
@@ -54532,6 +54532,34 @@ var init_pageNavigationTimeoutErrorHint = __esm({
54532
54532
  }
54533
54533
  });
54534
54534
 
54535
+ // ../engine/src/services/drawElementCaptureError.ts
54536
+ function isDrawElementCaptureError(error) {
54537
+ let current2 = error;
54538
+ for (let depth = 0; depth < 5 && typeof current2 === "object" && current2 !== null; depth++) {
54539
+ if ("deCaptureFailure" in current2 && current2.deCaptureFailure === true) return true;
54540
+ current2 = "cause" in current2 ? current2.cause : void 0;
54541
+ }
54542
+ return false;
54543
+ }
54544
+ var DrawElementCaptureError;
54545
+ var init_drawElementCaptureError = __esm({
54546
+ "../engine/src/services/drawElementCaptureError.ts"() {
54547
+ "use strict";
54548
+ DrawElementCaptureError = class extends Error {
54549
+ frameIndex;
54550
+ constructor(frameIndex, reason, cause) {
54551
+ super(
54552
+ `drawElement capture failed at frame ${frameIndex}: ${reason}; fresh screenshot capture required`,
54553
+ { cause }
54554
+ );
54555
+ this.name = "DrawElementCaptureError";
54556
+ Object.defineProperty(this, "deCaptureFailure", { value: true, enumerable: true });
54557
+ this.frameIndex = frameIndex;
54558
+ }
54559
+ };
54560
+ }
54561
+ });
54562
+
54535
54563
  // ../engine/src/services/screenshotService.ts
54536
54564
  async function getCdpSession(page) {
54537
54565
  let client = cdpSessionCache.get(page);
@@ -58596,7 +58624,10 @@ async function captureFrameCore(session, frameIndex, time) {
58596
58624
  else session.beginFrameNoDamageCount++;
58597
58625
  screenshotBuffer = result.buffer;
58598
58626
  } else if (session.captureMode === "drawelement" && session.clipBoundaryFrames?.has(frameIndex) && process.env.HF_FAST_CAPTURE_BOUNDARY_SS === "true") {
58599
- screenshotBuffer = await pageScreenshotCapture(page, options);
58627
+ throw new DrawElementCaptureError(
58628
+ frameIndex,
58629
+ "boundary screenshot requested on an injected canvas page"
58630
+ );
58600
58631
  } else if (session.captureMode === "drawelement") {
58601
58632
  if (session.beginFrameTimeTicks > 0) {
58602
58633
  const client = await getCdpSession(page);
@@ -58625,10 +58656,10 @@ async function captureFrameCore(session, frameIndex, time) {
58625
58656
  const median = sorted ? sorted[sorted.length >> 1] ?? 0 : 0;
58626
58657
  const floor = Math.max(2e4, median * 0.12);
58627
58658
  if (screenshotBuffer.length < floor) {
58628
- console.log(
58629
- `[engine] fast capture: frame ${frameIndex} \u2014 drawElement frame anomalously small (${screenshotBuffer.length}B < ${Math.round(floor)}B, likely a silent paint-record drop); screenshot fallback (see fast-capture-limitations.md)`
58659
+ throw new DrawElementCaptureError(
58660
+ frameIndex,
58661
+ `suspect small frame (${screenshotBuffer.length}B < ${Math.round(floor)}B)`
58630
58662
  );
58631
- screenshotBuffer = await pageScreenshotCapture(page, options);
58632
58663
  } else {
58633
58664
  if (sizes.length >= 60) sizes.shift();
58634
58665
  sizes.push(screenshotBuffer.length);
@@ -58638,10 +58669,7 @@ async function captureFrameCore(session, frameIndex, time) {
58638
58669
  if (isRecoverableDrawElementError(err)) {
58639
58670
  session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
58640
58671
  const reason = isCanvasNotInitializedError(err) ? "drawElement canvas not initialized" : "No cached paint record";
58641
- console.log(
58642
- `[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
58643
- );
58644
- screenshotBuffer = await pageScreenshotCapture(page, options);
58672
+ throw new DrawElementCaptureError(frameIndex, reason, err);
58645
58673
  } else {
58646
58674
  throw err;
58647
58675
  }
@@ -58730,21 +58758,10 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
58730
58758
  );
58731
58759
  void quantizedTime;
58732
58760
  if (session.clipBoundaryFrames?.has(frameIndex) && process.env.HF_FAST_CAPTURE_BOUNDARY_SS === "true") {
58733
- const buffer = await pageScreenshotCapture(page, options);
58734
- session.capturePerf.frames += 1;
58735
- session.capturePerf.seekMs += seekMs;
58736
- session.capturePerf.beforeCaptureMs += beforeCaptureMs;
58737
- {
58738
- const boundaryMs = Date.now() - startTime;
58739
- session.capturePerf.totalMs += boundaryMs;
58740
- session.capturePerf.frameMs.push(boundaryMs);
58741
- }
58742
- const boundaryResult = Promise.resolve(buffer);
58743
- if (session.staticFrames) {
58744
- session.lastEncodeResult = boundaryResult;
58745
- session.lastEncodeResultFrame = frameIndex;
58746
- }
58747
- return { encodeResult: boundaryResult, captureTimeMs: Date.now() - startTime };
58761
+ throw new DrawElementCaptureError(
58762
+ frameIndex,
58763
+ "boundary screenshot requested on an injected canvas page"
58764
+ );
58748
58765
  }
58749
58766
  const { encodeResult } = await produceDrawElementFrame(
58750
58767
  page,
@@ -58766,15 +58783,6 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
58766
58783
  }
58767
58784
  return { encodeResult, captureTimeMs };
58768
58785
  } catch (captureError) {
58769
- if (isRecoverableDrawElementError(captureError)) {
58770
- session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
58771
- const reason = isCanvasNotInitializedError(captureError) ? "drawElement canvas not initialized" : "No cached paint record";
58772
- console.log(
58773
- `[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
58774
- );
58775
- const buffer = await pageScreenshotCapture(page, options);
58776
- return { encodeResult: Promise.resolve(buffer), captureTimeMs: Date.now() - startTime };
58777
- }
58778
58786
  if (session.isInitialized) {
58779
58787
  await captureFrameErrorDiagnostics(
58780
58788
  session,
@@ -58783,6 +58791,11 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
58783
58791
  captureError instanceof Error ? captureError : new Error(String(captureError))
58784
58792
  );
58785
58793
  }
58794
+ if (isRecoverableDrawElementError(captureError)) {
58795
+ session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
58796
+ const reason = isCanvasNotInitializedError(captureError) ? "drawElement canvas not initialized" : "No cached paint record";
58797
+ throw new DrawElementCaptureError(frameIndex, reason, captureError);
58798
+ }
58786
58799
  throw captureError;
58787
58800
  }
58788
58801
  }
@@ -58816,6 +58829,8 @@ async function captureFramesBatchPipelined(session, frameIndices, times) {
58816
58829
  options.height,
58817
58830
  options.quality ?? 80
58818
58831
  );
58832
+ for (const result of encodeResults) void result.catch(() => {
58833
+ });
58819
58834
  const okCount = failedAt === null ? frameIndices.length : failedAt;
58820
58835
  const elapsed = Date.now() - startTime;
58821
58836
  session.capturePerf.frames += okCount;
@@ -58835,23 +58850,8 @@ async function captureFramesBatchPipelined(session, frameIndices, times) {
58835
58850
  if (failedAt !== null) {
58836
58851
  if (isRecoverableDrawElementError(error)) {
58837
58852
  const reason = isCanvasNotInitializedError(error) ? "drawElement canvas not initialized" : "No cached paint record";
58838
- console.log(
58839
- `[engine] fast capture: batch produce failed at frame ${frameIndices[failedAt] ?? "?"} (${reason}); screenshot fallback for ${frameIndices.length - failedAt} frame(s) (see fast-capture-limitations.md)`
58840
- );
58841
- for (let i = failedAt; i < frameIndices.length; i++) {
58842
- const frameIndex = frameIndices[i];
58843
- const time = times[i];
58844
- if (frameIndex === void 0 || time === void 0) break;
58845
- session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
58846
- await prepareFrameForCapture(session, frameIndex, time);
58847
- const buffer = await pageScreenshotCapture(page, options);
58848
- const encodeResult = Promise.resolve(buffer);
58849
- if (session.staticFrames) {
58850
- session.lastEncodeResult = encodeResult;
58851
- session.lastEncodeResultFrame = frameIndex;
58852
- }
58853
- results.push({ frameIndex, encodeResult });
58854
- }
58853
+ session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
58854
+ throw new DrawElementCaptureError(frameIndices[failedAt] ?? failedAt, reason, error);
58855
58855
  } else {
58856
58856
  console.log(
58857
58857
  `[engine] fast capture: batch produce failed at frame ${frameIndices[failedAt] ?? "?"} (${error ?? "?"}); re-capturing ${frameIndices.length - failedAt} frame(s) per-frame`
@@ -59024,7 +59024,7 @@ function getCapturePerfSummary(session) {
59024
59024
  if (frames > 0 && ncprFallbacks / frames > DE_FALLBACK_RATIO_WARN_THRESHOLD) {
59025
59025
  const pct = Math.round(ncprFallbacks / frames * 100);
59026
59026
  console.warn(
59027
- `[engine] fast capture: ${ncprFallbacks}/${frames} frame(s) (${pct}%) fell back to screenshot capture (canvas-not-initialized / no-cached-paint-record) \u2014 drawElement likely failed to engage for this render rather than recovering a few edge-case frames; see fast-capture-limitations.md.`
59027
+ `[engine] fast capture: ${ncprFallbacks}/${frames} frame(s) (${pct}%) rejected due to missing canvas/paint records; fresh screenshot capture required.`
59028
59028
  );
59029
59029
  }
59030
59030
  return {
@@ -59074,6 +59074,7 @@ var init_frameCapture = __esm({
59074
59074
  "../engine/src/services/frameCapture.ts"() {
59075
59075
  "use strict";
59076
59076
  init_dist2();
59077
+ init_drawElementCaptureError();
59077
59078
  init_browserManager();
59078
59079
  init_screenshotService();
59079
59080
  init_drawElementService();
@@ -68748,6 +68749,21 @@ function findRootTag(source, parsedTags) {
68748
68749
  }
68749
68750
  return null;
68750
68751
  }
68752
+ function hasUnquotedLessThan(attrs) {
68753
+ let quote = null;
68754
+ for (const ch of attrs) {
68755
+ if (quote) {
68756
+ if (ch === quote) quote = null;
68757
+ continue;
68758
+ }
68759
+ if (ch === '"' || ch === "'") {
68760
+ quote = ch;
68761
+ } else if (ch === "<") {
68762
+ return true;
68763
+ }
68764
+ }
68765
+ return false;
68766
+ }
68751
68767
  function readAttr(tagSource, attr) {
68752
68768
  if (!tagSource) return null;
68753
68769
  const escaped = attr.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -71170,6 +71186,21 @@ var init_dist3 = __esm({
71170
71186
  }
71171
71187
  return findings;
71172
71188
  },
71189
+ // unclosed_tag_swallowed_element
71190
+ ({ tags }) => {
71191
+ const findings = [];
71192
+ for (const tag of tags) {
71193
+ if (!hasUnquotedLessThan(tag.attrs)) continue;
71194
+ findings.push({
71195
+ code: "unclosed_tag_swallowed_element",
71196
+ severity: "error",
71197
+ message: `<${tag.name}> is missing its closing \`>\` before the next \`<\` \u2014 the following element is swallowed as bogus attribute text and never becomes a real node.`,
71198
+ fixHint: "Close the previous tag's `>` before opening the next element.",
71199
+ snippet: truncateSnippet(tag.raw)
71200
+ });
71201
+ }
71202
+ return findings;
71203
+ },
71173
71204
  // invalid_inline_script_syntax (malformed close tag)
71174
71205
  ({ source }) => {
71175
71206
  if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source)) return [];
@@ -81878,6 +81909,7 @@ __export(src_exports, {
81878
81909
  DEFAULT_HDR10_MASTERING: () => DEFAULT_HDR10_MASTERING,
81879
81910
  DEFAULT_VP9_CPU_USED: () => DEFAULT_VP9_CPU_USED,
81880
81911
  DOM_LAYER_MASK_STYLE_ID: () => DOM_LAYER_MASK_STYLE_ID,
81912
+ DrawElementCaptureError: () => DrawElementCaptureError,
81881
81913
  DrawElementVerificationError: () => DrawElementVerificationError,
81882
81914
  ENABLE_BROWSER_POOL: () => ENABLE_BROWSER_POOL,
81883
81915
  ENCODER_PRESETS: () => ENCODER_PRESETS,
@@ -81992,6 +82024,7 @@ __export(src_exports, {
81992
82024
  initializeSession: () => initializeSession,
81993
82025
  injectVideoFramesBatch: () => injectVideoFramesBatch,
81994
82026
  isBlockedNetworkHost: () => isBlockedNetworkHost,
82027
+ isDrawElementCaptureError: () => isDrawElementCaptureError,
81995
82028
  isDrawElementVerificationError: () => isDrawElementVerificationError,
81996
82029
  isExternalFfmpegInterruption: () => isExternalFfmpegInterruption,
81997
82030
  isFatalCaptureFailure: () => isFatalCaptureFailure,
@@ -82107,6 +82140,7 @@ var init_src = __esm({
82107
82140
  init_videoFrameInjector();
82108
82141
  init_hdr();
82109
82142
  init_renderProvenance();
82143
+ init_drawElementCaptureError();
82110
82144
  }
82111
82145
  });
82112
82146
 
@@ -86818,7 +86852,7 @@ function revertedRouting(routing) {
86818
86852
  return freezeRouting({ ...routing, state: "reverted" });
86819
86853
  }
86820
86854
  function replanAfterFailure(plan2, failure) {
86821
- if (plan2.kind === "sdr_disk" && failure.kind === "draw_element_verification") {
86855
+ if (plan2.kind === "sdr_disk" && (failure.kind === "draw_element_verification" || failure.kind === "draw_element_capture")) {
86822
86856
  return createCapturePlan({
86823
86857
  ...plan2,
86824
86858
  forceScreenshot: true,
@@ -96523,7 +96557,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
96523
96557
  if (failure.kind === "cancelled") {
96524
96558
  throw error;
96525
96559
  }
96526
- if (isDrawElementVerificationError(error)) {
96560
+ if (isDrawElementVerificationError(error) || isDrawElementCaptureError(error)) {
96527
96561
  throw error;
96528
96562
  }
96529
96563
  const remaining = findMissingFrameRanges(
@@ -96751,7 +96785,7 @@ function resolveParallelRouterRetryPlan(args) {
96751
96785
  }
96752
96786
  function shouldRetryViaPinnedFallback(args) {
96753
96787
  if (args.isCancellation || args.isEncoderInterrupted) return false;
96754
- if (args.isVerifyError) return true;
96788
+ if (args.isVerifyError || args.isDeCaptureError) return true;
96755
96789
  if (args.isDeRendererStall === true || args.isSequentialCaptureStall === true) return true;
96756
96790
  return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
96757
96791
  }
@@ -96777,6 +96811,9 @@ async function closeOrphanedProbeForRetry(probe2, closer, log, retryContext) {
96777
96811
  function shouldStreamParallelCapture(args) {
96778
96812
  return args.routerEnabled && args.workerCount > 1 && !args.useDrawElement && args.outputFormat === "mp4" && args.streamingOk && !args.layeredOrEffectRoute;
96779
96813
  }
96814
+ function shouldClampDefaultDrawElement(args) {
96815
+ return args.useDrawElement && !args.fastCaptureExplicitOptIn && (!args.useStreamingEncode || args.workerCount > 1) && !args.deParallelStreamVerified;
96816
+ }
96780
96817
  function resolveCaptureForceScreenshotForPageSideCompositing(args) {
96781
96818
  return args.usePageSideCompositing ? true : args.forceScreenshot;
96782
96819
  }
@@ -97519,6 +97556,32 @@ async function executeRenderPipeline(input) {
97519
97556
  deWorkerInversion: deWorkerInversion ?? "none",
97520
97557
  deParallelRouter: deParallelRouter ?? "none"
97521
97558
  });
97559
+ let useStreamingEncode = shouldUseStreamingEncode(
97560
+ cfg,
97561
+ outputFormat,
97562
+ workerCount,
97563
+ job.duration,
97564
+ deParallelStreamForced
97565
+ );
97566
+ const deParallelStreamVerified = (deParallelStreamForced || process.env.HF_DE_PARALLEL_STREAM === "true") && useStreamingEncode && workerCount > 1;
97567
+ if (shouldClampDefaultDrawElement({
97568
+ useDrawElement: cfg.useDrawElement,
97569
+ fastCaptureExplicitOptIn: process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE === "true",
97570
+ useStreamingEncode,
97571
+ workerCount,
97572
+ deParallelStreamVerified
97573
+ })) {
97574
+ cfg.useDrawElement = false;
97575
+ deClampReason = workerCount > 1 ? "parallel" : "disk_path";
97576
+ log.info(
97577
+ "[Render] Fast capture: default-on drawElement disabled for this render \u2014 " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
97578
+ );
97579
+ if (probeSession && probeSession.captureMode === "drawelement") {
97580
+ lastBrowserConsole = probeSession.browserConsoleBuffer;
97581
+ await closeCaptureSession(probeSession);
97582
+ probeSession = null;
97583
+ }
97584
+ }
97522
97585
  const captureParallelStreamRouterEnabled = process.env.HF_CAPTURE_PARALLEL_STREAM === "true";
97523
97586
  const captureParallelStreamArgs = {
97524
97587
  workerCount,
@@ -97550,7 +97613,7 @@ async function executeRenderPipeline(input) {
97550
97613
  await closeCaptureSession(probeSession);
97551
97614
  probeSession = null;
97552
97615
  }
97553
- let useStreamingEncode = shouldUseStreamingEncode(
97616
+ useStreamingEncode = shouldUseStreamingEncode(
97554
97617
  cfg,
97555
97618
  outputFormat,
97556
97619
  workerCount,
@@ -97565,18 +97628,6 @@ async function executeRenderPipeline(input) {
97565
97628
  durationSeconds: job.duration,
97566
97629
  maxDurationSeconds: cfg.streamingEncodeMaxDurationSeconds
97567
97630
  });
97568
- const deParallelStreamVerified = (deParallelStreamForced || process.env.HF_DE_PARALLEL_STREAM === "true") && useStreamingEncode && workerCount > 1;
97569
- if (cfg.useDrawElement && process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE !== "true" && (!useStreamingEncode || workerCount > 1) && !deParallelStreamVerified) {
97570
- cfg.useDrawElement = false;
97571
- deClampReason = workerCount > 1 ? "parallel" : "disk_path";
97572
- log.info(
97573
- "[Render] Fast capture: default-on drawElement disabled for this render \u2014 " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
97574
- );
97575
- if (probeSession && probeSession.captureMode === "drawelement") {
97576
- await closeCaptureSession(probeSession);
97577
- probeSession = null;
97578
- }
97579
- }
97580
97631
  const FORMAT_EXT = {
97581
97632
  mp4: ".mp4",
97582
97633
  webm: ".webm",
@@ -97837,11 +97888,13 @@ async function executeRenderPipeline(input) {
97837
97888
  streamingRes = await invokeStreaming();
97838
97889
  } catch (err) {
97839
97890
  const isVerifyError = isDrawElementVerificationError(err);
97891
+ const isDeCaptureError = isDrawElementCaptureError(err);
97840
97892
  const isDeStall = isDeRendererStallError(err);
97841
97893
  const isSequentialStall = isSequentialCaptureStallError(err);
97842
97894
  const isCancellation = err instanceof RenderCancelledError || executionSignal?.aborted === true;
97843
97895
  if (!shouldRetryViaPinnedFallback({
97844
97896
  isVerifyError,
97897
+ isDeCaptureError,
97845
97898
  isCancellation,
97846
97899
  isEncoderInterrupted: err instanceof EncoderInterruptedError,
97847
97900
  deWorkerInversion,
@@ -97862,12 +97915,12 @@ async function executeRenderPipeline(input) {
97862
97915
  deFallbackReason = isMemoryExhaustion ? "oom" : isDeStall ? "de_renderer_stall" : "capture_error";
97863
97916
  }
97864
97917
  log.warn(
97865
- isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : isDeStall ? "[Render] drawElement renderer stalled; re-rendering via screenshot" : isSequentialStall ? "[Render] sequential capture stalled; retrying on a fresh screenshot session" : "[Render] capture failed on the pinned worker count; re-rendering via screenshot",
97918
+ isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : isDeStall ? "[Render] drawElement renderer stalled; re-rendering via screenshot" : isSequentialStall ? "[Render] sequential capture stalled; retrying on a fresh screenshot session" : "[Render] capture failed; re-rendering via a fresh screenshot session",
97866
97919
  { error: err instanceof Error ? err.message : String(err) }
97867
97920
  );
97868
97921
  observability.checkpoint(
97869
97922
  "capture_streaming",
97870
- isVerifyError ? "drawElement self-verify failed; retrying with forceScreenshot" : isDeStall ? "drawElement renderer stalled; retrying with forceScreenshot" : isSequentialStall ? "sequential capture stalled; retrying with a fresh screenshot session" : "capture failed on pinned worker count; retrying with forceScreenshot"
97923
+ isVerifyError ? "drawElement self-verify failed; retrying with forceScreenshot" : isDeStall ? "drawElement renderer stalled; retrying with forceScreenshot" : isSequentialStall ? "sequential capture stalled; retrying with a fresh screenshot session" : "capture failed; retrying with a fresh screenshot session"
97871
97924
  );
97872
97925
  const failedRouting = capturePlan.routing.kind;
97873
97926
  capturePlan = replanAfterFailure(
@@ -97980,22 +98033,22 @@ async function executeRenderPipeline(input) {
97980
98033
  try {
97981
98034
  captureRes = await invokeDiskCapture(capturePlan);
97982
98035
  } catch (err) {
97983
- if (!isDrawElementVerificationError(err) || err instanceof RenderCancelledError || executionSignal?.aborted === true) {
98036
+ if (!isDrawElementVerificationError(err) && !isDrawElementCaptureError(err) || err instanceof RenderCancelledError || executionSignal?.aborted === true) {
97984
98037
  throw err;
97985
98038
  }
97986
- deSelfVerifyFallback = true;
98039
+ deSelfVerifyFallback = isDrawElementVerificationError(err);
97987
98040
  const t = deVerifyFallbackTelemetry(err);
97988
- deFallbackReason = t.reason;
98041
+ deFallbackReason = deSelfVerifyFallback ? t.reason : "capture_error";
97989
98042
  deFallbackFailedDb = t.failedDb;
97990
98043
  deFallbackFrameIndex = t.frameIndex;
97991
98044
  deFallbackThresholdDb = t.thresholdDb;
97992
98045
  log.warn(
97993
- "[Render] drawElement self-verification failed on the parallel disk path; re-rendering via screenshot",
98046
+ "[Render] drawElement capture failed on the parallel disk path; re-rendering via screenshot",
97994
98047
  { error: err instanceof Error ? err.message : String(err) }
97995
98048
  );
97996
98049
  observability.checkpoint(
97997
98050
  "capture_disk",
97998
- "drawElement self-verify failed; retrying with forceScreenshot"
98051
+ "drawElement capture failed; retrying with a fresh screenshot session"
97999
98052
  );
98000
98053
  rmSync14(framesDir, { recursive: true, force: true });
98001
98054
  mkdirSync17(framesDir, { recursive: true });
@@ -98008,7 +98061,9 @@ async function executeRenderPipeline(input) {
98008
98061
  probeSession = null;
98009
98062
  await closeOrphanedProbeForRetry(orphaned, closeCaptureSession, log, "disk verify");
98010
98063
  }
98011
- capturePlan = replanAfterFailure(capturePlan, { kind: "draw_element_verification" });
98064
+ capturePlan = replanAfterFailure(capturePlan, {
98065
+ kind: deSelfVerifyFallback ? "draw_element_verification" : "draw_element_capture"
98066
+ });
98012
98067
  syncCapturePlan();
98013
98068
  updateCaptureObservability({
98014
98069
  forceScreenshot: capturePlan.forceScreenshot,
@@ -99571,8 +99626,8 @@ async function runFontLocalize(io, localize) {
99571
99626
  }
99572
99627
 
99573
99628
  // src/version.ts
99574
- var VERSION = true ? "0.8.34" : "0.0.0-dev";
99575
- var PRODUCER_VERSION = true ? "0.8.34" : "0.0.0-dev";
99629
+ var VERSION = true ? "0.8.35" : "0.0.0-dev";
99630
+ var PRODUCER_VERSION = true ? "0.8.35" : "0.0.0-dev";
99576
99631
 
99577
99632
  // src/fontLocalizeCli.ts
99578
99633
  async function readStdin() {
@@ -1,4 +1,4 @@
1
- "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.34/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
1
+ "use strict";var HyperframesPlayer=(()=>{var ee=Object.defineProperty;var et=Object.getOwnPropertyDescriptor;var tt=Object.getOwnPropertyNames;var it=Object.prototype.hasOwnProperty;var rt=(r,e)=>{for(var t in e)ee(r,t,{get:e[t],enumerable:!0})},nt=(r,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of tt(e))!it.call(r,n)&&n!==t&&ee(r,n,{get:()=>e[n],enumerable:!(i=et(e,n))||i.enumerable});return r};var ot=r=>nt(ee({},"__esModule",{value:!0}),r);var Ht={};rt(Ht,{HyperframesPlayer:()=>K,SPEED_PRESETS:()=>re,formatSpeed:()=>O,formatTime:()=>q});function we(r){return r.hasRuntime||r.runtimeInjected?!1:!!(r.hasNestedCompositions||r.hasTimelines&&r.attempts>=5)}function P(r){return typeof r=="object"&&r!==null}function Ae(r){return P(r)&&typeof r.getDuration=="function"}function Ce(r){return P(r)&&typeof r.duration=="function"&&typeof r.time=="function"&&typeof r.seek=="function"&&typeof r.play=="function"&&typeof r.pause=="function"}var k="https://cdn.jsdelivr.net/npm/@hyperframes/core@0.8.35/dist/hyperframe.runtime.iife.js";function N(r){if(r===null)return null;let e=Number.parseInt(r,10);return Number.isFinite(e)&&e>0?e:null}function at(r){let e=r?.querySelector("[data-composition-id][data-width][data-height]")??r?.querySelector("[data-width][data-height]");if(!e)return null;let t=N(e.getAttribute("data-width")),i=N(e.getAttribute("data-height"));return t!==null&&i!==null?{width:t,height:i}:null}var W=class{constructor(e,t){this._iframe=e;this._callbacks=t}_iframe;_callbacks;_interval=null;_runtimeInjected=!1;get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let e=0;this._interval=setInterval(()=>{e++;try{let t=this._iframe.contentWindow;if(!t)return;let i=!!(t.__hf||t.__player),n=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!this._iframe.contentDocument?.querySelector("[data-composition-src]");if(we({hasRuntime:i,hasTimelines:n,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:e})){this._injectRuntime();return}if(this._runtimeInjected&&!i)return;let d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();let s=at(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:s});return}}catch{}e>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{let e=this._iframe.contentWindow;return e?this._resolveDirectTimelineAdapterFromWindow(e):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(e){return this._resolveDirectTimelineAdapterFromWindow(e)}hasRuntimeBridge(e){return Reflect.get(e,"__hf")!==void 0||P(Reflect.get(e,"__player"))}_injectRuntime(){this._runtimeInjected=!0;try{let e=this._iframe.contentDocument;if(!e)return;let t=e.createElement("script");t.src=k,(e.head||e.documentElement).appendChild(t),this._callbacks.onRuntimeInjected?.()}catch{}}_resolveDirectTimelineAdapterFromWindow(e){if(this.hasRuntimeBridge(e))return null;let t=Reflect.get(e,"__timelines");if(!P(t))return null;let i=Object.keys(t);if(i.length===0)return null;let n=this._iframe.contentDocument?.querySelector("[data-composition-id]")?.getAttribute("data-composition-id"),o=n&&n in t?n:i[i.length-1],d=t[o];return Ce(d)?d:null}_resolvePlaybackDurationAdapter(e){let t=Reflect.get(e,"__player");if(Ae(t))return{kind:"runtime",getDuration:()=>t.getDuration()};let i=this._resolveDirectTimelineAdapterFromWindow(e);return i?{kind:"direct-timeline",timeline:i,getDuration:()=>i.duration()}:null}};var Re=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;
@@ -78,10 +78,10 @@ Treat tiny unstyled content, canvas-sized icons, missing hero elements, or timel
78
78
 
79
79
  - **Search the catalog before writing motion by hand.** `npx hyperframes catalog --query "<the beat, in plain English>"`. Search is entirely local: there is no hosted tier, no account, and the query text is never sent anywhere. By default it ranks on vocabulary shared with the item's name, title and description, which misses any phrasing that does not reuse the catalog's own wording. Add `--on-device` to rank by meaning instead (see the offline tier below).
80
80
  - **Query in English even when the video is not.** Both tiers index an English catalog, so a query in another script produces no searchable terms and returns nothing. Describe the move in English; the on-screen copy stays in whatever language the video needs. `No searchable words in query` means exactly this and is not a missing component, so do not report it as a catalog gap.
81
- - **Read which tier answered; never infer it from results appearing.** With `--json` the envelope carries `query`, `tier` (`on-device` or `words`), `tier_detail`, `dropped`, `unindexed`, `shown`, `total` and `results`, plus `top_score` when the answering tier produces one and `warnings` when a tier was asked for and could not run. A weak result on `words` is expected; the same result on `on-device` is a bug. `top_score` is on-device only and has no threshold behind it: the ranker returns the whole catalog in some order for every query, so read it as evidence rather than as a pass or fail.
81
+ - **Read which tier answered; never infer it from results appearing.** With `--json` the envelope carries `query`, `tier` (`on-device` or `words`), `tier_detail`, `dropped`, `unindexed`, `shown`, `total` and `results`, plus `top_score` when the answering tier produces one and `warnings` when a tier was asked for and could not run, or when a search returned nothing and a better tier is still waiting on someone's consent. A weak result on `words` is expected; the same result on `on-device` is a bug. `top_score` is on-device only and has no threshold behind it: the ranker returns the whole catalog in some order for every query, so read it as evidence rather than as a pass or fail.
82
82
  - **`dropped` and `unindexed` are opposite skews between the registry and the on-device index, and rewording the query fixes neither.** `dropped` counts ranked names this registry cannot install, so the strongest matches are the ones being lost. `unindexed` counts registry moves the index cannot see at all, which no query can ever return. Refreshing the registry is not the answer to either: its manifest carries a 24h TTL and heals itself, while the vectors are a separately published artifact fetched into `~/.hyperframes/catalog/`. Re-running with `--on-device` refetches that index when `unindexed` is above zero, so that is the remedy to hand the user. A pure over-coverage skew (`dropped` above zero while `unindexed` is zero) does not trigger the refetch; clearing `~/.hyperframes/catalog/` is the only way out of that one. Both counts are of names rather than of results, so either can exceed `total`.
83
83
  - **When a search comes back with nothing worth installing, say so.** `npx hyperframes feedback --search-miss "<the query you ran>" --wanted "<the move you needed>" --tier <the tier that answered>`. You do not have to assemble that line: `catalog --query` prints it pre-filled, and every `--json` search envelope carries it as `report_gap` with the query and tier already correct — fill in `--wanted` and send. This is the only path that sends a query anywhere, and it is a separate deliberate command precisely so plain `catalog --query` keeps its promise of sending nothing. **Report on either tier**, whenever the results do not do the thing; do not hold out for the on-device tier, which needs a consented 33 MB download and is therefore off in most agent runs — waiting for it means never reporting at all. The tier rides along in the report, so a vocabulary miss stays distinguishable from a meaning miss without you having to judge which one you hit. What comes back is a list of moves the catalog does not have yet, read directly rather than guessed from install counts, so the phrasing that matters is the effect you wanted, not the item name you imagined. It carries no rating and never lands in the rating metric.
84
- - **Offer the offline tier; never enable it silently.** A one-time ~33 MB download (a quantized ONNX build of `bge-small-en-v1.5` plus its tokenizer, pinned to a fixed revision) and the catalog vectors from the registry, both cached under `~/.hyperframes/`, neither added to the project or any package. Once cached it ranks by meaning with nothing sent. Say the size out loud and let the person decide, then pass `--on-device` (with `-y` to skip the prompt) once they agree. The interactive offer only fires on a TTY, and under `--json` nothing about it is printed at all, so in an agent run you have to raise it with the user yourself.
84
+ - **Offer the offline tier; never enable it silently.** A one-time ~33 MB download (a quantized ONNX build of `bge-small-en-v1.5` plus its tokenizer, pinned to a fixed revision) and the catalog vectors from the registry, both cached under `~/.hyperframes/`, neither added to the project or any package. Once cached it ranks by meaning with nothing sent. Say the size out loud and let the person decide, then pass `--on-device` (with `-y` to skip the prompt) once they agree. The interactive offer only fires on a TTY. Under `--json` there is no prompt, but a search that found nothing puts the same ask in `warnings`, so read that array and put the decision to the user yourself.
85
85
 
86
86
  - Prefer `--json` for agent and CI calls. Server-mode `render`, `preview`, and `play` do not provide ordinary JSON output; `preview --selection --json` and `preview --context --json` are query-mode exceptions.
87
87
  - `doctor --json` always exits zero. Gate on its payload:
@@ -1,4 +1,4 @@
1
- var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-CkxPQxLJ.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
1
+ var ve=Object.defineProperty;var be=(n,i,e)=>i in n?ve(n,i,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[i]=e;var u=(n,i,e)=>be(n,typeof i!="symbol"?i+"":i,e);import{r as le,i as we,a as Ae}from"./index-BRr1JoHX.js";function Ee(n){return n.hasRuntime||n.runtimeInjected?!1:!!(n.hasNestedCompositions||n.hasTimelines&&n.attempts>=5)}function V(n){return typeof n=="object"&&n!==null}function Ce(n){return V(n)&&typeof n.getDuration=="function"}function Te(n){return V(n)&&typeof n.duration=="function"&&typeof n.time=="function"&&typeof n.seek=="function"&&typeof n.play=="function"&&typeof n.pause=="function"}function Se(n){if(!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(n))throw new Error(`Invalid HyperFrames runtime version: ${n}`);return`https://cdn.jsdelivr.net/npm/@hyperframes/core@${n}/dist/hyperframe.runtime.iife.js`}const H=typeof __HYPERFRAMES_RUNTIME_CDN_URL__=="string"?__HYPERFRAMES_RUNTIME_CDN_URL__:Se("0.0.0-dev");function $(n){if(n===null)return null;const i=Number.parseInt(n,10);return Number.isFinite(i)&&i>0?i:null}function Re(n){const i=(n==null?void 0:n.querySelector("[data-composition-id][data-width][data-height]"))??(n==null?void 0:n.querySelector("[data-width][data-height]"));if(!i)return null;const e=$(i.getAttribute("data-width")),t=$(i.getAttribute("data-height"));return e!==null&&t!==null?{width:e,height:t}:null}class xe{constructor(i,e){u(this,"_interval",null);u(this,"_runtimeInjected",!1);this._iframe=i,this._callbacks=e}get runtimeInjected(){return this._runtimeInjected}start(){this.stop(),this._runtimeInjected=!1;let i=0;this._interval=setInterval(()=>{var e;i++;try{const t=this._iframe.contentWindow;if(!t)return;const r=!!(t.__hf||t.__player),s=!!(t.__timelines&&Object.keys(t.__timelines).length>0),o=!!((e=this._iframe.contentDocument)!=null&&e.querySelector("[data-composition-src]"));if(Ee({hasRuntime:r,hasTimelines:s,hasNestedCompositions:o,runtimeInjected:this._runtimeInjected,attempts:i})){this._injectRuntime();return}if(this._runtimeInjected&&!r)return;const d=this._resolvePlaybackDurationAdapter(t);if(d&&d.getDuration()>0){this.stop();const p=Re(this._iframe.contentDocument);this._callbacks.onReady({duration:d.getDuration(),adapter:d,compositionSize:p});return}}catch{}i>=40&&(this.stop(),this._callbacks.onError("Composition timeline not found after 8s"))},200)}stop(){this._interval!==null&&(clearInterval(this._interval),this._interval=null)}resolveDirectTimelineAdapter(){try{const i=this._iframe.contentWindow;return i?this._resolveDirectTimelineAdapterFromWindow(i):null}catch{return null}}resolveDirectTimelineAdapterFromWindow(i){return this._resolveDirectTimelineAdapterFromWindow(i)}hasRuntimeBridge(i){return Reflect.get(i,"__hf")!==void 0||V(Reflect.get(i,"__player"))}_injectRuntime(){var i,e;this._runtimeInjected=!0;try{const t=this._iframe.contentDocument;if(!t)return;const r=t.createElement("script");r.src=H,(t.head||t.documentElement).appendChild(r),(e=(i=this._callbacks).onRuntimeInjected)==null||e.call(i)}catch{}}_resolveDirectTimelineAdapterFromWindow(i){var d,p;if(this.hasRuntimeBridge(i))return null;const e=Reflect.get(i,"__timelines");if(!V(e))return null;const t=Object.keys(e);if(t.length===0)return null;const r=(p=(d=this._iframe.contentDocument)==null?void 0:d.querySelector("[data-composition-id]"))==null?void 0:p.getAttribute("data-composition-id"),s=r&&r in e?r:t[t.length-1],o=e[s];return Te(o)?o:null}_resolvePlaybackDurationAdapter(i){const e=Reflect.get(i,"__player");if(Ce(e))return{kind:"runtime",getDuration:()=>e.getDuration()};const t=this._resolveDirectTimelineAdapterFromWindow(i);return t?{kind:"direct-timeline",timeline:t,getDuration:()=>t.duration()}:null}}const Me=`
2
2
  :host {
3
3
  display: block;
4
4
  position: relative;