@wenathlan/extension 1.1.39 → 1.1.40

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.
@@ -1,5 +1,5 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Devthink review</title><link rel="stylesheet" href="style.css"></head>
4
- <body><main class="wide"><header><p class="eyebrow">REVIEW GATE</p><h1>Plan before action</h1><p>Every browser operation remains blocked until the user reviews and approves it here.</p></header><label for="objective">Objective</label><textarea id="objective" rows="4" placeholder="Describe a browser task to turn into a reviewable plan."></textarea><div class="actions"><button id="localplan">Create local observation plan</button><button id="remoteplan" class="secondary">Ask configured endpoint</button><button id="diagnostic" class="secondary">Capture local diagnostics</button></div><p id="status" role="status">Loading session state.</p><p id="capabilitiestext" role="status" class="muted">Optional capabilities unknown.</p><section><h2>Current plan</h2><progress id="planprogress" max="1" value="0"></progress><div id="plan" class="panel"></div></section><section><h2>Clickable map</h2><ol id="map" class="audit maplist"></ol></section><section><h2>Navigation trail</h2><ol id="trail" class="audit"></ol></section><section><h2>Navigation state</h2><div id="navigation" class="panel"></div></section><section><h2>Tabs and windows</h2><div id="tabswindows" class="panel"></div></section><section><h2>Forms and data</h2><div id="forms" class="panel"></div></section><section><h2>Files and downloads</h2><div id="files" class="panel"></div></section><section><h2>Datasets</h2><div id="datasets" class="panel"></div></section><section><h2>Consent banners</h2><div id="banners" class="panel"></div></section><section><h2>Accessibility tree</h2><div id="a11y" class="panel"></div></section><section><h2>Reader view</h2><div id="reader" class="panel"></div></section><section><h2>Detected shapes</h2><ol id="detections" class="audit maplist"></ol></section><section><h2>Watch stream</h2><ol id="stream" class="audit"></ol></section><section><h2>Snapshot diffs</h2><div id="diffs" class="panel"></div></section><section><h2>Derived selectors</h2><ol id="selectors" class="audit maplist"></ol></section><section><h2>Structured diagnostics</h2><ul id="diagnostics" class="audit"></ul></section><section><h2>Local audit</h2><ol id="audit" class="audit"></ol></section></main><script type="module" src="sidepanel.js"></script></body>
4
+ <body><main class="wide"><header><p class="eyebrow">REVIEW GATE</p><h1>Plan before action</h1><p>Every browser operation remains blocked until the user reviews and approves it here.</p></header><label for="objective">Objective</label><textarea id="objective" rows="4" placeholder="Describe a browser task to turn into a reviewable plan."></textarea><div class="actions"><button id="localplan">Create local observation plan</button><button id="remoteplan" class="secondary">Ask configured endpoint</button><button id="diagnostic" class="secondary">Capture local diagnostics</button></div><p id="status" role="status">Loading session state.</p><p id="capabilitiestext" role="status" class="muted">Optional capabilities unknown.</p><section><h2>Current plan</h2><progress id="planprogress" max="1" value="0"></progress><div id="plan" class="panel"></div></section><section><h2>Clickable map</h2><ol id="map" class="audit maplist"></ol></section><section><h2>Navigation trail</h2><ol id="trail" class="audit"></ol></section><section><h2>Navigation state</h2><div id="navigation" class="panel"></div></section><section><h2>Tabs and windows</h2><div id="tabswindows" class="panel"></div></section><section><h2>Forms and data</h2><div id="forms" class="panel"></div></section><section><h2>Files and downloads</h2><div id="files" class="panel"></div></section><section><h2>Capture gallery</h2><div id="captures" class="panel"></div></section><section><h2>Datasets</h2><div id="datasets" class="panel"></div></section><section><h2>Consent banners</h2><div id="banners" class="panel"></div></section><section><h2>Accessibility tree</h2><div id="a11y" class="panel"></div></section><section><h2>Reader view</h2><div id="reader" class="panel"></div></section><section><h2>Detected shapes</h2><ol id="detections" class="audit maplist"></ol></section><section><h2>Watch stream</h2><ol id="stream" class="audit"></ol></section><section><h2>Snapshot diffs</h2><div id="diffs" class="panel"></div></section><section><h2>Derived selectors</h2><ol id="selectors" class="audit maplist"></ol></section><section><h2>Structured diagnostics</h2><ul id="diagnostics" class="audit"></ul></section><section><h2>Local audit</h2><ol id="audit" class="audit"></ol></section></main><script type="module" src="sidepanel.js"></script></body>
5
5
  </html>
@@ -1,7 +1,7 @@
1
1
  // policy.ts
2
2
  var sensitiveactions = /* @__PURE__ */ new Set(["click", "type", "navigate", "select", "presskey", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "reload", "back", "forward", "writestorage", "setattribute", "removeattribute", "evaluate", "tabcreate", "tabactivate", "tabclose", "tabreload", "windowcreate", "windowclose", "windowresize", "downloadfile", "clickpoint", "shiftclick", "dismissdialog", "enterframe", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "openlink", "openprivate", "reloadcache", "stopnav", "followlink", "spanav", "rewritequery", "setfragment", "navlist", "navprofile", "handleauth", "printpdf", "prefetch", "preconnect", "deeplink", "reopentab", "pausenav", "navrate", "openclipboard", "batchopen", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "restorelayout", "reopenrun", "badgetab", "fillform", "filllabel", "fillplaceholder", "submitform", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcard", "fillcode", "consentpassword", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk", "paginateextract", "resumeextract", "batchdownload", "pausedownload", "resumedownload", "interceptmime", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "cleanupartifacts"]);
3
3
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction"]);
4
- var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures"]);
4
+ var readactions = /* @__PURE__ */ new Set(["observe", "inspect", "extract", "wait", "waitfor", "waittext", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "readlinks", "readimages", "readmeta", "readforms", "readstorage", "highlight", "tablist", "windowlist", "tabsnapshot", "mapclicks", "verifyvisible", "verifyenabled", "resolvexpath", "a11ytree", "readvisible", "readertree", "detectlists", "detecttables", "readjson", "watchmutate", "waitquiet", "watchbanner", "detectinfinitescroll", "detectvirtual", "detectlazy", "readscrollpos", "readlang", "readoutline", "countpages", "listshadow", "listframes", "classifypage", "fingerprintsection", "diffsnapshots", "readselection", "watchfocus", "detectsticky", "detectscrolllock", "readopengraph", "detectlanguage", "deriveselector", "waitload", "waiturl", "spawait", "detecthttp", "readredirects", "readfinalurl", "trailaudit", "navintent", "checksafe", "querytabs", "watchtab", "findclones", "searchtabs", "listaudio", "snapshotsession", "savelayout", "attachmeta", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "readerrors", "skiphoneypot", "detectlogin", "detecttemplate", "handoffcaptcha", "scrapetable", "importcsv", "looprows", "transformvalues", "deduperows", "mergepages", "stamplerows", "previewgrid", "logprovenance", "verifydownload", "exportnetlog", "namecaptures", "shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"]);
5
5
  var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
6
6
 
7
7
  // extension/tabscommand.ts
@@ -63,6 +63,7 @@ var tabswindowsroot = document.querySelector("#tabswindows");
63
63
  var formsroot = document.querySelector("#forms");
64
64
  var datasetsroot = document.querySelector("#datasets");
65
65
  var filesroot = document.querySelector("#files");
66
+ var capturesroot = document.querySelector("#captures");
66
67
  var statusnode = document.querySelector("#status");
67
68
  var progressnode = document.querySelector("#planprogress");
68
69
  var capabilitiestext = document.querySelector("#capabilitiestext");
@@ -1301,6 +1302,141 @@ function renderfiles(context) {
1301
1302
  filesroot.append(hookcard);
1302
1303
  }
1303
1304
  }
1305
+ async function capturebytes(id) {
1306
+ try {
1307
+ const record = await request({ kind: "capturebytes", id });
1308
+ return record.bytes;
1309
+ } catch {
1310
+ return void 0;
1311
+ }
1312
+ }
1313
+ function opencapture(record) {
1314
+ if (!capturesroot) return;
1315
+ const viewer = document.createElement("div");
1316
+ viewer.className = "panel captureviewer";
1317
+ const head = document.createElement("p");
1318
+ head.textContent = `${record.kind} \xB7 ${record.format} \xB7 ${record.width}\xD7${record.height} px \xB7 step ${record.stepid}${record.annotated ? " \xB7 annotated evidence" : ""}${record.name !== void 0 ? ` \xB7 ${record.name}` : ""}`;
1319
+ viewer.append(head);
1320
+ const image = document.createElement("img");
1321
+ image.alt = `Capture ${record.id} of kind ${record.kind}`;
1322
+ image.src = "";
1323
+ void capturebytes(record.id).then((bytes) => {
1324
+ if (bytes) image.src = bytes;
1325
+ else viewer.append(Object.assign(document.createElement("p"), { textContent: "The capture bytes expired from the retention window; the metadata stays for the audit trail." }));
1326
+ });
1327
+ viewer.append(image);
1328
+ const actions = document.createElement("div");
1329
+ actions.className = "actions";
1330
+ actions.append(button("Download", () => request({ kind: "downloadcapture", id: record.id }).then(() => status(`Downloaded capture ${record.id} through the reviewed download flow.`))));
1331
+ actions.append(button("Copy to clipboard", () => request({ kind: "copycapture", id: record.id }).then(() => status(`Copied capture ${record.id} to the clipboard.`))));
1332
+ actions.append(button("Close", async () => viewer.remove()));
1333
+ viewer.append(actions);
1334
+ capturesroot.append(viewer);
1335
+ }
1336
+ function rendercaptures(context) {
1337
+ if (!capturesroot) return;
1338
+ capturesroot.replaceChildren();
1339
+ const active = context.session && !context.session.stoppedat && context.session.expiresat > Date.now();
1340
+ const policy = context.capturepolicy ?? "manual";
1341
+ const policyrow = document.createElement("div");
1342
+ policyrow.className = "actions";
1343
+ const policylabel = document.createElement("p");
1344
+ policylabel.textContent = `capture policy: ${policy}${policy === "beforeafter" ? " \u2014 state pairs wrap every page moving action" : ""}`;
1345
+ policyrow.append(policylabel);
1346
+ for (const mode of ["off", "manual", "annotated", "beforeafter"]) {
1347
+ policyrow.append(button(mode, async () => {
1348
+ await request({ kind: "setcapturepolicy", mode });
1349
+ status(`Capture policy set to ${mode}.`);
1350
+ await refresh();
1351
+ }, !active || mode === policy));
1352
+ }
1353
+ capturesroot.append(policyrow);
1354
+ for (const progress of context.stitchprogress ?? []) {
1355
+ const bar = document.createElement("progress");
1356
+ bar.max = Math.max(1, progress.total);
1357
+ bar.value = progress.done;
1358
+ const label = document.createElement("p");
1359
+ label.textContent = `stitching full page capture of step ${progress.stepid}: tile ${progress.done} of ${progress.total}`;
1360
+ capturesroot.append(label, bar);
1361
+ }
1362
+ const captures = context.captures ?? [];
1363
+ if (captures.length === 0 && (context.capturepairs ?? []).length === 0) {
1364
+ capturesroot.append(Object.assign(document.createElement("p"), { textContent: "No captures stored yet; run a shotview, shotfullpage, shotelement, shotregion or contactsheet step." }));
1365
+ return;
1366
+ }
1367
+ const runs = [...new Set(captures.map((record) => record.runid))];
1368
+ for (const run of runs) {
1369
+ const runcaptures = captures.filter((record) => record.runid === run);
1370
+ const card = document.createElement("div");
1371
+ card.className = "panel";
1372
+ const head = document.createElement("p");
1373
+ head.textContent = `run ${run}: ${runcaptures.length} capture${runcaptures.length === 1 ? "" : "s"}`;
1374
+ card.append(head);
1375
+ const grid = document.createElement("div");
1376
+ grid.className = "capturegrid";
1377
+ for (const record of runcaptures) {
1378
+ const cell = document.createElement("button");
1379
+ cell.type = "button";
1380
+ cell.className = record.annotated ? "capturecard annotated" : "capturecard";
1381
+ const label = document.createElement("span");
1382
+ label.textContent = `${record.kind} \xB7 ${record.format} \xB7 ${record.width}\xD7${record.height}${record.annotated ? " \xB7 annotated" : ""}${record.bytesexpired ? " \xB7 bytes expired" : ""}`;
1383
+ cell.append(label);
1384
+ const image = document.createElement("img");
1385
+ image.alt = `Capture ${record.id} of kind ${record.kind}`;
1386
+ if (!record.bytesexpired) void capturebytes(record.id).then((bytes) => {
1387
+ if (bytes) image.src = bytes;
1388
+ });
1389
+ cell.append(image);
1390
+ cell.addEventListener("click", () => opencapture(record));
1391
+ grid.append(cell);
1392
+ if (record.kind === "contactsheet") {
1393
+ const cells = (context.outcomes ?? []).find((outcome) => outcome.stepid === record.stepid && outcome.details?.cells !== void 0)?.details?.cells;
1394
+ for (const sheetcell of cells ?? []) {
1395
+ const cellbutton = document.createElement("button");
1396
+ cellbutton.type = "button";
1397
+ cellbutton.className = "secondary";
1398
+ cellbutton.textContent = sheetcell.caption || sheetcell.selector;
1399
+ cellbutton.addEventListener("click", () => opencapture(record));
1400
+ grid.append(cellbutton);
1401
+ }
1402
+ }
1403
+ }
1404
+ card.append(grid);
1405
+ capturesroot.append(card);
1406
+ }
1407
+ for (const pair of context.capturepairs ?? []) {
1408
+ const card = document.createElement("div");
1409
+ card.className = "panel pairview";
1410
+ const head = document.createElement("p");
1411
+ head.textContent = `state pair around the ${pair.actionkind} action${pair.target !== void 0 ? ` on ${pair.target}` : ""}${pair.domsnapshotid !== void 0 ? ` \xB7 dom snapshot ${pair.domsnapshotid}` : ""}`;
1412
+ card.append(head);
1413
+ const row = document.createElement("div");
1414
+ row.className = "pairrow";
1415
+ const before = document.createElement("img");
1416
+ before.alt = `Before shot ${pair.beforeid}`;
1417
+ const after = document.createElement("img");
1418
+ after.alt = `After shot ${pair.afterid}`;
1419
+ void capturebytes(pair.beforeid).then((bytes) => {
1420
+ if (bytes) before.src = bytes;
1421
+ });
1422
+ void capturebytes(pair.afterid).then((bytes) => {
1423
+ if (bytes) after.src = bytes;
1424
+ });
1425
+ row.append(before, after);
1426
+ const divider = document.createElement("input");
1427
+ divider.type = "range";
1428
+ divider.min = "0";
1429
+ divider.max = "100";
1430
+ divider.value = "50";
1431
+ divider.setAttribute("aria-label", "Before and after divider");
1432
+ divider.addEventListener("input", () => {
1433
+ before.style.width = `${100 - Number(divider.value)}%`;
1434
+ after.style.width = `${Number(divider.value)}%`;
1435
+ });
1436
+ card.append(row, divider);
1437
+ capturesroot.append(card);
1438
+ }
1439
+ }
1304
1440
  function rendercapabilities(report) {
1305
1441
  if (!capabilitiestext) return;
1306
1442
  if (!report) {
@@ -1350,6 +1486,7 @@ async function refresh() {
1350
1486
  renderforms(context);
1351
1487
  renderdatasets(context);
1352
1488
  renderfiles(context);
1489
+ rendercaptures(context);
1353
1490
  renderaudit(context.audit);
1354
1491
  rendercapabilities(context.capabilities);
1355
1492
  if (context.session?.pausedat) status("Session paused. Reviewed actions are blocked until resume.");