@tempo-ai/visual-review 0.0.113-staging.2 → 0.0.113-staging.4
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 +1 -1
- package/dist/{chunk-AX52T3IT.js → chunk-W3EZWPOB.js} +108 -15
- package/dist/chunk-W3EZWPOB.js.map +1 -0
- package/dist/{cli-32JWCJ2S.js → cli-OT7EUYFD.js} +2 -2
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-AX52T3IT.js.map +0 -1
- /package/dist/{cli-32JWCJ2S.js.map → cli-OT7EUYFD.js.map} +0 -0
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-
|
|
9
|
+
return await (await import("./cli-OT7EUYFD.js")).main(commandArgs);
|
|
10
10
|
case "claim":
|
|
11
11
|
return await (await import("./claim-J654JAS6.js")).main(commandArgs);
|
|
12
12
|
case "report":
|
|
@@ -134,6 +134,7 @@ var SETTLE_STEPS = [
|
|
|
134
134
|
"content-quiet",
|
|
135
135
|
"paint"
|
|
136
136
|
];
|
|
137
|
+
var VIDEO_FRAME_WAIT_CAP_MS = 2e3;
|
|
137
138
|
var DEFAULT_SETTLE_QUIET_MS = 300;
|
|
138
139
|
var DEFAULT_SETTLE_STEP_TIMEOUT_MS = 15e3;
|
|
139
140
|
var DEFAULT_SETTLE_POLL_MS = 50;
|
|
@@ -209,22 +210,48 @@ function buildSettleWaitScript(options) {
|
|
|
209
210
|
|
|
210
211
|
var quietKey = null;
|
|
211
212
|
var quietSince = 0;
|
|
213
|
+
// When a rendered video was first seen without a decoded frame, and how
|
|
214
|
+
// long that may hold the quiet window before we give up on it.
|
|
215
|
+
var videoWaitStartedAt = null;
|
|
216
|
+
var videoWaitCapMs = ${VIDEO_FRAME_WAIT_CAP_MS};
|
|
212
217
|
// Images that take part in the capture: laid out and not hidden. A
|
|
213
218
|
// hidden responsive variant never starts native lazy loading and must
|
|
214
219
|
// not hold the window; a rendered lazy image never starts either,
|
|
215
220
|
// because a capture does not scroll, so it is asked for eagerly.
|
|
216
|
-
function
|
|
217
|
-
var all = Array.prototype.slice.call(target.querySelectorAll(
|
|
221
|
+
function renderedMatches(target, tag) {
|
|
222
|
+
var all = Array.prototype.slice.call(target.querySelectorAll(tag));
|
|
218
223
|
var rendered = [];
|
|
219
224
|
for (var i = 0; i < all.length; i++) {
|
|
220
|
-
var
|
|
221
|
-
if (
|
|
222
|
-
var visibility = getComputedStyle(
|
|
225
|
+
var el = all[i];
|
|
226
|
+
if (el.getClientRects().length === 0) continue;
|
|
227
|
+
var visibility = getComputedStyle(el).visibility;
|
|
223
228
|
if (visibility === 'hidden' || visibility === 'collapse') continue;
|
|
224
|
-
rendered.push(
|
|
229
|
+
rendered.push(el);
|
|
225
230
|
}
|
|
226
231
|
return rendered;
|
|
227
232
|
}
|
|
233
|
+
function renderedImages(target) {
|
|
234
|
+
return renderedMatches(target, 'img');
|
|
235
|
+
}
|
|
236
|
+
// A video paints its current frame only once that frame is DECODED.
|
|
237
|
+
// HAVE_CURRENT_DATA (2) is exactly that bar.
|
|
238
|
+
//
|
|
239
|
+
// Everything else here is about FAILING OPEN. The baseline lane runs
|
|
240
|
+
// this step strict, so a video that can never reach that bar would turn
|
|
241
|
+
// a capture that used to succeed into a settle.content-quiet timeout \u2014
|
|
242
|
+
// for every storyboard in the repo, not just ones we had in mind. So a
|
|
243
|
+
// video only holds the window while it is plausibly ON ITS WAY to a
|
|
244
|
+
// frame: an errored element, one with no source at all, and one the page
|
|
245
|
+
// explicitly opted out of loading (preload="none", whose poster-or-
|
|
246
|
+
// nothing paint is already deterministic) are all treated as finished.
|
|
247
|
+
function videoFrameReady(video) {
|
|
248
|
+
if (video.error) return true;
|
|
249
|
+
if (video.preload === 'none') return true;
|
|
250
|
+
var networkState = video.networkState;
|
|
251
|
+
if (networkState === 0 /* NETWORK_EMPTY */) return true;
|
|
252
|
+
if (networkState === 3 /* NETWORK_NO_SOURCE */) return true;
|
|
253
|
+
return video.readyState >= 2 /* HAVE_CURRENT_DATA */;
|
|
254
|
+
}
|
|
228
255
|
function contentQuiet() {
|
|
229
256
|
var target = document.querySelector(selector);
|
|
230
257
|
if (!target) return false;
|
|
@@ -240,6 +267,23 @@ function buildSettleWaitScript(options) {
|
|
|
240
267
|
return false;
|
|
241
268
|
}
|
|
242
269
|
}
|
|
270
|
+
// Second line of defence behind videoFrameReady's fail-open rules: a
|
|
271
|
+
// video that is legitimately loading can still stall forever (a dev
|
|
272
|
+
// server that never answers, a huge asset). Waiting is an OPTIMISATION
|
|
273
|
+
// for baseline stability, never a reason to fail a capture, so the
|
|
274
|
+
// whole video wait is bounded \u2014 past the cap we capture whatever is
|
|
275
|
+
// on screen, exactly as we did before videos were considered at all.
|
|
276
|
+
var videos = renderedMatches(target, 'video');
|
|
277
|
+
for (var w = 0; w < videos.length; w++) {
|
|
278
|
+
if (!videoFrameReady(videos[w])) {
|
|
279
|
+
if (videoWaitStartedAt === null) videoWaitStartedAt = now();
|
|
280
|
+
if (now() - videoWaitStartedAt < videoWaitCapMs) {
|
|
281
|
+
quietKey = null;
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
243
287
|
var rect = target.getBoundingClientRect();
|
|
244
288
|
var text = target.innerText || '';
|
|
245
289
|
var key = [
|
|
@@ -4202,6 +4246,16 @@ import os from "os";
|
|
|
4202
4246
|
import path6 from "path";
|
|
4203
4247
|
var PRE_BOOT_CLOCK_SLACK_MS = 5 * 60 * 1e3;
|
|
4204
4248
|
|
|
4249
|
+
// ../tempo-devserver/install-environment-fallback.ts
|
|
4250
|
+
function missingInstallEnvironment(error) {
|
|
4251
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4252
|
+
return /(?:^|[\s/"'])(?:docker|pnpm|yarn|bun)(?:["'])?: (?:command )?not found\b/im.test(
|
|
4253
|
+
message
|
|
4254
|
+
) || /['"](?:docker|pnpm|yarn|bun)['"] is not recognized as an internal or external command/i.test(
|
|
4255
|
+
message
|
|
4256
|
+
) || /cannot connect to the docker daemon/i.test(message) || /is the docker daemon running\?/i.test(message);
|
|
4257
|
+
}
|
|
4258
|
+
|
|
4205
4259
|
// ../tempo-devserver/tempo-devserver.ts
|
|
4206
4260
|
import { spawn as spawn5 } from "child_process";
|
|
4207
4261
|
import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
|
|
@@ -4825,7 +4879,7 @@ async function parcelEventToFileEvent(event, rootInfo) {
|
|
|
4825
4879
|
// ../tempo-sdk/package.json
|
|
4826
4880
|
var package_default = {
|
|
4827
4881
|
name: "tempo-sdk",
|
|
4828
|
-
version: "0.0.
|
|
4882
|
+
version: "0.0.48",
|
|
4829
4883
|
type: "module",
|
|
4830
4884
|
description: "Tempo SDK \u2014 Vite, Next.js, and Expo plugins for JSX annotation and shared page/storyboard types",
|
|
4831
4885
|
repository: {
|
|
@@ -4906,7 +4960,7 @@ var package_default = {
|
|
|
4906
4960
|
demo: "TEMPO=true pnpm --filter @tempo-modules/vite-annotate-plugin-demo dev",
|
|
4907
4961
|
"demo:nextjs": "TEMPO=true pnpm --filter @tempo-modules/tempo-sdk-nextjs-demo dev",
|
|
4908
4962
|
test: "vitest run",
|
|
4909
|
-
"test:browser": "vitest run canvas-capture-determinism-browser.test.ts canvas-host-vite-e2e.test.ts canvas-host-packed-sdk-e2e.test.ts error-tracking-e2e.test.ts",
|
|
4963
|
+
"test:browser": "vitest run 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",
|
|
4910
4964
|
"test:watch": "vitest",
|
|
4911
4965
|
"test:nextjs:unit": "vitest run nextjs-loader.test.ts nextjs-wrapper.test.ts nextjs-fixtures.test.ts nextjs-published.test.ts",
|
|
4912
4966
|
"test:nextjs:integration": "vitest run nextjs-e2e-correctness.test.ts",
|
|
@@ -7301,6 +7355,7 @@ async function walkPagesDir(directory, collector) {
|
|
|
7301
7355
|
var CanvasRegistry = class {
|
|
7302
7356
|
constructor(projectRoot, tempoRoot, _pagesDir, options) {
|
|
7303
7357
|
this.pendingRequestedCanvasPaths = null;
|
|
7358
|
+
this.requestedThisSession = /* @__PURE__ */ new Set();
|
|
7304
7359
|
this.requestedCanvasesQueue = Promise.resolve();
|
|
7305
7360
|
this.projectRoot = projectRoot;
|
|
7306
7361
|
this.tempoRoot = tempoRoot;
|
|
@@ -7338,9 +7393,31 @@ var CanvasRegistry = class {
|
|
|
7338
7393
|
async resetRequestedCanvases() {
|
|
7339
7394
|
await this.runRequestedCanvasesExclusive(async () => {
|
|
7340
7395
|
this.pendingRequestedCanvasPaths = null;
|
|
7396
|
+
this.requestedThisSession.clear();
|
|
7341
7397
|
await rm3(this.requestedCanvasesPath, { force: true });
|
|
7342
7398
|
});
|
|
7343
7399
|
}
|
|
7400
|
+
/**
|
|
7401
|
+
* Drop demand registrations inherited from an older host session without
|
|
7402
|
+
* erasing canvases already requested through this registry instance.
|
|
7403
|
+
*
|
|
7404
|
+
* Canvas admission may run while first-time initialization is queued. The
|
|
7405
|
+
* registry queue makes both orderings safe: a reset that wins clears the old
|
|
7406
|
+
* file before admission writes it, while a reset that follows admission
|
|
7407
|
+
* observes the current-session request and preserves the file.
|
|
7408
|
+
*/
|
|
7409
|
+
async resetStaleRequestedCanvases() {
|
|
7410
|
+
await this.runRequestedCanvasesExclusive(async () => {
|
|
7411
|
+
const requestedPaths = [...this.requestedThisSession];
|
|
7412
|
+
this.pendingRequestedCanvasPaths = requestedPaths;
|
|
7413
|
+
if (requestedPaths.length === 0) {
|
|
7414
|
+
await rm3(this.requestedCanvasesPath, { force: true });
|
|
7415
|
+
} else {
|
|
7416
|
+
await this.writeRequestedCanvasPaths(requestedPaths);
|
|
7417
|
+
}
|
|
7418
|
+
this.pendingRequestedCanvasPaths = null;
|
|
7419
|
+
});
|
|
7420
|
+
}
|
|
7344
7421
|
requestedPathToAbsolutePath(relativePath) {
|
|
7345
7422
|
if (typeof relativePath !== "string" || relativePath.length === 0) {
|
|
7346
7423
|
return null;
|
|
@@ -7465,6 +7542,7 @@ var CanvasRegistry = class {
|
|
|
7465
7542
|
}
|
|
7466
7543
|
return this.runRequestedCanvasesExclusive(async () => {
|
|
7467
7544
|
const requestedPath = this.toRequestedPath(absolutePath);
|
|
7545
|
+
this.requestedThisSession.add(requestedPath);
|
|
7468
7546
|
const pruned = await this.pruneDeletedRequestedPaths(
|
|
7469
7547
|
await this.readRequestedCanvasPaths()
|
|
7470
7548
|
);
|
|
@@ -9523,9 +9601,24 @@ var TempoDevServer = class _TempoDevServer {
|
|
|
9523
9601
|
}
|
|
9524
9602
|
this.state.dependenciesInstalled = false;
|
|
9525
9603
|
await this.persistStatus();
|
|
9526
|
-
|
|
9604
|
+
try {
|
|
9605
|
+
for (const step of steps) {
|
|
9606
|
+
throwIfLaunchAborted(signal);
|
|
9607
|
+
await runInstallStep(step, signal);
|
|
9608
|
+
}
|
|
9609
|
+
} catch (error) {
|
|
9527
9610
|
throwIfLaunchAborted(signal);
|
|
9528
|
-
|
|
9611
|
+
if (!steps.some((step) => step.label === "custom tempo install") || !missingInstallEnvironment(error))
|
|
9612
|
+
throw error;
|
|
9613
|
+
const localSteps = await this.buildInstallSteps(false, false);
|
|
9614
|
+
if (!localSteps.length) throw error;
|
|
9615
|
+
console.warn(
|
|
9616
|
+
"[tempo-devserver] The configured installer needs unavailable local tooling; trying a local dependency install for this launch."
|
|
9617
|
+
);
|
|
9618
|
+
for (const step of localSteps) {
|
|
9619
|
+
throwIfLaunchAborted(signal);
|
|
9620
|
+
await runInstallStep(step, signal);
|
|
9621
|
+
}
|
|
9529
9622
|
}
|
|
9530
9623
|
};
|
|
9531
9624
|
while (_TempoDevServer.installBarriers.has(this.projectRoot)) {
|
|
@@ -9555,9 +9648,9 @@ var TempoDevServer = class _TempoDevServer {
|
|
|
9555
9648
|
throw error;
|
|
9556
9649
|
}
|
|
9557
9650
|
}
|
|
9558
|
-
async buildInstallSteps(forceInstall) {
|
|
9651
|
+
async buildInstallSteps(forceInstall, useConfiguredScript = true) {
|
|
9559
9652
|
const configuredInstall = this.config.scripts.install.trim();
|
|
9560
|
-
if (!looksLikeGeneratedInstallScript(configuredInstall)) {
|
|
9653
|
+
if (useConfiguredScript && !looksLikeGeneratedInstallScript(configuredInstall)) {
|
|
9561
9654
|
if (!forceInstall && await this.projectRootInstallReady() && await installCompletedForCurrentDeps(this.tempoRoot) && await this.tempoInstallReady()) {
|
|
9562
9655
|
devLog("supervisor:custom_install_skipped_premat", {
|
|
9563
9656
|
projectRoot: this.projectRoot,
|
|
@@ -9617,7 +9710,7 @@ var TempoDevServer = class _TempoDevServer {
|
|
|
9617
9710
|
markerRoots: [this.tempoRoot]
|
|
9618
9711
|
});
|
|
9619
9712
|
}
|
|
9620
|
-
if (!rootManager && !tempoManager) {
|
|
9713
|
+
if (useConfiguredScript && !rootManager && !tempoManager) {
|
|
9621
9714
|
steps.push({
|
|
9622
9715
|
cwd: this.commandCwd,
|
|
9623
9716
|
command: configuredInstall,
|
|
@@ -10211,7 +10304,7 @@ var TempoDevServer = class _TempoDevServer {
|
|
|
10211
10304
|
const firstInitialize = !this.state.initialized;
|
|
10212
10305
|
const hostAlive = this.activeHostHasLivenessAuthority();
|
|
10213
10306
|
if (firstInitialize && !hostAlive) {
|
|
10214
|
-
await this.registry.
|
|
10307
|
+
await this.registry.resetStaleRequestedCanvases();
|
|
10215
10308
|
}
|
|
10216
10309
|
const reconcileResult = await this.enqueueReconcile(
|
|
10217
10310
|
"initialize",
|
|
@@ -13974,4 +14067,4 @@ export {
|
|
|
13974
14067
|
buildBaselineCaptureArgs,
|
|
13975
14068
|
main
|
|
13976
14069
|
};
|
|
13977
|
-
//# sourceMappingURL=chunk-
|
|
14070
|
+
//# sourceMappingURL=chunk-W3EZWPOB.js.map
|