@tempo-ai/visual-review 0.0.127 → 0.0.128

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/bin.js CHANGED
@@ -7,7 +7,7 @@ async function main(argv = process.argv.slice(2)) {
7
7
  const [command, ...commandArgs] = argv;
8
8
  switch (command) {
9
9
  case "capture":
10
- return await (await import("./cli-2B56ETHT.js")).main(commandArgs);
10
+ return await (await import("./cli-3JLEAQTK.js")).main(commandArgs);
11
11
  case "claim":
12
12
  return await (await import("./claim-C5UVLSMX.js")).main(commandArgs);
13
13
  case "report":
@@ -40009,7 +40009,7 @@ var MissingRootDepsError = class extends TempoDevServerError {
40009
40009
  // ../tempo-sdk/package.json
40010
40010
  var package_default = {
40011
40011
  name: "tempo-sdk",
40012
- version: "0.0.66",
40012
+ version: "0.0.69",
40013
40013
  publishConfig: {
40014
40014
  tag: "sdk-v2-latest"
40015
40015
  },
@@ -40118,7 +40118,7 @@ var package_default = {
40118
40118
  demo: "TEMPO=true pnpm --filter @tempo-modules/vite-annotate-plugin-demo dev",
40119
40119
  "demo:nextjs": "TEMPO=true pnpm --filter @tempo-modules/tempo-sdk-nextjs-demo dev",
40120
40120
  test: "vitest run",
40121
- "test:browser": "vitest run canvas-dependency-scan-browser.test.ts pruned-module-deletion-browser.test.ts asset-live-preview-browser.test.ts asset-popover-lifecycle-browser.test.ts component-controls-browser.test.ts canvas-controls-browser.test.ts canvas-capture-determinism-browser.test.ts canvas-host-vite-e2e.test.ts canvas-host-packed-sdk-e2e.test.ts error-tracking-e2e.test.ts",
40121
+ "test:browser": "vitest run canvas-dependency-scan-browser.test.ts pruned-module-deletion-browser.test.ts asset-live-preview-browser.test.ts asset-popover-lifecycle-browser.test.ts component-controls-browser.test.ts canvas-controls-browser.test.ts canvas-capture-determinism-browser.test.ts canvas-host-vite-e2e.test.ts canvas-host-packed-sdk-e2e.test.ts error-tracking-e2e.test.ts astro-integration.test.ts astro-storyboard-routing.test.ts astro-react-integration.test.ts astro-descriptor-browser.test.ts astro-packed.test.ts",
40122
40122
  "test:watch": "vitest",
40123
40123
  "test:nextjs:unit": "vitest run nextjs-loader.test.ts nextjs-wrapper.test.ts nextjs-fixtures.test.ts nextjs-published.test.ts",
40124
40124
  "test:nextjs:integration": "vitest run nextjs-e2e-correctness.test.ts",
@@ -43730,6 +43730,15 @@ function deliver(reader, scan) {
43730
43730
  });
43731
43731
  return reader.delivery;
43732
43732
  }
43733
+ function unchanged(previous, next) {
43734
+ if (!previous || previous.size !== next.size) return false;
43735
+ for (const [path34, stamp] of next) {
43736
+ const before = previous.get(path34);
43737
+ if (!before || before.isDir !== stamp.isDir || !stamp.isDir && (before.mtimeMs !== stamp.mtimeMs || before.size !== stamp.size))
43738
+ return false;
43739
+ }
43740
+ return true;
43741
+ }
43733
43742
  function createPollingScanPool(scan = scanTree) {
43734
43743
  const scans = /* @__PURE__ */ new Map();
43735
43744
  let queue = Promise.resolve();
@@ -43751,7 +43760,9 @@ function createPollingScanPool(scan = scanTree) {
43751
43760
  running: null,
43752
43761
  baseline: null,
43753
43762
  scanCount: 0,
43754
- lastDurationMs: 0
43763
+ lastDurationMs: 0,
43764
+ lastCompletedAt: 0,
43765
+ unchangedScans: 0
43755
43766
  };
43756
43767
  scans.set(key2, entry);
43757
43768
  }
@@ -43765,13 +43776,26 @@ function createPollingScanPool(scan = scanTree) {
43765
43776
  const { nativeIgnorePaths, relativePathFilters } = splitIgnorePatterns(exclusions);
43766
43777
  const keep = createEventKeepFilter(root2, relativePathFilters);
43767
43778
  function schedule() {
43768
- if (!shared.readers.size || shared.timer) return;
43769
- const interval = Math.min(...[...shared.readers].map((r) => r.interval));
43779
+ if (shared.timer) clearTimeout(shared.timer);
43780
+ shared.timer = null;
43781
+ if (!shared.readers.size || shared.running) return;
43782
+ const interval = Math.min(
43783
+ ...[...shared.readers].map(
43784
+ (r) => Math.min(
43785
+ r.interval * 2 ** shared.unchangedScans,
43786
+ Math.max(r.interval, r.maxIdleInterval ?? r.interval)
43787
+ )
43788
+ )
43789
+ );
43790
+ const delay2 = Math.max(
43791
+ 0,
43792
+ interval - (performance.now() - shared.lastCompletedAt)
43793
+ );
43770
43794
  shared.timer = setTimeout(() => {
43771
43795
  shared.timer = null;
43772
43796
  void run().catch(() => {
43773
43797
  });
43774
- }, interval);
43798
+ }, delay2);
43775
43799
  }
43776
43800
  function run() {
43777
43801
  if (shared.running) return shared.running;
@@ -43781,12 +43805,14 @@ function createPollingScanPool(scan = scanTree) {
43781
43805
  const snapshot = await scan(root2, nativeIgnorePaths, keep);
43782
43806
  shared.lastDurationMs = performance.now() - start;
43783
43807
  shared.scanCount++;
43808
+ shared.unchangedScans = unchanged(shared.baseline, snapshot) ? Math.min(30, shared.unchangedScans + 1) : 0;
43784
43809
  shared.baseline = snapshot;
43785
43810
  await Promise.all([...shared.readers].map((r) => deliver(r, snapshot)));
43786
43811
  });
43787
43812
  queue = operation.catch(() => {
43788
43813
  });
43789
43814
  shared.running = operation.catch((error) => {
43815
+ shared.unchangedScans = 0;
43790
43816
  for (const r of shared.readers) {
43791
43817
  try {
43792
43818
  r.onError(
@@ -43798,13 +43824,16 @@ function createPollingScanPool(scan = scanTree) {
43798
43824
  throw error;
43799
43825
  }).finally(() => {
43800
43826
  shared.running = null;
43827
+ shared.lastCompletedAt = performance.now();
43801
43828
  schedule();
43802
43829
  });
43803
43830
  return shared.running;
43804
43831
  }
43805
43832
  try {
43806
- if (shared.baseline) await deliver(subscriber, shared.baseline);
43807
- else await run();
43833
+ if (shared.baseline) {
43834
+ await deliver(subscriber, shared.baseline);
43835
+ schedule();
43836
+ } else await run();
43808
43837
  } catch (error) {
43809
43838
  subscriber.active = false;
43810
43839
  shared.readers.delete(subscriber);
@@ -43819,7 +43848,10 @@ function createPollingScanPool(scan = scanTree) {
43819
43848
  subscriber.active = false;
43820
43849
  shared.readers.delete(subscriber);
43821
43850
  await subscriber.delivery;
43822
- if (shared.readers.size) return;
43851
+ if (shared.readers.size) {
43852
+ schedule();
43853
+ return;
43854
+ }
43823
43855
  if (shared.timer) clearTimeout(shared.timer);
43824
43856
  shared.timer = null;
43825
43857
  if (scans.get(key2) === shared) scans.delete(key2);
@@ -43850,6 +43882,7 @@ var DEFAULT_DEBOUNCE_MS = 100;
43850
43882
  var DEFAULT_MAX_BATCH_SIZE = 1e3;
43851
43883
  var DEFAULT_MAX_BUFFERED_EVENTS = 3e4;
43852
43884
  var DEFAULT_POLLING_INTERVAL_MS = 500;
43885
+ var DEFAULT_IDLE_POLLING_INTERVAL_MS = 5e3;
43853
43886
  var MIN_POLLING_INTERVAL_MS = 10;
43854
43887
  var EINTR_RESTART_DELAY_MS = 100;
43855
43888
  var MAX_RECOVERY_RESTARTS = 50;
@@ -44045,6 +44078,13 @@ async function watchLocal(rootPath, callback, options = {}) {
44045
44078
  onError2(new Error("Event buffer full, dropping events"));
44046
44079
  return;
44047
44080
  }
44081
+ if (kept.length > remaining) {
44082
+ if (autoRecover) {
44083
+ void handleErrorWithRecovery("buffer overflow");
44084
+ return;
44085
+ }
44086
+ onError2(new Error("Event buffer full, dropping events"));
44087
+ }
44048
44088
  eventBuffer.push(...kept.slice(0, remaining));
44049
44089
  scheduleFlush();
44050
44090
  },
@@ -44147,6 +44187,9 @@ async function watchWithPolling(rootPath, callback, options) {
44147
44187
  ignore,
44148
44188
  {
44149
44189
  interval: pollingInterval,
44190
+ // Default watches stay responsive while editing, then back off when
44191
+ // idle. An explicit interval preserves the caller's fixed cadence.
44192
+ maxIdleInterval: options.pollingIntervalMs === void 0 ? DEFAULT_IDLE_POLLING_INTERVAL_MS : pollingInterval,
44150
44193
  onError: onError2,
44151
44194
  async onScan(scan) {
44152
44195
  if (disposed) return;
@@ -44267,6 +44310,73 @@ async function parcelEventToFileEvent(event, rootInfo) {
44267
44310
  };
44268
44311
  }
44269
44312
 
44313
+ // ../../modules/file-watcher/reconciliation.ts
44314
+ function createReconciliationQueue(reconcile, options = {}) {
44315
+ const now = options.now ?? Date.now;
44316
+ const minInterval = options.minIntervalMs ?? 5e3;
44317
+ let dirtyRevision = 0;
44318
+ let completedRevision = 0;
44319
+ let running = false;
44320
+ let disposed = false;
44321
+ let failures = 0;
44322
+ let nextRunAt = Number.NEGATIVE_INFINITY;
44323
+ let timer = null;
44324
+ function schedule() {
44325
+ if (disposed || running || timer !== null || completedRevision === dirtyRevision)
44326
+ return;
44327
+ const delay2 = nextRunAt - now();
44328
+ if (delay2 <= 0) void run();
44329
+ else
44330
+ timer = setTimeout(() => {
44331
+ timer = null;
44332
+ void run();
44333
+ }, delay2);
44334
+ }
44335
+ async function run() {
44336
+ if (disposed || running) return;
44337
+ running = true;
44338
+ const revision = dirtyRevision;
44339
+ nextRunAt = now() + minInterval;
44340
+ try {
44341
+ await reconcile();
44342
+ if (!disposed) completedRevision = revision;
44343
+ failures = 0;
44344
+ } catch (error) {
44345
+ const delays = [5e3, 15e3, 6e4];
44346
+ nextRunAt = now() + delays[Math.min(failures++, delays.length - 1)];
44347
+ try {
44348
+ options.onError?.(error);
44349
+ } catch {
44350
+ }
44351
+ } finally {
44352
+ running = false;
44353
+ schedule();
44354
+ }
44355
+ }
44356
+ return {
44357
+ invalidate() {
44358
+ if (!disposed) {
44359
+ dirtyRevision++;
44360
+ schedule();
44361
+ }
44362
+ },
44363
+ dispose() {
44364
+ disposed = true;
44365
+ if (timer !== null) clearTimeout(timer);
44366
+ timer = null;
44367
+ },
44368
+ getDiagnostics() {
44369
+ return {
44370
+ dirtyRevision,
44371
+ completedRevision,
44372
+ running,
44373
+ failures,
44374
+ pending: !disposed && dirtyRevision !== completedRevision
44375
+ };
44376
+ }
44377
+ };
44378
+ }
44379
+
44270
44380
  // ../tempo-devserver/install-feedback.ts
44271
44381
  var INSTALL_IDLE_TIMEOUT_MS = 5 * 6e4;
44272
44382
  var CONNECTION_CODE = /\b(?:ETIMEDOUT|ESOCKETTIMEDOUT|ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|ENETUNREACH|EHOSTUNREACH|ERR_SOCKET_TIMEOUT|UND_ERR_CONNECT_TIMEOUT|UND_ERR_SOCKET)\b/;
@@ -46275,6 +46385,16 @@ var TempoDevServer = class _TempoDevServer {
46275
46385
  // a debounced repair() call fires. `@modules/file-watcher` wraps
46276
46386
  // @parcel/watcher with recursive watching, batching, coalescing, and
46277
46387
  // auto-recovery, so this path does not need a periodic drift-polling backstop.
46388
+ this.managedReconciliation = createReconciliationQueue(
46389
+ async () => {
46390
+ if (!this.disposed) await this.repair();
46391
+ },
46392
+ {
46393
+ onError: (error) => {
46394
+ this.state.lastError = String(error);
46395
+ }
46396
+ }
46397
+ );
46278
46398
  this.managedFileWatchers = [];
46279
46399
  this.managedWatchVersion = 0;
46280
46400
  this.managedFileWatcherStopPromise = null;
@@ -47637,6 +47757,7 @@ var TempoDevServer = class _TempoDevServer {
47637
47757
  }
47638
47758
  async dispose() {
47639
47759
  this.disposed = true;
47760
+ this.managedReconciliation.dispose();
47640
47761
  this.registry.dispose();
47641
47762
  this.stopUrlHealthProbe();
47642
47763
  await this.stopManagedFileWatchers();
@@ -47883,7 +48004,7 @@ var TempoDevServer = class _TempoDevServer {
47883
48004
  // so one scheduled repair reconciles any drift fully.
47884
48005
  onInterruption: () => {
47885
48006
  if (!this.disposed && version === this.managedWatchVersion)
47886
- this.scheduleManagedRepair();
48007
+ this.managedReconciliation.invalidate();
47887
48008
  }
47888
48009
  }
47889
48010
  );
@@ -47931,6 +48052,10 @@ var TempoDevServer = class _TempoDevServer {
47931
48052
  }
47932
48053
  scheduleManagedRepair() {
47933
48054
  if (this.disposed) return;
48055
+ if (this.managedReconciliation.getDiagnostics().pending) {
48056
+ this.managedReconciliation.invalidate();
48057
+ return;
48058
+ }
47934
48059
  if (this.repairDebounceTimer !== null) {
47935
48060
  clearTimeout(this.repairDebounceTimer);
47936
48061
  }
@@ -47998,7 +48123,7 @@ var TempoDevServer = class _TempoDevServer {
47998
48123
  // converging the generated files with the source of truth even after
47999
48124
  // transient I/O failures.
48000
48125
  scheduleRecoveryReconcile() {
48001
- if (this.disposed || this.reconcileRetryTimer !== null) {
48126
+ if (this.disposed || this.reconcileRetryTimer !== null || this.managedReconciliation.getDiagnostics().pending) {
48002
48127
  return;
48003
48128
  }
48004
48129
  if (this.reconcileRetryCount >= _TempoDevServer.RECONCILE_RETRY_DELAYS.length) {
@@ -58053,4 +58178,4 @@ export {
58053
58178
  buildBaselineCaptureArgs,
58054
58179
  main
58055
58180
  };
58056
- //# sourceMappingURL=chunk-YR24GAJ7.js.map
58181
+ //# sourceMappingURL=chunk-YIQ7EFFN.js.map