@wenathlan/extension 1.1.38 → 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.
package/dist/index.js CHANGED
@@ -1,3 +1,201 @@
1
+ // capture.ts
2
+ var captureformats = ["png", "jpeg", "webp"];
3
+ var capturetargets = ["memory", "download", "clipboard"];
4
+ var capturekinds = ["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"];
5
+ function captureoptionsof(value) {
6
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
7
+ const options = value;
8
+ const normalized = {};
9
+ if (options.format === "png" || options.format === "jpeg" || options.format === "webp") normalized.format = options.format;
10
+ if (typeof options.quality === "number" && Number.isFinite(options.quality)) normalized.quality = options.quality;
11
+ if (typeof options.pixelratio === "number" && Number.isFinite(options.pixelratio)) normalized.pixelratio = options.pixelratio;
12
+ if (typeof options.annotate === "boolean") normalized.annotate = options.annotate;
13
+ if (options.exporttarget === "memory" || options.exporttarget === "download" || options.exporttarget === "clipboard") normalized.exporttarget = options.exporttarget;
14
+ return normalized;
15
+ }
16
+ function capturevisible(input) {
17
+ const ratio = input.options.pixelratio ?? 1;
18
+ return {
19
+ id: input.id,
20
+ runid: input.runid,
21
+ stepid: input.stepid,
22
+ kind: "shotview",
23
+ format: input.options.format ?? "png",
24
+ width: Math.round(input.viewport.width * ratio),
25
+ height: Math.round(input.viewport.height * ratio),
26
+ capturedat: input.at,
27
+ bytes: input.dataurl,
28
+ ...input.name !== void 0 ? { name: input.name } : {},
29
+ ...input.options.annotate === true ? { annotated: true } : {},
30
+ ...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
31
+ ...input.target !== void 0 ? { target: input.target } : {}
32
+ };
33
+ }
34
+ function capturestitched(input) {
35
+ const ratio = input.options.pixelratio ?? 1;
36
+ return {
37
+ id: input.id,
38
+ runid: input.runid,
39
+ stepid: input.stepid,
40
+ kind: "shotfullpage",
41
+ format: input.options.format ?? "png",
42
+ width: Math.round(input.plan.scrollwidth * ratio),
43
+ height: Math.round(input.plan.scrollheight * ratio),
44
+ capturedat: input.at,
45
+ bytes: input.dataurl,
46
+ ...input.name !== void 0 ? { name: input.name } : {},
47
+ ...input.options.annotate === true ? { annotated: true } : {},
48
+ ...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {}
49
+ };
50
+ }
51
+ function captureelement(input) {
52
+ const ratio = input.options.pixelratio ?? 1;
53
+ const scaled = scaledrect(input.rect, ratio);
54
+ return {
55
+ id: input.id,
56
+ runid: input.runid,
57
+ stepid: input.stepid,
58
+ kind: "shotelement",
59
+ format: input.options.format ?? "png",
60
+ width: scaled.width,
61
+ height: scaled.height,
62
+ capturedat: input.at,
63
+ bytes: input.dataurl,
64
+ ...input.name !== void 0 ? { name: input.name } : {},
65
+ ...input.options.annotate === true ? { annotated: true } : {},
66
+ ...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
67
+ ...input.target !== void 0 ? { target: input.target } : {}
68
+ };
69
+ }
70
+ function captureregion(input) {
71
+ const ratio = input.options.pixelratio ?? 1;
72
+ const scaled = scaledrect(input.rect, ratio);
73
+ return {
74
+ id: input.id,
75
+ runid: input.runid,
76
+ stepid: input.stepid,
77
+ kind: "shotregion",
78
+ format: input.options.format ?? "png",
79
+ width: scaled.width,
80
+ height: scaled.height,
81
+ capturedat: input.at,
82
+ bytes: input.dataurl,
83
+ ...input.name !== void 0 ? { name: input.name } : {},
84
+ ...input.options.annotate === true ? { annotated: true } : {},
85
+ ...input.options.exporttarget !== void 0 ? { exporttarget: input.options.exporttarget } : {},
86
+ ...input.target !== void 0 ? { target: input.target } : {}
87
+ };
88
+ }
89
+ function pairstates(before, after, action, at, id) {
90
+ if (!before) return { skipped: "before", reason: "The before shot was not captured, so no state pair exists." };
91
+ if (!after) return { skipped: "after", reason: `The action of kind ${action.kind} failed before the after shot, so the state pair is skipped.` };
92
+ return {
93
+ pair: {
94
+ id,
95
+ beforeid: before.id,
96
+ afterid: after.id,
97
+ actionkind: action.kind,
98
+ ...action.target !== void 0 ? { target: action.target } : {},
99
+ ...action.domsnapshotid !== void 0 ? { domsnapshotid: action.domsnapshotid } : {},
100
+ at
101
+ },
102
+ reason: `Paired the before shot ${before.id} with the after shot ${after.id} around the ${action.kind} action.`
103
+ };
104
+ }
105
+ function capturestates(input) {
106
+ if (input.policy !== "beforeafter") return { reason: `The ${input.policy} capture policy takes no state pair around the ${input.actionkind} action.` };
107
+ return pairstates(input.before, input.after, { kind: input.actionkind, ...input.target !== void 0 ? { target: input.target } : {}, ...input.domsnapshotid !== void 0 ? { domsnapshotid: input.domsnapshotid } : {} }, input.at, input.id);
108
+ }
109
+ function buildstitchplan(input) {
110
+ const overlap = Math.max(0, Math.round(input.overlap ?? 0));
111
+ const stepy = Math.max(1, input.viewportheight - overlap);
112
+ const columns = Math.max(1, Math.ceil(input.scrollwidth / input.viewportwidth));
113
+ const rows = input.scrollheight <= input.viewportheight ? 1 : Math.max(1, Math.ceil((input.scrollheight - overlap) / stepy));
114
+ const tiles = [];
115
+ for (let column = 0; column < columns; column += 1) {
116
+ for (let row = 0; row < rows; row += 1) {
117
+ const x = Math.min(column * input.viewportwidth, Math.max(0, input.scrollwidth - input.viewportwidth));
118
+ const y = rows === 1 ? 0 : Math.min(row * stepy, Math.max(0, input.scrollheight - input.viewportheight));
119
+ tiles.push({ x: Math.round(x), y: Math.round(y) });
120
+ }
121
+ }
122
+ return { columns, rows, tiles, overlap, scrollwidth: Math.round(input.scrollwidth), scrollheight: Math.round(input.scrollheight), viewportwidth: Math.round(input.viewportwidth), viewportheight: Math.round(input.viewportheight) };
123
+ }
124
+ function seamweights(overlap) {
125
+ if (overlap <= 0) return [];
126
+ const weights = [];
127
+ for (let index = 0; index < overlap; index += 1) weights.push((index + 1) / (overlap + 1));
128
+ return weights;
129
+ }
130
+ function blendrows(upper, lower) {
131
+ const weights = seamweights(upper.length);
132
+ return upper.map((value, index) => {
133
+ const weight = weights[index] ?? 1;
134
+ return value * (1 - weight) + (lower[index] ?? value) * weight;
135
+ });
136
+ }
137
+ function fixedheadermatch(band, firstband) {
138
+ if (band.length === 0 || band.length !== firstband.length) return false;
139
+ return band.every((value, index) => value === firstband[index]);
140
+ }
141
+ function scaledrect(rect, pixelratio) {
142
+ const ratio = pixelratio >= 1 ? pixelratio : 1;
143
+ return { x: Math.round(rect.x * ratio), y: Math.round(rect.y * ratio), width: Math.round(rect.width * ratio), height: Math.round(rect.height * ratio) };
144
+ }
145
+ function croprect(rect, viewport) {
146
+ const x = Math.max(0, rect.x);
147
+ const y = Math.max(0, rect.y);
148
+ return { x: Math.round(x), y: Math.round(y), width: Math.round(Math.max(0, Math.min(rect.width, viewport.width - x))), height: Math.round(Math.max(0, Math.min(rect.height, viewport.height - y))) };
149
+ }
150
+ function crossesviewport(rect, viewport) {
151
+ return rect.x < 0 || rect.y < 0 || rect.x + rect.width > viewport.width || rect.y + rect.height > viewport.height;
152
+ }
153
+ function regionsteps(containerheight, viewportstep) {
154
+ if (containerheight <= 0 || viewportstep <= 0) return [0];
155
+ const steps = [];
156
+ for (let top = 0; top < containerheight; top += viewportstep) {
157
+ const clamped = Math.min(top, Math.max(0, containerheight - viewportstep));
158
+ if (!steps.includes(clamped)) steps.push(clamped);
159
+ }
160
+ return steps;
161
+ }
162
+ function buildsheet(cells, layout) {
163
+ const columns = Math.max(1, Math.round(layout.columns));
164
+ const rows = Math.max(1, Math.ceil(cells.length / columns));
165
+ const placed = cells.map((cell, index) => {
166
+ const column = index % columns;
167
+ const row = Math.floor(index / columns);
168
+ const label = cell.label ?? "";
169
+ const caption = layout.label === "none" ? "" : layout.label === "index" ? `${index + 1}` : layout.label === "selector" ? cell.selector : label ? `${index + 1} \xB7 ${cell.selector} \xB7 ${label}` : `${index + 1} \xB7 ${cell.selector}`;
170
+ return { index, column, row, selector: cell.selector, label, caption };
171
+ });
172
+ return { columns, rows, cells: placed };
173
+ }
174
+ function capturepart(value) {
175
+ return value.replace(/[^a-z0-9-]+/gi, "-").replace(/^-+|-+$/g, "").toLowerCase() || "capture";
176
+ }
177
+ function buildname(rule, parts, extension) {
178
+ const segments = [];
179
+ if (rule.run) segments.push(capturepart(parts.run));
180
+ if (rule.step) segments.push(capturepart(parts.step));
181
+ if (rule.sequence) segments.push(String(Math.max(0, Math.round(parts.sequence))));
182
+ if (rule.kind) segments.push(capturepart(parts.kind));
183
+ const safeextension = extension.replace(/^\.+/, "").toLowerCase() || "png";
184
+ return `${(segments.length > 0 ? segments : ["capture"]).join("-")}.${safeextension}`;
185
+ }
186
+ function annotationplanof(input) {
187
+ const inset = Math.min(24, Math.max(8, Math.round(Math.min(input.width, input.height) / 12)));
188
+ const plan = {
189
+ marker: { x: inset, y: inset, number: Math.max(1, Math.round(input.step)) },
190
+ footer: `${new Date(input.at).toISOString()} \xB7 ${input.url}`
191
+ };
192
+ if (input.rect !== void 0) {
193
+ const expansion = 2;
194
+ plan.outline = { x: Math.round(input.rect.x - expansion), y: Math.round(input.rect.y - expansion), width: Math.round(input.rect.width + expansion * 2), height: Math.round(input.rect.height + expansion * 2) };
195
+ }
196
+ return plan;
197
+ }
198
+
1
199
  // memory.ts
2
200
  var sessionmemory = class {
3
201
  constructor(adapter) {
@@ -619,23 +817,176 @@ var sessionmemory = class {
619
817
  async getexports() {
620
818
  return await this.adapter.get("exports") ?? [];
621
819
  }
820
+ /** Removes one exported data artifact by id and reports whether it existed. */
821
+ async removeexport(id) {
822
+ const records = await this.getexports();
823
+ const remaining = records.filter((item) => item.id !== id);
824
+ await this.adapter.set("exports", remaining);
825
+ return remaining.length !== records.length;
826
+ }
827
+ /** Removes one run store artifact by id and reports whether it existed. */
828
+ async removeartifact(id) {
829
+ const records = await this.getartifacts();
830
+ const remaining = records.filter((item) => item.id !== id);
831
+ await this.adapter.set("artifacts", remaining);
832
+ return remaining.length !== records.length;
833
+ }
834
+ /** Stores one batch download file record with its state, path and checksum, replacing the previous record of that id. */
835
+ async setdownload(record2) {
836
+ const records = (await this.adapter.get("downloads") ?? []).filter((item) => item.id !== record2.id);
837
+ await this.adapter.set("downloads", [record2, ...records]);
838
+ }
839
+ /** Returns every batch download file record with its state, path and checksum, newest first. */
840
+ async getdownloads() {
841
+ return await this.adapter.get("downloads") ?? [];
842
+ }
843
+ /** Records one captured network log record; netlog retention is a user setting and an absent value keeps every record. */
844
+ async addnetlog(record2) {
845
+ const records = await this.getnetlog();
846
+ const combined = [record2, ...records];
847
+ const retention = (await this.getsettings())?.netlogretention;
848
+ await this.adapter.set("netlog", retention === void 0 ? combined : combined.slice(0, retention));
849
+ }
850
+ /** Returns the captured network log of the run with its step correlation, newest first. */
851
+ async getnetlog() {
852
+ return await this.adapter.get("netlog") ?? [];
853
+ }
854
+ /** Stores one clipboard consent record with its prompt and origin, replacing the previous record of that id. */
855
+ async setclipconsent(record2) {
856
+ const records = (await this.adapter.get("clipconsents") ?? []).filter((item) => item.id !== record2.id);
857
+ await this.adapter.set("clipconsents", [record2, ...records]);
858
+ }
859
+ /** Returns every clipboard consent record with its prompt and origin, newest first. */
860
+ async getclipconsents() {
861
+ return await this.adapter.get("clipconsents") ?? [];
862
+ }
863
+ /** Records one clipboard entry hash with its origin provenance; the payload text itself never persists. */
864
+ async addclip(entry) {
865
+ const records = await this.getclips();
866
+ await this.adapter.set("clips", [entry, ...records]);
867
+ }
868
+ /** Returns every clipboard entry hash with its kind and origin provenance, newest first. */
869
+ async getclips() {
870
+ return await this.adapter.get("clips") ?? [];
871
+ }
872
+ /** Stores one quarantine entry with its scan verdict, replacing the previous entry of that id. */
873
+ async setquarantine(entry) {
874
+ const records = (await this.adapter.get("quarantines") ?? []).filter((item) => item.id !== entry.id);
875
+ await this.adapter.set("quarantines", [entry, ...records]);
876
+ }
877
+ /** Returns every quarantine entry with its scan verdict and release ref, newest first. */
878
+ async getquarantines() {
879
+ return await this.adapter.get("quarantines") ?? [];
880
+ }
881
+ /** Stores the reviewed cleanup rule set of the run, replacing the previous set. */
882
+ async setcleanuprules(rules) {
883
+ return this.adapter.set("cleanuprules", rules);
884
+ }
885
+ /** Returns the reviewed cleanup rule set of the run. */
886
+ async getcleanuprules() {
887
+ return await this.adapter.get("cleanuprules") ?? [];
888
+ }
889
+ /** Records one cleanup run in the run history. */
890
+ async addcleanuprun(run) {
891
+ const records = await this.getcleanupruns();
892
+ await this.adapter.set("cleanupruns", [run, ...records]);
893
+ }
894
+ /** Returns every cleanup run history record with removed and kept counts, newest first. */
895
+ async getcleanupruns() {
896
+ return await this.adapter.get("cleanupruns") ?? [];
897
+ }
898
+ /** Stores the capture naming counters of one task, replacing the previous counters of that task. */
899
+ async setcapturecounter(counter) {
900
+ const records = (await this.adapter.get("capturecounters") ?? []).filter((item) => item.taskid !== counter.taskid);
901
+ await this.adapter.set("capturecounters", [counter, ...records]);
902
+ }
903
+ /** Returns every stored capture naming counter per task, newest first. */
904
+ async getcapturecounters() {
905
+ return await this.adapter.get("capturecounters") ?? [];
906
+ }
907
+ /** Replaces the artifact inventory the cleanup sweeper plans against. */
908
+ async setinventory(entries) {
909
+ return this.adapter.set("inventory", entries);
910
+ }
911
+ /** Returns the artifact inventory with sizes and ages for the cleanup sweeper. */
912
+ async getinventory() {
913
+ return await this.adapter.get("inventory") ?? [];
914
+ }
915
+ /** Stores one user configured virus scanning hook, replacing the previous hook of that scanner name. */
916
+ async setscanhook(config) {
917
+ const records = (await this.adapter.get("scanhooks") ?? []).filter((item) => item.scanner !== config.scanner);
918
+ await this.adapter.set("scanhooks", [config, ...records]);
919
+ }
920
+ /** Returns every configured virus scanning hook, newest first. */
921
+ async getscanhooks() {
922
+ return await this.adapter.get("scanhooks") ?? [];
923
+ }
924
+ /** Stores the armed mime interception filters of the run, newest first. */
925
+ async setmimefilters(filters) {
926
+ return this.adapter.set("mimefilters", filters);
927
+ }
928
+ /** Returns the armed mime interception filters of the run, newest first. */
929
+ async getmimefilters() {
930
+ return await this.adapter.get("mimefilters") ?? [];
931
+ }
932
+ /** Stores one capture record with its bytes and step linkage, replacing the previous record of that id; the user configured capture retention window expires the oldest bytes while the metadata always survives for the audit trail. */
933
+ async addcapture(record2) {
934
+ const records = await this.getcaptures();
935
+ const retention = (await this.getsettings())?.captureretention;
936
+ const combined = [record2, ...records.filter((item) => item.id !== record2.id)];
937
+ const stored = retention === void 0 ? combined : combined.map((item, index) => index < retention ? item : expirecapturebytes(item));
938
+ await this.adapter.set("captures", stored);
939
+ }
940
+ /** Returns every stored capture record with its metadata, newest first. */
941
+ async getcaptures() {
942
+ return await this.adapter.get("captures") ?? [];
943
+ }
944
+ /** Returns one capture record with its bytes by its id. */
945
+ async getcapture(id) {
946
+ return (await this.getcaptures()).find((item) => item.id === id);
947
+ }
948
+ /** Returns the capture records filtered by run, step and kind. */
949
+ async listcaptures(filter) {
950
+ const records = await this.getcaptures();
951
+ return records.filter((item) => (filter.runid === void 0 || item.runid === filter.runid) && (filter.stepid === void 0 || item.stepid === filter.stepid) && (filter.kind === void 0 || item.kind === filter.kind));
952
+ }
953
+ /** Records one before and after shotpair of the run with its action context. */
954
+ async addpair(pair) {
955
+ const records = await this.getpairs();
956
+ await this.adapter.set("capturepairs", [pair, ...records.filter((item) => item.id !== pair.id)]);
957
+ }
958
+ /** Returns the shotpairs of one run resolved through their before records, newest first; an absent run returns every pair. */
959
+ async getpairs(runid) {
960
+ const records = await this.adapter.get("capturepairs") ?? [];
961
+ if (runid === void 0) return records;
962
+ const runs = /* @__PURE__ */ new Map();
963
+ for (const capture of await this.getcaptures()) runs.set(capture.id, capture.runid);
964
+ return records.filter((item) => runs.get(item.beforeid) === runid);
965
+ }
622
966
  };
967
+ function expirecapturebytes(record2) {
968
+ const { bytes, ...metadata } = record2;
969
+ void bytes;
970
+ return { ...metadata, bytesexpired: true };
971
+ }
623
972
  function randomid() {
624
973
  return crypto.randomUUID();
625
974
  }
626
975
 
627
976
  // policy.ts
628
- 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"]);
977
+ 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"]);
629
978
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction"]);
630
- 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"]);
979
+ 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"]);
631
980
  var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
632
981
  var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
633
- 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"]);
634
- var valueactions = /* @__PURE__ */ new Set(["presskey", "drag", "drop", "upload", "readattribute", "removeattribute", "waittext", "evaluate", "zoomset", "tabactivate", "tabclose", "tabreload", "windowclose", "windowresize", "tabcreate", "windowcreate", "downloadfile", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "chooseradio", "setslider", "setdate", "setcolor", "followlink", "setfragment", "handleauth", "navintent", "openclipboard", "checksafe", "reopentab", "spanav", "duplicatetab", "pintab", "mutetab", "movetab", "movetabwindow", "searchtabs", "badgetab", "attachmeta", "focuswindow", "maximizewindow", "minimizewindow", "restorewindow", "incognitowindow", "asksubmit", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword"]);
982
+ 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"]);
983
+ var valueactions = /* @__PURE__ */ new Set(["presskey", "drag", "drop", "upload", "readattribute", "removeattribute", "waittext", "evaluate", "zoomset", "tabactivate", "tabclose", "tabreload", "windowclose", "windowresize", "tabcreate", "windowcreate", "downloadfile", "typetime", "appendtext", "setvalue", "typeedit", "keyhold", "keyrelease", "chooseradio", "setslider", "setdate", "setcolor", "followlink", "setfragment", "handleauth", "navintent", "openclipboard", "checksafe", "reopentab", "spanav", "duplicatetab", "pintab", "mutetab", "movetab", "movetabwindow", "searchtabs", "badgetab", "attachmeta", "focuswindow", "maximizewindow", "minimizewindow", "restorewindow", "incognitowindow", "asksubmit", "selectchain", "picktypeahead", "pickdate", "attachfile", "fillcode", "consentpassword", "pausedownload", "resumedownload", "verifydownload", "writeclipboard", "quarantinedownload", "scanvirus"]);
635
984
  var tabscommandactions = /* @__PURE__ */ new Set(["querytabs", "duplicatetab", "closepattern", "pintab", "mutetab", "movetab", "movetabwindow", "grouptabs", "colorgroup", "collapsegroup", "discardtab", "reloadtabs", "zoomin", "zoomout", "watchtab", "switchtab", "maximizewindow", "minimizewindow", "restorewindow", "focuswindow", "scratchwindow", "incognitowindow", "restoretab", "savelayout", "restorelayout", "findclones", "searchtabs", "badgetab", "attachmeta", "listaudio", "reopenrun", "snapshotsession"]);
636
985
  var formactions = /* @__PURE__ */ new Set(["fillform", "filllabel", "fillplaceholder", "detectfields", "generatevalues", "saveprofiles", "asksubmit", "submitform", "readerrors", "retryform", "runwizard", "selectchain", "picktypeahead", "pickdate", "attachfile", "handoffcaptcha", "fillcard", "fillcode", "consentpassword", "skiphoneypot", "detectlogin", "detecttemplate"]);
637
986
  var datasetactions = /* @__PURE__ */ new Set(["scrapetable", "exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "importcsv", "looprows", "transformvalues", "deduperows", "paginateextract", "mergepages", "stamplerows", "previewgrid", "streamdisk", "resumeextract", "logprovenance"]);
638
987
  var exportactions = /* @__PURE__ */ new Set(["exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk"]);
988
+ var filesactions = /* @__PURE__ */ new Set(["batchdownload", "pausedownload", "resumedownload", "verifydownload", "interceptmime", "exportnetlog", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "namecaptures", "cleanupartifacts"]);
989
+ var captureactions = /* @__PURE__ */ new Set(["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"]);
639
990
  var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
640
991
  var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
641
992
  var groupcolors = ["grey", "blue", "red", "yellow", "green", "pink", "purple", "cyan", "orange"];
@@ -689,6 +1040,86 @@ function isdatasetkind(kind) {
689
1040
  function isexportkind(kind) {
690
1041
  return exportactions.has(kind);
691
1042
  }
1043
+ function isfileskind(kind) {
1044
+ return filesactions.has(kind);
1045
+ }
1046
+ function iscapturekind(kind) {
1047
+ return captureactions.has(kind);
1048
+ }
1049
+ function capturegate(session, tabid, origin, now) {
1050
+ if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the capture." };
1051
+ if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot capture." };
1052
+ if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot capture." };
1053
+ if (session.tabid !== tabid) return { allowed: false, reason: `The capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };
1054
+ if (!origingranted(session, origin)) return { allowed: false, reason: `The capture of ${origin} needs the session origin grants first.` };
1055
+ return { allowed: true };
1056
+ }
1057
+ function validatecaptureoptions(value) {
1058
+ if (value === void 0) return { allowed: true };
1059
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "The reviewed capture options must be an object in options.capture." };
1060
+ const options = value;
1061
+ if (options.format !== void 0 && options.format !== "png" && options.format !== "jpeg" && options.format !== "webp") return { allowed: false, reason: "The reviewed capture format must be png, jpeg or webp." };
1062
+ if (options.quality !== void 0 && (typeof options.quality !== "number" || !Number.isFinite(options.quality) || options.quality < 0 || options.quality > 100)) return { allowed: false, reason: "The reviewed capture quality must stay between zero and one hundred; any value in that range is the user choice with no code cap." };
1063
+ if (options.pixelratio !== void 0 && (typeof options.pixelratio !== "number" || !Number.isFinite(options.pixelratio) || options.pixelratio < 1)) return { allowed: false, reason: "The reviewed pixel ratio starts at one and climbs to any user configured ceiling with no code ceiling." };
1064
+ if (options.annotate !== void 0 && typeof options.annotate !== "boolean") return { allowed: false, reason: "The reviewed capture annotation flag must be a boolean." };
1065
+ if (options.exporttarget !== void 0 && options.exporttarget !== "memory" && options.exporttarget !== "download" && options.exporttarget !== "clipboard") return { allowed: false, reason: "The reviewed capture export target must be memory, download or clipboard." };
1066
+ return { allowed: true };
1067
+ }
1068
+ function validateregionrect(value) {
1069
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed regionrect with x, y, width and height in css pixels is required in options." };
1070
+ const rect = value;
1071
+ for (const field of ["x", "y", "width", "height"]) {
1072
+ if (typeof rect[field] !== "number" || !Number.isFinite(rect[field])) return { allowed: false, reason: `The reviewed regionrect needs a numeric ${field} in css pixels.` };
1073
+ }
1074
+ if (rect.x < 0 || rect.y < 0) return { allowed: false, reason: "The reviewed regionrect refuses negative coordinates." };
1075
+ if (rect.width <= 0 || rect.height <= 0) return { allowed: false, reason: "The reviewed regionrect needs positive width and height values." };
1076
+ return { allowed: true };
1077
+ }
1078
+ function validatecapturenaming(value) {
1079
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed capturenaming rule with run, step, sequence and kind flags is required." };
1080
+ const rule = value;
1081
+ const segments = ["run", "step", "sequence", "kind"];
1082
+ for (const key of Object.keys(rule)) {
1083
+ if (!segments.includes(key)) return { allowed: false, reason: `The reviewed capturenaming rule refuses the unknown ${key} segment; only run, step, sequence and kind participate.` };
1084
+ }
1085
+ for (const segment of segments) {
1086
+ if (rule[segment] !== void 0 && typeof rule[segment] !== "boolean") return { allowed: false, reason: `The reviewed capturenaming ${segment} flag must be a boolean.` };
1087
+ }
1088
+ if (!segments.some((segment) => rule[segment] === true)) return { allowed: false, reason: "The reviewed capturenaming rule needs at least one enabled segment of run, step, sequence and kind." };
1089
+ return { allowed: true };
1090
+ }
1091
+ function validatecapturegrammar(step, options) {
1092
+ const kind = step.kind;
1093
+ const optioncheck = validatecaptureoptions(options.capture);
1094
+ if (!optioncheck.allowed) return optioncheck;
1095
+ if (options.settle !== void 0 && (typeof options.settle !== "number" || !Number.isFinite(options.settle) || options.settle < 0)) return { allowed: false, reason: "The reviewed capture settle window must be zero or a positive number of milliseconds." };
1096
+ if (options.overlap !== void 0 && (typeof options.overlap !== "number" || !Number.isInteger(options.overlap) || options.overlap < 0)) return { allowed: false, reason: "The reviewed stitch overlap must be zero or a positive number of rows." };
1097
+ if (options.wait !== void 0 && (typeof options.wait !== "number" || !Number.isFinite(options.wait) || options.wait < 0)) return { allowed: false, reason: "The reviewed capture wait window must be zero or a positive number of milliseconds." };
1098
+ if (options.naming !== void 0) {
1099
+ const namingcheck = validatecapturenaming(options.naming);
1100
+ if (!namingcheck.allowed) return namingcheck;
1101
+ }
1102
+ if (kind === "shotregion") {
1103
+ const rectcheck = validateregionrect(options.regionrect);
1104
+ if (!rectcheck.allowed) return rectcheck;
1105
+ if (options.reviewed !== true) return { allowed: false, reason: "Every reviewed regionrect needs the explicit reviewed flag before shotregion runs." };
1106
+ if (options.container !== void 0 && !isnonempty(options.container)) return { allowed: false, reason: "The reviewed scrollable container selector must be a non-empty string." };
1107
+ if (options.steps !== void 0 && (typeof options.steps !== "number" || !Number.isInteger(options.steps) || options.steps < 1)) return { allowed: false, reason: "The reviewed container scroll steps must be a positive integer with no code ceiling." };
1108
+ }
1109
+ if (kind === "contactsheet") {
1110
+ const elements = options.elements;
1111
+ if (!Array.isArray(elements) || elements.length === 0 || !elements.every((item) => isnonempty(item))) return { allowed: false, reason: "A reviewed non-empty list of element selectors is required in options for the contact sheet; the cell count stays the user choice." };
1112
+ const layout = options.sheet;
1113
+ if (layout !== void 0) {
1114
+ if (!layout || typeof layout !== "object" || Array.isArray(layout)) return { allowed: false, reason: "The reviewed sheetlayout must be an object with cellsize, columns and label." };
1115
+ const sheet = layout;
1116
+ if (typeof sheet.cellsize !== "number" || !Number.isFinite(sheet.cellsize) || sheet.cellsize <= 0) return { allowed: false, reason: "The reviewed contact sheet cell size must be a positive number of pixels." };
1117
+ if (typeof sheet.columns !== "number" || !Number.isInteger(sheet.columns) || sheet.columns < 1) return { allowed: false, reason: "The reviewed contact sheet column count must be a positive integer with no code ceiling." };
1118
+ if (sheet.label !== void 0 && sheet.label !== "none" && sheet.label !== "index" && sheet.label !== "selector" && sheet.label !== "both") return { allowed: false, reason: "The reviewed contact sheet label style must be none, index, selector or both." };
1119
+ }
1120
+ }
1121
+ return { allowed: true };
1122
+ }
692
1123
  function exportgranted(session, origin) {
693
1124
  if (!origingranted(session, origin)) return { allowed: false, reason: `The export of extracted data from ${origin} needs the session origin grants before it leaves local memory.` };
694
1125
  return { allowed: true };
@@ -873,6 +1304,81 @@ function validatedatagrammar(step, options, origin) {
873
1304
  if (kind === "logprovenance" && !isnonempty(options.artifact)) return { allowed: false, reason: "A reviewed artifact id or name is required in options." };
874
1305
  return { allowed: true };
875
1306
  }
1307
+ function validatedownloadspec(value) {
1308
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed downloadspec with a url list is required in options." };
1309
+ const spec = value;
1310
+ if (!Array.isArray(spec.urls) || spec.urls.length === 0 || !spec.urls.every((url) => ishttpsurl(url))) return { allowed: false, reason: "The reviewed downloadspec needs a non-empty list of HTTPS urls." };
1311
+ if (spec.filename !== void 0 && !isnonempty(spec.filename)) return { allowed: false, reason: "The reviewed downloadspec filename rule must be a non-empty string." };
1312
+ if (spec.complete !== void 0 && spec.complete !== "size" && spec.complete !== "checksum") return { allowed: false, reason: "The reviewed downloadspec completion criterion must be size or checksum." };
1313
+ return { allowed: true };
1314
+ }
1315
+ function validatemimefilter(value) {
1316
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed mimefilter with include and exclude patterns is required in options." };
1317
+ const filter = value;
1318
+ if (!Array.isArray(filter.include) || filter.include.length === 0 || !filter.include.every((pattern) => isnonempty(pattern))) return { allowed: false, reason: "The reviewed mimefilter needs a non-empty list of include patterns." };
1319
+ if (filter.exclude !== void 0 && (!Array.isArray(filter.exclude) || !filter.exclude.every((pattern) => isnonempty(pattern)))) return { allowed: false, reason: "The reviewed mimefilter exclude patterns must be a list of non-empty strings." };
1320
+ if (filter.default !== "deny" && filter.default !== "allow") return { allowed: false, reason: "The reviewed mimefilter needs the deny or allow default for unlisted mime types." };
1321
+ return { allowed: true };
1322
+ }
1323
+ function validatecleanuprule(value) {
1324
+ if (!value || typeof value !== "object" || Array.isArray(value)) return { allowed: false, reason: "A reviewed cleanuprule with an age, a kind and a keep policy is required." };
1325
+ const rule = value;
1326
+ if (typeof rule.age !== "number" || !Number.isFinite(rule.age) || rule.age <= 0) return { allowed: false, reason: "The reviewed cleanup age window must be a positive number of milliseconds with no code ceiling." };
1327
+ if (!isnonempty(rule.kind)) return { allowed: false, reason: "The reviewed cleanup rule needs a non-empty artifact kind, or any to match every kind." };
1328
+ if (rule.keep !== "none" && rule.keep !== "latest" && rule.keep !== "all") return { allowed: false, reason: "The reviewed cleanup keep policy must be none, latest or all." };
1329
+ return { allowed: true };
1330
+ }
1331
+ function validatefilesgrammar(step, options) {
1332
+ const kind = step.kind;
1333
+ if (kind === "batchdownload") {
1334
+ const speccheck = validatedownloadspec(options.downloadspec);
1335
+ if (!speccheck.allowed) return speccheck;
1336
+ if (options.concurrent !== void 0 && (typeof options.concurrent !== "number" || !Number.isInteger(options.concurrent) || options.concurrent < 1)) return { allowed: false, reason: "The reviewed concurrent download window must be a positive integer with no code ceiling." };
1337
+ }
1338
+ if (kind === "pausedownload" || kind === "resumedownload" || kind === "verifydownload" || kind === "quarantinedownload" || kind === "scanvirus") {
1339
+ if (!isnonempty(step.value)) return { allowed: false, reason: "A reviewed download or quarantine reference is required." };
1340
+ if (kind === "verifydownload") {
1341
+ if (options.checksum !== void 0 && !isnonempty(options.checksum)) return { allowed: false, reason: "The reviewed expected checksum must be a non-empty string." };
1342
+ if (options.bytes !== void 0 && (typeof options.bytes !== "number" || !Number.isFinite(options.bytes) || options.bytes < 0)) return { allowed: false, reason: "The reviewed expected size must be zero or a positive number of bytes." };
1343
+ }
1344
+ if (kind === "scanvirus" && options.scanner !== void 0 && !isnonempty(options.scanner)) return { allowed: false, reason: "The reviewed scanner name must be a non-empty string." };
1345
+ if (kind === "quarantinedownload" && options.reason !== void 0 && !isnonempty(options.reason)) return { allowed: false, reason: "The reviewed quarantine reason must be a non-empty string." };
1346
+ }
1347
+ if (kind === "interceptmime") {
1348
+ const filtercheck = validatemimefilter(options.mimefilter);
1349
+ if (!filtercheck.allowed) return filtercheck;
1350
+ }
1351
+ if (kind === "readclipboard") {
1352
+ if (!isnonempty(options.consentref)) return { allowed: false, reason: "A clipboard read requires a reviewed consent ref of an approved consent prompt in options." };
1353
+ if (options.prompt !== void 0 && !isnonempty(options.prompt)) return { allowed: false, reason: "The reviewed clipboard consent prompt must be a non-empty string." };
1354
+ }
1355
+ if (kind === "exportnetlog" && options.stepid !== void 0 && !isnonempty(options.stepid)) return { allowed: false, reason: "The reviewed netlog step filter must be a non-empty step id." };
1356
+ if (kind === "namecaptures") {
1357
+ if (!isnonempty(options.task)) return { allowed: false, reason: "A reviewed task id is required in options for capture naming." };
1358
+ if (options.steps !== void 0 && (!Array.isArray(options.steps) || options.steps.length === 0 || !options.steps.every((item) => isnonempty(item)))) return { allowed: false, reason: "The reviewed capture steps must be a non-empty list of step ids when present." };
1359
+ if (options.extension !== void 0 && !isnonempty(options.extension)) return { allowed: false, reason: "The reviewed capture extension must be a non-empty string." };
1360
+ }
1361
+ if (kind === "cleanupartifacts" && options.rules !== void 0) {
1362
+ const rules = options.rules;
1363
+ if (!Array.isArray(rules) || rules.length === 0) return { allowed: false, reason: "The reviewed cleanup rules must be a non-empty list when present." };
1364
+ for (const item of rules) {
1365
+ const rulecheck = validatecleanuprule(item);
1366
+ if (!rulecheck.allowed) return rulecheck;
1367
+ }
1368
+ }
1369
+ return { allowed: true };
1370
+ }
1371
+ function clipboardconsentgranted(step) {
1372
+ let options = {};
1373
+ try {
1374
+ options = parseoptions(step);
1375
+ } catch {
1376
+ options = {};
1377
+ }
1378
+ const consentref = options.consentref;
1379
+ if (typeof consentref !== "string" || !consentref.trim()) return { allowed: false, reason: "A clipboard read requires a reviewed consent ref in options." };
1380
+ return { allowed: true };
1381
+ }
876
1382
  function submitreviewgranted(steps, submitid) {
877
1383
  const position = steps.findIndex((candidate) => candidate.id === submitid);
878
1384
  const asked = steps.some((candidate, index) => candidate.kind === "asksubmit" && (position === -1 || index < position));
@@ -1395,6 +1901,14 @@ function validatestep(step, origin) {
1395
1901
  const datacheck = validatedatagrammar(step, options, origin);
1396
1902
  if (!datacheck.allowed) return datacheck;
1397
1903
  }
1904
+ if (isfileskind(step.kind)) {
1905
+ const filescheck = validatefilesgrammar(step, options);
1906
+ if (!filescheck.allowed) return filescheck;
1907
+ }
1908
+ if (iscapturekind(step.kind)) {
1909
+ const capturecheck = validatecapturegrammar(step, options);
1910
+ if (!capturecheck.allowed) return capturecheck;
1911
+ }
1398
1912
  if (step.kind === "tabcreate") {
1399
1913
  if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
1400
1914
  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." };
@@ -1449,6 +1963,23 @@ function canexecute(input) {
1449
1963
  const consentgate = passwordconsentgranted(input.step);
1450
1964
  if (!consentgate.allowed) return consentgate;
1451
1965
  }
1966
+ if (input.step.kind === "readclipboard") {
1967
+ const clipgate = clipboardconsentgranted(input.step);
1968
+ if (!clipgate.allowed) return clipgate;
1969
+ }
1970
+ if (input.step.kind === "interceptmime" && !origingranted(input.session, input.origin)) return { allowed: false, reason: "The download interception is outside the session origin grants." };
1971
+ if (iscapturekind(input.step.kind)) {
1972
+ const capturegatecheck = capturegate(input.session, input.tabid, input.origin, now);
1973
+ if (!capturegatecheck.allowed) return capturegatecheck;
1974
+ let captureoptions = {};
1975
+ try {
1976
+ captureoptions = parseoptions(input.step);
1977
+ } catch {
1978
+ captureoptions = {};
1979
+ }
1980
+ const target = captureoptions.capture?.exporttarget;
1981
+ if (target !== void 0 && target !== "memory" && target !== "download" && target !== "clipboard") return { allowed: false, reason: "The capture export target must be memory, download or clipboard." };
1982
+ }
1452
1983
  if (input.step.kind === "openlink" || input.step.kind === "openprivate" || input.step.kind === "batchopen" || input.step.kind === "prefetch" || input.step.kind === "deeplink" || input.step.kind === "reopentab") {
1453
1984
  let options = {};
1454
1985
  try {
@@ -1470,7 +2001,7 @@ function canexecute(input) {
1470
2001
  }
1471
2002
 
1472
2003
  // version.ts
1473
- var packageversion = "1.1.38";
2004
+ var packageversion = "1.1.40";
1474
2005
 
1475
2006
  // types.ts
1476
2007
  var protocolversion = packageversion;
@@ -1534,7 +2065,7 @@ function requestbody(input) {
1534
2065
  return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
1535
2066
  }
1536
2067
  function outcomeresponse(input) {
1537
- return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, outcome: input.outcome, ...input.resolvedtarget ? { resolvedtarget: input.resolvedtarget } : {} });
2068
+ 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 } : {} });
1538
2069
  }
1539
2070
  function mapresponse(input) {
1540
2071
  return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
@@ -1602,14 +2133,45 @@ function provenancereport(input) {
1602
2133
  function transformgrammar(rules) {
1603
2134
  return JSON.stringify({ rules: rules.map((rule) => ({ expression: rule.expression, sources: rule.sources, target: rule.target })) });
1604
2135
  }
2136
+ function downloadreport(input) {
2137
+ return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, downloads: input.downloads });
2138
+ }
2139
+ function netlogreport(input) {
2140
+ return { version: protocolversion, records: input.records };
2141
+ }
2142
+ function quarantinereport(input) {
2143
+ return { version: protocolversion, entries: input.entries };
2144
+ }
2145
+ function capturereport(input) {
2146
+ return { version: protocolversion, records: input.records, pairs: input.pairs };
2147
+ }
1605
2148
  export {
2149
+ annotationplanof,
2150
+ blendrows,
2151
+ buildname,
2152
+ buildsheet,
2153
+ buildstitchplan,
1606
2154
  canexecute,
2155
+ captureelement,
2156
+ captureformats,
2157
+ capturekinds,
2158
+ captureoptionsof,
2159
+ captureregion,
2160
+ capturereport,
2161
+ capturestates,
2162
+ capturestitched,
2163
+ capturetargets,
2164
+ capturevisible,
2165
+ croprect,
2166
+ crossesviewport,
1607
2167
  datasetresponse,
1608
2168
  actionrisk as deriveactionrisk,
1609
2169
  diffresponse,
2170
+ downloadreport,
1610
2171
  errorreportresponse,
1611
2172
  eventresponse,
1612
2173
  extractionreport,
2174
+ fixedheadermatch,
1613
2175
  formreportresponse,
1614
2176
  generatedvalueallowed,
1615
2177
  heldkeysreport,
@@ -1619,19 +2181,25 @@ export {
1619
2181
  layoutreport,
1620
2182
  mapresponse,
1621
2183
  navstateresponse,
2184
+ netlogreport,
1622
2185
  normalizeendpoint,
1623
2186
  observationmodeof,
1624
2187
  observationresponse,
1625
2188
  outcomeresponse,
2189
+ pairstates,
1626
2190
  parseproposal,
1627
2191
  passwordconsentgranted,
1628
2192
  profilegrantgranted,
1629
2193
  protocolversion,
1630
2194
  provenancereport,
2195
+ quarantinereport,
1631
2196
  randomid,
2197
+ regionsteps,
1632
2198
  requestbody,
1633
2199
  resolutionverdict,
1634
2200
  safetyresponse,
2201
+ scaledrect,
2202
+ seamweights,
1635
2203
  selectorresponse,
1636
2204
  sessionmemory,
1637
2205
  signalsreport,