@wenathlan/extension 1.1.47 → 1.1.48

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/index.js CHANGED
@@ -333,6 +333,190 @@ function teardowncdpsession(input) {
333
333
  };
334
334
  }
335
335
 
336
+ // emulation.ts
337
+ var emulationkinds = ["emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "blackboxscripts"];
338
+ var browserpermissions = ["geolocation", "notifications", "camera", "microphone", "clipboard-read", "clipboard-write", "midi", "persistent-storage"];
339
+ var permissionstates = ["granted", "denied", "prompt"];
340
+ function familyofkind(kind) {
341
+ if (kind === "emulatedevice") return "device";
342
+ if (kind === "emulatenetwork") return "network";
343
+ if (kind === "emulatelocate") return "location";
344
+ if (kind === "setuseragent") return "agent";
345
+ if (kind === "overridepermission") return "permission";
346
+ if (kind === "blackboxscripts") return "blackbox";
347
+ return void 0;
348
+ }
349
+ function devicepresetof(value) {
350
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
351
+ const entry = value;
352
+ const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
353
+ const width = typeof entry.width === "number" && Number.isInteger(entry.width) && entry.width > 0 ? entry.width : void 0;
354
+ const height = typeof entry.height === "number" && Number.isInteger(entry.height) && entry.height > 0 ? entry.height : void 0;
355
+ const pixelratio = typeof entry.pixelratio === "number" && Number.isFinite(entry.pixelratio) && entry.pixelratio > 0 ? entry.pixelratio : void 0;
356
+ if (name === void 0 || width === void 0 || height === void 0 || pixelratio === void 0) return void 0;
357
+ return { name, width, height, pixelratio, mobile: entry.mobile === true };
358
+ }
359
+ function networkpresetof(value) {
360
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
361
+ const entry = value;
362
+ const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
363
+ const latency = typeof entry.latency === "number" && Number.isFinite(entry.latency) && entry.latency >= 0 ? entry.latency : void 0;
364
+ const download = typeof entry.download === "number" && Number.isFinite(entry.download) && entry.download >= 0 ? entry.download : void 0;
365
+ const upload = typeof entry.upload === "number" && Number.isFinite(entry.upload) && entry.upload >= 0 ? entry.upload : void 0;
366
+ if (name === void 0 || latency === void 0 || download === void 0 || upload === void 0) return void 0;
367
+ return { name, latency, download, upload, offline: entry.offline === true };
368
+ }
369
+ function locationpresetof(value) {
370
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
371
+ const entry = value;
372
+ const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
373
+ const latitude = typeof entry.latitude === "number" && Number.isFinite(entry.latitude) ? entry.latitude : void 0;
374
+ const longitude = typeof entry.longitude === "number" && Number.isFinite(entry.longitude) ? entry.longitude : void 0;
375
+ const accuracy = typeof entry.accuracy === "number" && Number.isFinite(entry.accuracy) && entry.accuracy >= 0 ? entry.accuracy : void 0;
376
+ if (name === void 0 || latitude === void 0 || longitude === void 0 || accuracy === void 0) return void 0;
377
+ if (!locationrangevalid(latitude, longitude)) return void 0;
378
+ return { name, latitude, longitude, accuracy };
379
+ }
380
+ function agentpresetof(value) {
381
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
382
+ const entry = value;
383
+ const name = typeof entry.name === "string" && entry.name.trim() ? entry.name.trim() : void 0;
384
+ const useragent = typeof entry.useragent === "string" ? entry.useragent : void 0;
385
+ const platform = typeof entry.platform === "string" && entry.platform.trim() ? entry.platform.trim() : void 0;
386
+ const brands = Array.isArray(entry.brands) ? entry.brands.filter((brand) => typeof brand === "string" && brand.trim().length > 0) : [];
387
+ if (name === void 0 || useragent === void 0 || platform === void 0 || brands.length === 0) return void 0;
388
+ if (!agentgrammarvalid(useragent)) return void 0;
389
+ return { name, useragent, platform, brands: [...new Set(brands)] };
390
+ }
391
+ function permissiongrantof(value) {
392
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
393
+ const entry = value;
394
+ const name = typeof entry.name === "string" && browserpermissions.includes(entry.name) ? entry.name : void 0;
395
+ const state = typeof entry.state === "string" && permissionstates.includes(entry.state) ? entry.state : void 0;
396
+ if (name === void 0 || state === void 0) return void 0;
397
+ return { name, state, runscope: entry.runscope !== false };
398
+ }
399
+ function blackboxruleof(value) {
400
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
401
+ const entry = value;
402
+ const urlpatterns = Array.isArray(entry.urlpatterns) ? entry.urlpatterns.filter((pattern) => typeof pattern === "string" && /^https:\/\//.test(pattern)) : [];
403
+ const tracescope = entry.tracescope;
404
+ if (urlpatterns.length === 0) return void 0;
405
+ if (tracescope !== "profiles" && tracescope !== "traces" && tracescope !== "both") return void 0;
406
+ return { urlpatterns: [...new Set(urlpatterns)], tracescope };
407
+ }
408
+ function revertplanof(value) {
409
+ const steps = Array.isArray(value) ? value.filter((step) => typeof step === "string" && step.trim().length > 0) : [];
410
+ return steps.length > 0 ? steps : void 0;
411
+ }
412
+ function newlayer(input) {
413
+ return { id: input.id, runid: input.runid, stepid: input.stepid, family: input.family, name: input.name, originscope: input.originscope, appliedat: input.at, ...input.prior !== void 0 ? { prior: input.prior } : {}, revertplan: [...input.revertplan] };
414
+ }
415
+ function emulationstateof(input) {
416
+ return { runid: input.runid, tabid: input.tabid, origin: input.origin, layers: [], updatedat: input.now };
417
+ }
418
+ function applylayer(state, layer, at) {
419
+ const layers = [...state.layers.filter((item) => item.id !== layer.id), layer];
420
+ return { ...state, layers, updatedat: at };
421
+ }
422
+ function revertlayer(state, layerid, at) {
423
+ const layers = state.layers.map((layer) => layer.id === layerid && layer.revertedat === void 0 ? { ...layer, revertedat: at } : layer);
424
+ return { ...state, layers, updatedat: at };
425
+ }
426
+ function revertalllayers(state, at) {
427
+ const reverted = [...state.layers].reverse().filter((layer) => layer.revertedat === void 0);
428
+ const layers = state.layers.map((layer) => layer.revertedat === void 0 ? { ...layer, revertedat: at } : layer);
429
+ return { state: { ...state, layers, updatedat: at }, reverted };
430
+ }
431
+ function activelayers(state) {
432
+ return state ? state.layers.filter((layer) => layer.revertedat === void 0) : [];
433
+ }
434
+ function layernames(state) {
435
+ return activelayers(state).map((layer) => layer.name);
436
+ }
437
+ function stackedcount(state) {
438
+ return activelayers(state).length;
439
+ }
440
+ function locationrangevalid(latitude, longitude) {
441
+ return Number.isFinite(latitude) && Number.isFinite(longitude) && latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180;
442
+ }
443
+ function agentgrammarvalid(useragent) {
444
+ const text2 = useragent.trim();
445
+ if (text2.length === 0 || text2.length > 512) return false;
446
+ if (/[\r\n]/.test(text2)) return false;
447
+ if (!/^[A-Za-z0-9][A-Za-z0-9._+\-()/:; ,]*$/.test(text2)) return false;
448
+ return /\/\d/.test(text2) || /\d+\.\d+/.test(text2);
449
+ }
450
+ function permissiongrade(name) {
451
+ return name === "geolocation" || name === "camera" || name === "microphone" || name === "notifications" ? "powerful" : "standard";
452
+ }
453
+ function blackboxmatches(urlpattern, url) {
454
+ const patternmatch = /^(https:\/\/[^/]+)(\/.*)?$/.exec(urlpattern);
455
+ const urlmatch = /^(https:\/\/[^/]+)(\/.*)?$/.exec(url);
456
+ if (!patternmatch || !urlmatch) return false;
457
+ if (patternmatch[1] !== urlmatch[1]) return false;
458
+ const patternpath = (patternmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
459
+ const urlpath = (urlmatch[2] ?? "/").split("/").filter((segment) => segment.length > 0);
460
+ const walk = (patternindex, urlindex) => {
461
+ if (patternindex >= patternpath.length) return urlindex >= urlpath.length;
462
+ const segment = patternpath[patternindex];
463
+ if (segment === void 0) return false;
464
+ if (segment === "**") return walk(patternindex + 1, urlindex) || urlindex < urlpath.length && walk(patternindex, urlindex + 1);
465
+ if (urlindex >= urlpath.length) return false;
466
+ if (segment !== "*" && segment !== urlpath[urlindex]) return false;
467
+ return walk(patternindex + 1, urlindex + 1);
468
+ };
469
+ return walk(0, 0);
470
+ }
471
+ function hideblackboxedframes(rules, frames) {
472
+ const patterns = rules.filter((rule) => rule.tracescope === "traces" || rule.tracescope === "both").flatMap((rule) => rule.urlpatterns);
473
+ if (patterns.length === 0) return frames;
474
+ return frames.filter((frame) => !patterns.some((pattern) => blackboxmatches(pattern, frame.url)));
475
+ }
476
+ function blackboxedurls(rules, urls) {
477
+ const patterns = rules.flatMap((rule) => rule.urlpatterns);
478
+ return urls.filter((url) => patterns.some((pattern) => blackboxmatches(pattern, url)));
479
+ }
480
+ function expirelayers(state, retention, now) {
481
+ if (retention === void 0) return state;
482
+ const layers = state.layers.map((layer) => {
483
+ if (layer.revertedat === void 0 || layer.prior === void 0 || layer.priorexpired === true) return layer;
484
+ if (now - layer.revertedat <= retention) return layer;
485
+ const { prior, ...metadata } = layer;
486
+ void prior;
487
+ return { ...metadata, priorexpired: true };
488
+ });
489
+ return { ...state, layers, updatedat: now };
490
+ }
491
+ function exportpresetlibrary(input) {
492
+ return { version: 1, devices: [...input.devices], networks: [...input.networks], locations: [...input.locations], agents: [...input.agents], exportedat: input.now };
493
+ }
494
+ function importpresetlibrary(value) {
495
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
496
+ const entry = value;
497
+ const devices = (Array.isArray(entry.devices) ? entry.devices : []).flatMap((preset) => {
498
+ const parsed = devicepresetof(preset);
499
+ return parsed !== void 0 ? [parsed] : [];
500
+ });
501
+ const networks = (Array.isArray(entry.networks) ? entry.networks : []).flatMap((preset) => {
502
+ const parsed = networkpresetof(preset);
503
+ return parsed !== void 0 ? [parsed] : [];
504
+ });
505
+ const locations = (Array.isArray(entry.locations) ? entry.locations : []).flatMap((preset) => {
506
+ const parsed = locationpresetof(preset);
507
+ return parsed !== void 0 ? [parsed] : [];
508
+ });
509
+ const agents = (Array.isArray(entry.agents) ? entry.agents : []).flatMap((preset) => {
510
+ const parsed = agentpresetof(preset);
511
+ return parsed !== void 0 ? [parsed] : [];
512
+ });
513
+ if (devices.length + networks.length + locations.length + agents.length === 0) return void 0;
514
+ return { version: typeof entry.version === "number" && Number.isInteger(entry.version) && entry.version >= 1 ? entry.version : 1, devices, networks, locations, agents, exportedat: typeof entry.exportedat === "number" ? entry.exportedat : Date.now() };
515
+ }
516
+ function locationconsentcovers(origin, latitude, longitude, consents) {
517
+ return consents.some((consent) => consent.origin === origin && consent.approved === true && consent.revokedat === void 0 && consent.latitude === latitude && consent.longitude === longitude);
518
+ }
519
+
336
520
  // httpclient.ts
337
521
  var httpkinds = ["fetchurl", "parsejson", "parsehtml", "callrest", "callgraphql"];
338
522
  var redirectstatuses = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
@@ -2517,6 +2701,83 @@ var sessionmemory = class {
2517
2701
  await this.adapter.set("sourcemapconsents", updated);
2518
2702
  return revoked;
2519
2703
  }
2704
+ /** Stores the emulation state of one run keyed by its run id; the reverted layer prior states expire after the user configured retention window while the layer history always survives. */
2705
+ async setemulationstate(state) {
2706
+ const retention = (await this.getsettings())?.emulationretention;
2707
+ await this.adapter.set(`emulationstate${state.runid}`, expirelayers(state, retention, Date.now()));
2708
+ }
2709
+ /** Returns the persisted emulation state of one run so the layers survive service worker restarts. */
2710
+ async getemulationstate(runid) {
2711
+ return this.adapter.get(`emulationstate${runid}`);
2712
+ }
2713
+ /** Returns the active and past layers of one run, newest last in apply order; the listlayers accessor of the emulation memory. */
2714
+ async listlayers(runid) {
2715
+ const state = await this.getemulationstate(runid);
2716
+ return state?.layers ?? [];
2717
+ }
2718
+ /** Stores one user curated device preset by its name so the preset library stays user data instead of a hardcoded list. */
2719
+ async setdevicepreset(preset) {
2720
+ const records = (await this.adapter.get("devicepresets") ?? []).filter((item) => item.name !== preset.name);
2721
+ await this.adapter.set("devicepresets", [...records, preset]);
2722
+ }
2723
+ /** Returns every user curated device preset. */
2724
+ async getdevicepresets() {
2725
+ return await this.adapter.get("devicepresets") ?? [];
2726
+ }
2727
+ /** Stores one user curated network preset by its name with editable values. */
2728
+ async setnetworkpreset(preset) {
2729
+ const records = (await this.adapter.get("networkpresets") ?? []).filter((item) => item.name !== preset.name);
2730
+ await this.adapter.set("networkpresets", [...records, preset]);
2731
+ }
2732
+ /** Returns every user curated network preset. */
2733
+ async getnetworkpresets() {
2734
+ return await this.adapter.get("networkpresets") ?? [];
2735
+ }
2736
+ /** Stores one user curated location preset by its name. */
2737
+ async setlocationpreset(preset) {
2738
+ const records = (await this.adapter.get("locationpresets") ?? []).filter((item) => item.name !== preset.name);
2739
+ await this.adapter.set("locationpresets", [...records, preset]);
2740
+ }
2741
+ /** Returns every user curated location preset. */
2742
+ async getlocationpresets() {
2743
+ return await this.adapter.get("locationpresets") ?? [];
2744
+ }
2745
+ /** Stores one user curated agent preset by its name. */
2746
+ async setagentpreset(preset) {
2747
+ const records = (await this.adapter.get("agentpresets") ?? []).filter((item) => item.name !== preset.name);
2748
+ await this.adapter.set("agentpresets", [...records, preset]);
2749
+ }
2750
+ /** Returns every user curated agent preset. */
2751
+ async getagentpresets() {
2752
+ return await this.adapter.get("agentpresets") ?? [];
2753
+ }
2754
+ /** Replaces the blackbox rule set of one origin so third party script blackboxing stays scoped per origin. */
2755
+ async setblackboxrules(origin, rules) {
2756
+ const records = (await this.adapter.get("blackboxrules") ?? []).filter((item) => item.origin !== origin);
2757
+ await this.adapter.set("blackboxrules", [...records, { origin, rules }]);
2758
+ }
2759
+ /** Returns every stored blackbox rule set with its origin. */
2760
+ async getblackboxrules() {
2761
+ return await this.adapter.get("blackboxrules") ?? [];
2762
+ }
2763
+ /** Records one permission override of a run with its prior state captured for the exact restore. */
2764
+ async addpermissionoverride(record2) {
2765
+ const records = (await this.adapter.get("permissionoverrides") ?? []).filter((item) => item.id !== record2.id);
2766
+ await this.adapter.set("permissionoverrides", [record2, ...records]);
2767
+ }
2768
+ /** Returns the permission override history with restore states, newest first. */
2769
+ async getpermissionoverrides() {
2770
+ return await this.adapter.get("permissionoverrides") ?? [];
2771
+ }
2772
+ /** Stores one location consent decision per origin, replacing the previous decision of its id. */
2773
+ async setlocationconsent(consent) {
2774
+ const records = (await this.adapter.get("locationconsents") ?? []).filter((item) => item.id !== consent.id);
2775
+ await this.adapter.set("locationconsents", [consent, ...records]);
2776
+ }
2777
+ /** Returns every location consent decision, newest first. */
2778
+ async getlocationconsents() {
2779
+ return await this.adapter.get("locationconsents") ?? [];
2780
+ }
2520
2781
  };
2521
2782
  function mediakindof(record2) {
2522
2783
  if ("pages" in record2) return "pdf";
@@ -3463,9 +3724,9 @@ function polldecision(input) {
3463
3724
  }
3464
3725
 
3465
3726
  // policy.ts
3466
- 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", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps"]);
3727
+ 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", "recordscreen", "captureaudio", "downloadimages", "callrest", "callgraphql", "sendmessage", "blockrequest", "mockresponse", "rewriteheaders", "setcookies", "clearcookies", "authflow", "saveapikey", "routeproxy", "postform", "postfiles", "attachcdp", "detachcdp", "cdpcmd", "overridescript", "heapshot", "profilecpu", "capturesourcemaps", "emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission"]);
3467
3728
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction", "capturebodies", "setbreakpoint", "stepcode", "watchexpr"]);
3468
- 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", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace"]);
3729
+ 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", "capturepdf", "captureframe", "readmedia", "readassets", "probestream", "timelapse", "shotcanvas", "convertimage", "makethumbs", "fetchurl", "parsejson", "parsehtml", "opensocket", "waitmessage", "watchrequests", "readheaders", "mapapi", "subscribesse", "longpoll", "extractapi", "readcookies", "watchconsole", "watcherrors", "watchtasks", "watchcdp", "measureflow", "trackmemory", "watchshifts", "traceload", "annotatetrace", "replaytrace", "blackboxscripts"]);
3469
3730
  var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
3470
3731
  var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
3471
3732
  var targetactions = /* @__PURE__ */ new Set(["inspect", "focus", "click", "type", "scroll", "select", "hover", "clickdeep", "rightclick", "doubleclick", "drag", "drop", "upload", "clear", "check", "uncheck", "toggle", "submit", "readattribute", "readstyle", "readgeometry", "readvalue", "readtext", "readhtml", "countelements", "readtable", "highlight", "setattribute", "removeattribute", "waitfor", "shiftclick", "typetime", "appendtext", "setvalue", "typeedit", "submitsearch", "selectmulti", "chooseradio", "setslider", "setdate", "setcolor", "expanddetails", "verifyvisible", "verifyenabled", "pierceshadow", "deriveselector", "fingerprintsection", "submitform", "retryform", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "scrapetable", "paginateextract", "shotelement", "captureframe", "shotcanvas"]);
@@ -3484,6 +3745,7 @@ var controlactions = /* @__PURE__ */ new Set(["blockrequest", "mockresponse", "r
3484
3745
  var debugactions = /* @__PURE__ */ new Set(["watchconsole", "watcherrors", "watchtasks"]);
3485
3746
  var cdpactions = /* @__PURE__ */ new Set(["attachcdp", "detachcdp", "cdpcmd", "watchcdp", "setbreakpoint", "stepcode", "watchexpr", "overridescript"]);
3486
3747
  var profileractions = /* @__PURE__ */ new Set(["measureflow", "heapshot", "trackmemory", "profilecpu", "watchshifts", "traceload", "annotatetrace", "replaytrace", "capturesourcemaps"]);
3748
+ var emulationactions = /* @__PURE__ */ new Set(["emulatedevice", "emulatenetwork", "emulatelocate", "setuseragent", "overridepermission", "blackboxscripts"]);
3487
3749
  var credentialheaders = /* @__PURE__ */ new Set(["authorization", "proxy-authorization", "cookie", "cookie2", "set-cookie", "api-key", "x-api-key", "x-auth-token", "x-session-token", "proxy-authorization"]);
3488
3750
  var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
3489
3751
  var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
@@ -3511,6 +3773,9 @@ function iscdpkind(kind) {
3511
3773
  function isprofilekind(kind) {
3512
3774
  return profileractions.has(kind);
3513
3775
  }
3776
+ function isemulationkind(kind) {
3777
+ return emulationactions.has(kind);
3778
+ }
3514
3779
  function observationmodeof(kind) {
3515
3780
  if (watchactions.has(kind) || debugactions.has(kind) || profileractions.has(kind) && kind !== "heapshot" && kind !== "replaytrace" && kind !== "annotatetrace" && kind !== "capturesourcemaps" && kind !== "profilecpu" || cdpactions.has(kind) && kind === "watchcdp" || kind === "waitquiet") return "watching";
3516
3781
  if (kind === "diffsnapshots") return "diffing";
@@ -4795,6 +5060,85 @@ function pauseretentionwindow(settings) {
4795
5060
  function breakpointceilingof(settings) {
4796
5061
  return settings?.breakpointceiling;
4797
5062
  }
5063
+ function emugate(input) {
5064
+ const gate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now: input.now, action: "emulate the run tab" });
5065
+ if (!gate.allowed) return gate;
5066
+ if (!input.plan || input.plan.state !== "approved") return { allowed: false, reason: "Emulation layers need an approved plan before they apply." };
5067
+ let options = {};
5068
+ try {
5069
+ options = parseoptions(input.step);
5070
+ } catch {
5071
+ options = {};
5072
+ }
5073
+ if (options.reviewed !== true) return { allowed: false, reason: `The ${input.step.kind} layer needs the explicit reviewed flag before any mask applies.` };
5074
+ if (revertplanof(options.revertplan) === void 0) return { allowed: false, reason: `Every ${input.step.kind} layer needs a reviewed revert plan beside it before any mask applies.` };
5075
+ return { allowed: true };
5076
+ }
5077
+ function emulationstackallowed(plan, kind, active) {
5078
+ if (!plan) return { allowed: false, reason: "Layer stacking needs the reviewed plan first." };
5079
+ const listed = plan.steps.filter((step) => step.kind === kind).length;
5080
+ if (active >= listed) return { allowed: false, reason: `The plan lists ${listed} reviewed ${kind} step${listed === 1 ? "" : "s"} and ${active} layer${active === 1 ? "" : "s"} of that family are already active; stacking beyond the reviewed plan is refused.` };
5081
+ return { allowed: true };
5082
+ }
5083
+ function locationconsentgate(origin, latitude, longitude, consents) {
5084
+ if (consents.some((consent) => consent.origin === origin && consent.revokedat !== void 0)) return { allowed: false, reason: `The location consent on ${origin} was revoked; approve a new prompt before the location override runs again.` };
5085
+ if (locationconsentcovers(origin, latitude, longitude, consents)) return { allowed: true };
5086
+ return { allowed: false, reason: `The location override of ${latitude}, ${longitude} on ${origin} needs the reviewed location consent first; approve the prompt with the coordinates shown in the review panel.` };
5087
+ }
5088
+ function emulationretentionwindow(settings) {
5089
+ return settings?.emulationretention;
5090
+ }
5091
+ function validateemulationgrammar(step, options) {
5092
+ const kind = step.kind;
5093
+ if (revertplanof(options.revertplan) === void 0) return { allowed: false, reason: `Every ${kind} layer needs a reviewed revert plan before any mask applies.` };
5094
+ if (kind === "emulatedevice") {
5095
+ const preset = devicepresetof(options.device);
5096
+ if (!preset) return { allowed: false, reason: "The device layer needs a reviewed preset with a name, positive integer width and height and a positive pixel ratio." };
5097
+ if (options.reload !== void 0 && typeof options.reload !== "boolean") return { allowed: false, reason: "The reviewed reload flag must be a boolean; the page reloads only when the reviewed plan asks." };
5098
+ return { allowed: true };
5099
+ }
5100
+ if (kind === "emulatenetwork") {
5101
+ const preset = networkpresetof(options.network);
5102
+ if (!preset) return { allowed: false, reason: "The network layer needs a reviewed preset with a name and zero or positive latency, download and upload bounds." };
5103
+ if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isFinite(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed offline window must be zero or a positive number of milliseconds with no code ceiling." };
5104
+ return { allowed: true };
5105
+ }
5106
+ if (kind === "emulatelocate") {
5107
+ const preset = locationpresetof(options.location);
5108
+ if (!preset) return { allowed: false, reason: "The location layer needs a reviewed preset with a name, a latitude inside -90 and 90, a longitude inside -180 and 180 and a zero or positive accuracy radius." };
5109
+ if (!locationrangevalid(preset.latitude, preset.longitude)) return { allowed: false, reason: "The reviewed latitude must stay inside -90 and 90 degrees and the longitude inside -180 and 180 degrees." };
5110
+ return { allowed: true };
5111
+ }
5112
+ if (kind === "setuseragent") {
5113
+ const preset = agentpresetof(options.agent);
5114
+ if (!preset) return { allowed: false, reason: "The agent layer needs a reviewed preset with a user agent string of the reviewed grammar, a platform and a non-empty brand list." };
5115
+ if (!agentgrammarvalid(preset.useragent)) return { allowed: false, reason: "The reviewed user agent string must use the reviewed grammar of tokens, separators and version marks without line breaks." };
5116
+ return { allowed: true };
5117
+ }
5118
+ if (kind === "overridepermission") {
5119
+ const grant = permissiongrantof(options.permission);
5120
+ if (!grant) return { allowed: false, reason: `The permission override needs a reviewed name of the browser permission set (${browserpermissions.join(", ")}) and a state of ${permissionstates.join(", ")}.` };
5121
+ void permissiongrade(grant.name);
5122
+ return { allowed: true };
5123
+ }
5124
+ if (kind === "blackboxscripts") {
5125
+ const rules = Array.isArray(options.rules) ? options.rules.flatMap((rule) => {
5126
+ const parsed = blackboxruleof(rule);
5127
+ return parsed !== void 0 ? [parsed] : [];
5128
+ }) : [];
5129
+ if (rules.length === 0) return { allowed: false, reason: "The blackbox layer needs a reviewed non-empty rule list where every pattern names its origin explicitly and carries a trace scope." };
5130
+ return { allowed: true };
5131
+ }
5132
+ return { allowed: true };
5133
+ }
5134
+ function permissionnamevalid(name) {
5135
+ if (!browserpermissions.includes(name)) return { allowed: false, reason: `The permission ${name} stays outside the reviewed browser permission set: ${browserpermissions.join(", ")}.` };
5136
+ return { allowed: true };
5137
+ }
5138
+ function permissionstatevalid(state) {
5139
+ if (!permissionstates.includes(state)) return { allowed: false, reason: `The reviewed permission state must be one of ${permissionstates.join(", ")}.` };
5140
+ return { allowed: true };
5141
+ }
4798
5142
  function validatecdpgrammar(step, options) {
4799
5143
  const kind = step.kind;
4800
5144
  if (kind === "attachcdp") {
@@ -5352,6 +5696,10 @@ function validatestep(step, origin) {
5352
5696
  const profilecheck = validateprofilegrammar(step, options);
5353
5697
  if (!profilecheck.allowed) return profilecheck;
5354
5698
  }
5699
+ if (isemulationkind(step.kind)) {
5700
+ const emulationcheck = validateemulationgrammar(step, options);
5701
+ if (!emulationcheck.allowed) return emulationcheck;
5702
+ }
5355
5703
  if (step.kind === "tabcreate") {
5356
5704
  if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
5357
5705
  if (options.window !== void 0 && (typeof options.window !== "number" || !Number.isInteger(options.window) || options.window < 0)) return { allowed: false, reason: "The reviewed target window id must be a non-negative integer." };
@@ -5521,6 +5869,10 @@ function canexecute(input) {
5521
5869
  }
5522
5870
  }
5523
5871
  }
5872
+ if (isemulationkind(input.step.kind)) {
5873
+ const emugatecheck = emugate({ session: input.session, plan: input.plan, step: input.step, tabid: input.tabid, origin: input.origin, now });
5874
+ if (!emugatecheck.allowed) return emugatecheck;
5875
+ }
5524
5876
  if (iscontrolkind(input.step.kind)) {
5525
5877
  const controlgate = sessiongate({ session: input.session, tabid: input.tabid, origin: input.origin, now, action: "control the network" });
5526
5878
  if (!controlgate.allowed) return controlgate;
@@ -5604,7 +5956,7 @@ function canexecute(input) {
5604
5956
  }
5605
5957
 
5606
5958
  // version.ts
5607
- var packageversion = "1.1.47";
5959
+ var packageversion = "1.1.48";
5608
5960
 
5609
5961
  // types.ts
5610
5962
  var protocolversion = packageversion;
@@ -5776,6 +6128,28 @@ function parseproposal(value, origin, grants) {
5776
6128
  }
5777
6129
  if (step.kind === "annotatetrace" && (!Array.isArray(profileoptions.annotations) || profileoptions.annotations.length === 0 || !profileoptions.annotations.every((annotation) => annotationof(annotation) !== void 0))) throw new Error("Trace annotation steps without reviewed step annotations are refused.");
5778
6130
  }
6131
+ if (isemulationkind(step.kind)) {
6132
+ const granted = covered.some((pattern) => {
6133
+ try {
6134
+ return new URL(origin).origin === new URL(pattern).origin;
6135
+ } catch {
6136
+ return false;
6137
+ }
6138
+ });
6139
+ if (!granted) throw new Error(`The ${step.kind} step of ${origin} targets an origin outside the grants.`);
6140
+ let emulationoptions = {};
6141
+ try {
6142
+ emulationoptions = parseoptions(step);
6143
+ } catch {
6144
+ emulationoptions = {};
6145
+ }
6146
+ if (revertplanof(emulationoptions.revertplan) === void 0) throw new Error("Emulation steps without a reviewed revert plan are refused.");
6147
+ if (step.kind === "emulatelocate") {
6148
+ const preset = locationpresetof(emulationoptions.location);
6149
+ if (preset === void 0) throw new Error("Location emulation needs a reviewed preset with coordinates inside the latitude and longitude ranges.");
6150
+ }
6151
+ if (step.kind === "overridepermission" && permissiongrantof(emulationoptions.permission) === void 0) throw new Error("Permission overrides of unknown permission names are refused.");
6152
+ }
5779
6153
  const evaluation = validatestep(step, origin);
5780
6154
  if (!evaluation.allowed) throw new Error(evaluation.reason);
5781
6155
  const target = outboundtarget(step);
@@ -5850,7 +6224,7 @@ function requestbody(input) {
5850
6224
  return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
5851
6225
  }
5852
6226
  function outcomeresponse(input) {
5853
- return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {} });
6227
+ return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {}, ...input.capture ? { capture: input.capture } : {}, ...input.media ? { media: input.media } : {}, ...input.transport ? { transport: input.transport } : {}, ...input.network ? { network: input.network } : {}, ...input.control ? { control: input.control } : {}, ...input.timeline ? { timeline: input.timeline } : {}, ...input.cdp ? { cdp: input.cdp } : {}, ...input.profile ? { profile: input.profile } : {}, ...input.emulation ? { emulation: input.emulation } : {} });
5854
6228
  }
5855
6229
  function mapresponse(input) {
5856
6230
  return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
@@ -5988,7 +6362,18 @@ function profilereport(input) {
5988
6362
  });
5989
6363
  return { version: protocolversion, flows: input.flows, heaps: input.heaps, samples: input.samples, trends: input.trends, profiles: input.profiles, shifts: input.shifts, traces: input.traces, sourcemaps: input.sourcemaps, consents };
5990
6364
  }
6365
+ function emulationreport(input) {
6366
+ const consents = input.consents.map((consent) => {
6367
+ const { prompt, ...metadata } = consent;
6368
+ void prompt;
6369
+ return metadata;
6370
+ });
6371
+ return { version: protocolversion, ...input.state !== void 0 ? { state: input.state } : {}, layers: input.state?.layers ?? [], devices: input.devices, networks: input.networks, locations: input.locations, agents: input.agents, blackbox: input.blackbox, permissions: input.permissions, consents };
6372
+ }
5991
6373
  export {
6374
+ activelayers,
6375
+ agentgrammarvalid,
6376
+ agentpresetof,
5992
6377
  allowlistcovers,
5993
6378
  annotatetrace,
5994
6379
  annotationof,
@@ -5997,6 +6382,7 @@ export {
5997
6382
  apikeyconsentgranted,
5998
6383
  apireplayspecof,
5999
6384
  applyheaderules,
6385
+ applylayer,
6000
6386
  argkind,
6001
6387
  assetentries,
6002
6388
  attachcdpsession,
@@ -6005,6 +6391,9 @@ export {
6005
6391
  authconsentgranted,
6006
6392
  authorizeurl,
6007
6393
  authreport,
6394
+ blackboxedurls,
6395
+ blackboxmatches,
6396
+ blackboxruleof,
6008
6397
  blendrows,
6009
6398
  blockgate,
6010
6399
  blockingduration,
@@ -6014,6 +6403,7 @@ export {
6014
6403
  breakpointbudgetallowed,
6015
6404
  breakpointceilingof,
6016
6405
  breakpointinputof,
6406
+ browserpermissions,
6017
6407
  buildname,
6018
6408
  buildpdf,
6019
6409
  buildsheet,
@@ -6069,17 +6459,27 @@ export {
6069
6459
  dedupeimages,
6070
6460
  actionrisk as deriveactionrisk,
6071
6461
  detachcdpsession,
6462
+ devicepresetof,
6072
6463
  diffresponse,
6073
6464
  diffreviewgrade,
6074
6465
  downloadreport,
6466
+ emugate,
6467
+ emulationkinds,
6468
+ emulationreport,
6469
+ emulationretentionwindow,
6470
+ emulationstackallowed,
6471
+ emulationstateof,
6075
6472
  errorcapture,
6076
6473
  errorreportresponse,
6077
6474
  eventresponse,
6078
6475
  exchangesreport,
6476
+ expirelayers,
6079
6477
  expireprofilerecords,
6478
+ exportpresetlibrary,
6080
6479
  extractionreport,
6081
6480
  extractvalues,
6082
6481
  failureclass,
6482
+ familyofkind,
6083
6483
  fetchoptionsof,
6084
6484
  fetchrequestof,
6085
6485
  filterentries,
@@ -6101,15 +6501,18 @@ export {
6101
6501
  heapintervalallowed,
6102
6502
  heapsnap,
6103
6503
  heldkeysreport,
6504
+ hideblackboxedframes,
6104
6505
  hostpattern,
6105
6506
  htmlqueriesof,
6106
6507
  httpkinds,
6107
6508
  imagefilterof,
6108
6509
  imagematches,
6109
6510
  imagenames,
6511
+ importpresetlibrary,
6110
6512
  iscdpkind,
6111
6513
  iscontrolkind,
6112
6514
  isdebugkind,
6515
+ isemulationkind,
6113
6516
  isformkind,
6114
6517
  isnetwatchkind,
6115
6518
  isprofilekind,
@@ -6118,8 +6521,13 @@ export {
6118
6521
  jsonpathrulesof,
6119
6522
  lapseframes,
6120
6523
  lapseplanof,
6524
+ layernames,
6121
6525
  layoutreport,
6122
6526
  levelrank,
6527
+ locationconsentcovers,
6528
+ locationconsentgate,
6529
+ locationpresetof,
6530
+ locationrangevalid,
6123
6531
  loglevels,
6124
6532
  longtaskcapture,
6125
6533
  mapresponse,
@@ -6140,10 +6548,12 @@ export {
6140
6548
  netfailureentryof,
6141
6549
  netlogreport,
6142
6550
  netwatchkinds,
6551
+ networkpresetof,
6143
6552
  newblockrule,
6144
6553
  newchannel,
6145
6554
  newexchange,
6146
6555
  newheaderule,
6556
+ newlayer,
6147
6557
  newmockspec,
6148
6558
  newrecording,
6149
6559
  normalizeendpoint,
@@ -6170,6 +6580,11 @@ export {
6170
6580
  pdfpagesize,
6171
6581
  pdfsegments,
6172
6582
  pdftextlayout,
6583
+ permissiongrade,
6584
+ permissiongrantof,
6585
+ permissionnamevalid,
6586
+ permissionstates,
6587
+ permissionstatevalid,
6173
6588
  planallowlist,
6174
6589
  pollcursorof,
6175
6590
  polldecision,
@@ -6207,6 +6622,9 @@ export {
6207
6622
  resolvedrisk,
6208
6623
  resourcefacts,
6209
6624
  retryafterof,
6625
+ revertalllayers,
6626
+ revertlayer,
6627
+ revertplanof,
6210
6628
  revertrule,
6211
6629
  revocationruleof,
6212
6630
  rewritesourcelocation,
@@ -6230,6 +6648,7 @@ export {
6230
6648
  spamdetect,
6231
6649
  spamruleof,
6232
6650
  sserequestheaders,
6651
+ stackedcount,
6233
6652
  stackframes,
6234
6653
  stackgate,
6235
6654
  statusclassof,