@tempo-ai/visual-review 0.0.122 → 0.0.123-staging.2

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
@@ -6,7 +6,7 @@ async function main(argv = process.argv.slice(2)) {
6
6
  const [command, ...commandArgs] = argv;
7
7
  switch (command) {
8
8
  case "capture":
9
- return await (await import("./cli-K6WGJOVH.js")).main(commandArgs);
9
+ return await (await import("./cli-KP6UZ2X7.js")).main(commandArgs);
10
10
  case "claim":
11
11
  return await (await import("./claim-J654JAS6.js")).main(commandArgs);
12
12
  case "report":
@@ -9,7 +9,7 @@ import {
9
9
  import { execFileSync, spawn as spawn6 } from "child_process";
10
10
  import { randomUUID as randomUUID3 } from "crypto";
11
11
  import { mkdir as mkdir7, mkdtemp as mkdtemp2, rm as rm6, writeFile as writeFile7 } from "fs/promises";
12
- import { tmpdir as tmpdir2 } from "os";
12
+ import { tmpdir } from "os";
13
13
  import path18 from "path";
14
14
 
15
15
  // ../canvas-capture-headless/src/capture.ts
@@ -4380,12 +4380,6 @@ function getInstalledWatchProvider() {
4380
4380
  return getSlot().provider;
4381
4381
  }
4382
4382
 
4383
- // ../../modules/file-watcher/watcher.ts
4384
- import { lstat as lstat2, realpath, stat as stat2, unlink } from "fs/promises";
4385
- import { createRequire as createRequire2 } from "module";
4386
- import { tmpdir } from "os";
4387
- import { join as join3, relative } from "path";
4388
-
4389
4383
  // ../../modules/file-watcher/ignore.ts
4390
4384
  import picomatch from "picomatch";
4391
4385
  function asSubtreePath(pattern) {
@@ -4433,7 +4427,7 @@ function resolveIgnoreRoots(realRoot, ignorePaths) {
4433
4427
  }
4434
4428
  return out;
4435
4429
  }
4436
- async function scanTree(realRoot, ignorePaths = []) {
4430
+ async function scanTree(realRoot, ignorePaths = [], keepEntry = () => true) {
4437
4431
  const ignored = resolveIgnoreRoots(realRoot, ignorePaths);
4438
4432
  const scan = /* @__PURE__ */ new Map();
4439
4433
  const pendingStats = [];
@@ -4450,7 +4444,8 @@ async function scanTree(realRoot, ignorePaths = []) {
4450
4444
  }
4451
4445
  for (const entry of entries) {
4452
4446
  const full = join2(dir, entry.name);
4453
- if (ignored.has(full)) continue;
4447
+ if (ignored.has(full) || !keepEntry(full)) continue;
4448
+ if (entry.isDirectory() && !keepEntry(`${full}/`)) continue;
4454
4449
  if (entry.isDirectory() && !entry.isSymbolicLink()) {
4455
4450
  scan.set(full, { mtimeMs: 0, size: 0, isDir: true });
4456
4451
  if (depth < MAX_DEPTH) queue.push({ dir: full, depth: depth + 1 });
@@ -4515,7 +4510,136 @@ async function readScanSnapshot(snapshotPath) {
4515
4510
  }
4516
4511
  }
4517
4512
 
4513
+ // ../../modules/file-watcher/polling-scans.ts
4514
+ function deliver(reader, scan) {
4515
+ reader.delivery = reader.delivery.then(async () => {
4516
+ if (reader.active) await reader.onScan(scan);
4517
+ }).catch((error) => {
4518
+ try {
4519
+ reader.onError(
4520
+ error instanceof Error ? error : new Error(String(error))
4521
+ );
4522
+ } catch {
4523
+ }
4524
+ });
4525
+ return reader.delivery;
4526
+ }
4527
+ function createPollingScanPool(scan = scanTree) {
4528
+ const scans = /* @__PURE__ */ new Map();
4529
+ let queue = Promise.resolve();
4530
+ async function subscribe(root, ignore, reader) {
4531
+ const exclusions = [
4532
+ ...new Set(
4533
+ ignore.filter(
4534
+ (p) => !splitIgnorePatterns([p]).relativePathFilters.length || p.endsWith("/**") || p.endsWith("/")
4535
+ )
4536
+ )
4537
+ ].sort();
4538
+ const key2 = JSON.stringify([root, exclusions]);
4539
+ let entry = scans.get(key2);
4540
+ if (!entry) {
4541
+ entry = {
4542
+ root,
4543
+ readers: /* @__PURE__ */ new Set(),
4544
+ timer: null,
4545
+ running: null,
4546
+ baseline: null,
4547
+ scanCount: 0,
4548
+ lastDurationMs: 0
4549
+ };
4550
+ scans.set(key2, entry);
4551
+ }
4552
+ const shared = entry;
4553
+ const subscriber = {
4554
+ ...reader,
4555
+ active: true,
4556
+ delivery: Promise.resolve()
4557
+ };
4558
+ shared.readers.add(subscriber);
4559
+ const { nativeIgnorePaths, relativePathFilters } = splitIgnorePatterns(exclusions);
4560
+ const keep = createEventKeepFilter(root, relativePathFilters);
4561
+ function schedule() {
4562
+ if (!shared.readers.size || shared.timer) return;
4563
+ const interval = Math.min(...[...shared.readers].map((r) => r.interval));
4564
+ shared.timer = setTimeout(() => {
4565
+ shared.timer = null;
4566
+ void run().catch(() => {
4567
+ });
4568
+ }, interval);
4569
+ }
4570
+ function run() {
4571
+ if (shared.running) return shared.running;
4572
+ const operation = queue.then(async () => {
4573
+ if (!shared.readers.size) return;
4574
+ const start = performance.now();
4575
+ const snapshot = await scan(root, nativeIgnorePaths, keep);
4576
+ shared.lastDurationMs = performance.now() - start;
4577
+ shared.scanCount++;
4578
+ shared.baseline = snapshot;
4579
+ await Promise.all([...shared.readers].map((r) => deliver(r, snapshot)));
4580
+ });
4581
+ queue = operation.catch(() => {
4582
+ });
4583
+ shared.running = operation.catch((error) => {
4584
+ for (const r of shared.readers) {
4585
+ try {
4586
+ r.onError(
4587
+ error instanceof Error ? error : new Error(String(error))
4588
+ );
4589
+ } catch {
4590
+ }
4591
+ }
4592
+ throw error;
4593
+ }).finally(() => {
4594
+ shared.running = null;
4595
+ schedule();
4596
+ });
4597
+ return shared.running;
4598
+ }
4599
+ try {
4600
+ if (shared.baseline) await deliver(subscriber, shared.baseline);
4601
+ else await run();
4602
+ } catch (error) {
4603
+ subscriber.active = false;
4604
+ shared.readers.delete(subscriber);
4605
+ if (!shared.readers.size) {
4606
+ if (shared.timer) clearTimeout(shared.timer);
4607
+ if (scans.get(key2) === shared) scans.delete(key2);
4608
+ }
4609
+ throw error;
4610
+ }
4611
+ return {
4612
+ async unsubscribe() {
4613
+ subscriber.active = false;
4614
+ shared.readers.delete(subscriber);
4615
+ await subscriber.delivery;
4616
+ if (shared.readers.size) return;
4617
+ if (shared.timer) clearTimeout(shared.timer);
4618
+ shared.timer = null;
4619
+ if (scans.get(key2) === shared) scans.delete(key2);
4620
+ await shared.running?.catch(() => {
4621
+ });
4622
+ }
4623
+ };
4624
+ }
4625
+ return {
4626
+ subscribe,
4627
+ getDiagnostics: () => [...scans.values()].map((s) => ({
4628
+ root: s.root,
4629
+ consumers: s.readers.size,
4630
+ entries: s.baseline?.size ?? 0,
4631
+ scanCount: s.scanCount,
4632
+ lastDurationMs: s.lastDurationMs,
4633
+ scanning: s.running !== null
4634
+ }))
4635
+ };
4636
+ }
4637
+ var pollingScanPool = createPollingScanPool();
4638
+
4518
4639
  // ../../modules/file-watcher/watcher.ts
4640
+ import { lstat as lstat2, realpath, stat as stat2 } from "fs/promises";
4641
+ import { createRequire as createRequire2 } from "module";
4642
+ import { relative } from "path";
4519
4643
  var DEFAULT_DEBOUNCE_MS = 100;
4520
4644
  var DEFAULT_MAX_BATCH_SIZE = 1e3;
4521
4645
  var DEFAULT_MAX_BUFFERED_EVENTS = 3e4;
@@ -4529,7 +4653,9 @@ var requireModule = createRequire2(
4529
4653
  var nativeWatcherPromise = null;
4530
4654
  function loadNativeWatcher() {
4531
4655
  nativeWatcherPromise ??= Promise.resolve().then(() => {
4532
- const loaded = requireModule("@parcel/watcher");
4656
+ const loaded = requireModule(
4657
+ "@parcel/watcher"
4658
+ );
4533
4659
  return loaded.default ?? loaded;
4534
4660
  });
4535
4661
  return nativeWatcherPromise;
@@ -4758,25 +4884,20 @@ async function watchWithPolling(rootPath, callback, options) {
4758
4884
  onError = (err) => {
4759
4885
  console.error("[file-watcher] Error:", err.message);
4760
4886
  },
4761
- autoRecover = false,
4762
4887
  snapshotPath,
4763
4888
  resumeFromSnapshot,
4764
4889
  pollingIntervalMs = DEFAULT_POLLING_INTERVAL_MS
4765
4890
  } = options;
4766
4891
  const rootSymlinkInfo = await resolveRootPath(rootPath);
4767
- const { nativeIgnorePaths, relativePathFilters } = splitIgnorePatterns(ignore);
4892
+ const { relativePathFilters } = splitIgnorePatterns(ignore);
4768
4893
  const keepEvent = createEventKeepFilter(
4769
4894
  rootSymlinkInfo.realPath,
4770
4895
  relativePathFilters
4771
4896
  );
4772
4897
  const pollingInterval = Math.max(MIN_POLLING_INTERVAL_MS, pollingIntervalMs);
4773
- const generatedSnapshotPath = join3(
4774
- tmpdir(),
4775
- `file-watcher-polling-${Date.now()}-${Math.random().toString(36).slice(2)}.txt`
4776
- );
4777
- const effectiveSnapshotPath = resumeFromSnapshot ?? snapshotPath ?? generatedSnapshotPath;
4778
- const shouldCleanupSnapshot = !snapshotPath && !resumeFromSnapshot;
4898
+ const effectiveSnapshotPath = snapshotPath ?? resumeFromSnapshot;
4779
4899
  let baseline = null;
4900
+ let snapshotDirty = false;
4780
4901
  if (resumeFromSnapshot) {
4781
4902
  baseline = await readScanSnapshot(resumeFromSnapshot);
4782
4903
  if (!baseline) {
@@ -4789,8 +4910,6 @@ async function watchWithPolling(rootPath, callback, options) {
4789
4910
  }
4790
4911
  let eventBuffer = [];
4791
4912
  let debounceTimer = null;
4792
- let pollTimer = null;
4793
- let pollInFlight = null;
4794
4913
  let disposed = false;
4795
4914
  function scheduleFlush() {
4796
4915
  if (debounceTimer || disposed) return;
@@ -4817,75 +4936,47 @@ async function watchWithPolling(rootPath, callback, options) {
4817
4936
  scheduleFlush();
4818
4937
  }
4819
4938
  }
4820
- async function pollOnce() {
4821
- if (disposed) return;
4822
- if (pollInFlight) return;
4823
- pollInFlight = (async () => {
4824
- try {
4825
- const scan = await scanTree(
4826
- rootSymlinkInfo.realPath,
4827
- nativeIgnorePaths
4828
- );
4939
+ const scanSubscription = await pollingScanPool.subscribe(
4940
+ rootSymlinkInfo.realPath,
4941
+ ignore,
4942
+ {
4943
+ interval: pollingInterval,
4944
+ onError,
4945
+ async onScan(scan) {
4829
4946
  if (disposed) return;
4830
4947
  const previous = baseline;
4831
4948
  baseline = scan;
4832
- void writeScanSnapshot(effectiveSnapshotPath, scan).catch(() => {
4833
- });
4834
- if (!previous) return;
4835
- const polledEvents = diffScans(previous, scan).filter(
4836
- (event) => keepEvent(event.path)
4837
- );
4838
- if (disposed || polledEvents.length === 0) return;
4949
+ const changes = previous ? diffScans(previous, scan) : [];
4950
+ snapshotDirty ||= !previous || changes.length > 0;
4951
+ if (effectiveSnapshotPath && snapshotDirty) {
4952
+ await writeScanSnapshot(effectiveSnapshotPath, scan).then(
4953
+ () => {
4954
+ snapshotDirty = false;
4955
+ },
4956
+ () => {
4957
+ }
4958
+ );
4959
+ }
4960
+ if (disposed || !previous) return;
4961
+ const polledEvents = changes.filter((event) => keepEvent(event.path));
4962
+ if (!polledEvents.length) return;
4839
4963
  const remaining = DEFAULT_MAX_BUFFERED_EVENTS - eventBuffer.length;
4840
- if (remaining <= 0) {
4964
+ if (polledEvents.length > remaining)
4841
4965
  onError(new Error("Event buffer full, dropping events"));
4842
- } else {
4843
- eventBuffer.push(...polledEvents.slice(0, remaining));
4844
- scheduleFlush();
4845
- }
4846
- } catch (err) {
4847
- onError(err instanceof Error ? err : new Error(String(err)));
4848
- if (autoRecover) {
4849
- baseline = null;
4850
- }
4851
- } finally {
4852
- pollInFlight = null;
4966
+ eventBuffer.push(...polledEvents.slice(0, Math.max(0, remaining)));
4967
+ scheduleFlush();
4853
4968
  }
4854
- })();
4855
- await pollInFlight;
4856
- }
4857
- await pollOnce();
4858
- if (!disposed) {
4859
- pollTimer = setInterval(() => {
4860
- pollOnce().catch((err) => {
4861
- onError(err instanceof Error ? err : new Error(String(err)));
4862
- });
4863
- }, pollingInterval);
4864
- }
4969
+ }
4970
+ );
4865
4971
  return {
4866
4972
  async unsubscribe() {
4867
4973
  disposed = true;
4868
- if (pollTimer) {
4869
- clearInterval(pollTimer);
4870
- pollTimer = null;
4871
- }
4872
4974
  if (debounceTimer) {
4873
4975
  clearTimeout(debounceTimer);
4874
4976
  debounceTimer = null;
4875
4977
  }
4876
- if (pollInFlight) {
4877
- try {
4878
- await pollInFlight;
4879
- } catch {
4880
- }
4881
- }
4978
+ await scanSubscription.unsubscribe();
4882
4979
  eventBuffer = [];
4883
- if (shouldCleanupSnapshot) {
4884
- try {
4885
- await unlink(effectiveSnapshotPath);
4886
- } catch {
4887
- }
4888
- }
4889
4980
  }
4890
4981
  };
4891
4982
  }
@@ -5001,7 +5092,7 @@ function describeInstallConnectivity(output) {
5001
5092
  // ../tempo-sdk/package.json
5002
5093
  var package_default = {
5003
5094
  name: "tempo-sdk",
5004
- version: "0.0.51",
5095
+ version: "0.0.52",
5005
5096
  type: "module",
5006
5097
  description: "Tempo SDK \u2014 Vite, Next.js, and Expo plugins for JSX annotation and shared page/storyboard types",
5007
5098
  repository: {
@@ -8329,7 +8420,19 @@ function resolveManagedWatchBackend(platform = process.platform, override = proc
8329
8420
  }
8330
8421
  var WATCH_BACKEND = resolveManagedWatchBackend();
8331
8422
  var MANAGED_WATCH_OPTIONS = {
8332
- ignore: ["node_modules/**", ".git/**", "dist/**", "build/**", ".next/**"],
8423
+ diagnosticKind: "devserver-managed",
8424
+ ignore: [
8425
+ "node_modules/**",
8426
+ "**/node_modules/**",
8427
+ ".git/**",
8428
+ "**/.git/**",
8429
+ "dist/**",
8430
+ "**/dist/**",
8431
+ "build/**",
8432
+ "**/build/**",
8433
+ ".next/**",
8434
+ "**/.next/**"
8435
+ ],
8333
8436
  debounceMs: 50,
8334
8437
  coalesce: true,
8335
8438
  autoRecover: true,
@@ -9050,6 +9153,7 @@ var TempoDevServer = class _TempoDevServer {
9050
9153
  // @parcel/watcher with recursive watching, batching, coalescing, and
9051
9154
  // auto-recovery, so this path does not need a periodic drift-polling backstop.
9052
9155
  this.managedFileWatchers = [];
9156
+ this.managedWatchVersion = 0;
9053
9157
  this.managedFileWatcherStopPromise = null;
9054
9158
  this.repairDebounceTimer = null;
9055
9159
  // Backoff for self-enqueued drift-correction passes that keep finding the
@@ -10555,13 +10659,15 @@ var TempoDevServer = class _TempoDevServer {
10555
10659
  // add/delete drift.
10556
10660
  async startManagedFileWatchers() {
10557
10661
  if (this.disposed) return;
10558
- await this.stopManagedFileWatchers();
10559
- if (this.disposed) return;
10662
+ const stopping = this.stopManagedFileWatchers();
10663
+ const version = this.managedWatchVersion;
10664
+ await stopping;
10665
+ if (this.disposed || version !== this.managedWatchVersion) return;
10560
10666
  try {
10561
10667
  const subscription = await watch(
10562
10668
  this.projectRoot,
10563
10669
  (events) => {
10564
- if (this.disposed) return;
10670
+ if (this.disposed || version !== this.managedWatchVersion) return;
10565
10671
  if (!events.some((event) => this.isManagedWatcherEvent(event))) {
10566
10672
  return;
10567
10673
  }
@@ -10572,9 +10678,16 @@ var TempoDevServer = class _TempoDevServer {
10572
10678
  // Transport interruption: the coverage gap may have missed a
10573
10679
  // managed-file change. repair() re-derives everything from disk,
10574
10680
  // so one scheduled repair reconciles any drift fully.
10575
- onInterruption: () => this.scheduleManagedRepair()
10681
+ onInterruption: () => {
10682
+ if (!this.disposed && version === this.managedWatchVersion)
10683
+ this.scheduleManagedRepair();
10684
+ }
10576
10685
  }
10577
10686
  );
10687
+ if (this.disposed || version !== this.managedWatchVersion) {
10688
+ await subscription.unsubscribe();
10689
+ return;
10690
+ }
10578
10691
  this.managedFileWatchers.push(subscription);
10579
10692
  } catch (error) {
10580
10693
  devLog("managed-file-watcher:start_failed", {
@@ -10584,6 +10697,7 @@ var TempoDevServer = class _TempoDevServer {
10584
10697
  }
10585
10698
  }
10586
10699
  async stopManagedFileWatchers() {
10700
+ ++this.managedWatchVersion;
10587
10701
  if (this.managedFileWatcherStopPromise) {
10588
10702
  await this.managedFileWatcherStopPromise;
10589
10703
  return;
@@ -13740,7 +13854,7 @@ function buildBaselineCaptureArgs(input) {
13740
13854
  }
13741
13855
  async function runBaselineCaptureInWorktree(options) {
13742
13856
  const tempParent = await mkdtemp2(
13743
- path18.join(process.env.RUNNER_TEMP || tmpdir2(), "tempo-vrt-baseline-")
13857
+ path18.join(process.env.RUNNER_TEMP || tmpdir(), "tempo-vrt-baseline-")
13744
13858
  );
13745
13859
  const worktreeRoot = path18.join(tempParent, "repo");
13746
13860
  try {
@@ -14244,4 +14358,4 @@ export {
14244
14358
  buildBaselineCaptureArgs,
14245
14359
  main
14246
14360
  };
14247
- //# sourceMappingURL=chunk-LFAVQ3IP.js.map
14361
+ //# sourceMappingURL=chunk-HUMMTEGB.js.map