@wenathlan/extension 1.1.40 → 1.1.41

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
@@ -196,6 +196,308 @@ function annotationplanof(input) {
196
196
  return plan;
197
197
  }
198
198
 
199
+ // media.ts
200
+ var mediakinds = ["capturepdf", "recordscreen", "captureaudio", "captureframe", "downloadimages", "shotcanvas", "probestream", "readmedia", "readassets", "timelapse", "convertimage", "makethumbs"];
201
+ var defaultpaperwidth = 8.5;
202
+ var defaultpaperheight = 11;
203
+ var defaultmargins = { top: 0.4, right: 0.4, bottom: 0.4, left: 0.4 };
204
+ var pdfpointsperinch = 72;
205
+ var basefontsize = 11;
206
+ function pdfoptionsof(value) {
207
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
208
+ const options = value;
209
+ const normalized = {};
210
+ if (typeof options.paperwidth === "number" && Number.isFinite(options.paperwidth)) normalized.paperwidth = options.paperwidth;
211
+ if (typeof options.paperheight === "number" && Number.isFinite(options.paperheight)) normalized.paperheight = options.paperheight;
212
+ if (options.margins && typeof options.margins === "object" && !Array.isArray(options.margins)) {
213
+ const margins = options.margins;
214
+ const top = typeof margins.top === "number" ? margins.top : defaultmargins.top;
215
+ const right = typeof margins.right === "number" ? margins.right : defaultmargins.right;
216
+ const bottom = typeof margins.bottom === "number" ? margins.bottom : defaultmargins.bottom;
217
+ const left = typeof margins.left === "number" ? margins.left : defaultmargins.left;
218
+ normalized.margins = { top, right, bottom, left };
219
+ }
220
+ if (typeof options.scale === "number" && Number.isFinite(options.scale)) normalized.scale = options.scale;
221
+ if (typeof options.landscape === "boolean") normalized.landscape = options.landscape;
222
+ if (typeof options.paginate === "boolean") normalized.paginate = options.paginate;
223
+ return normalized;
224
+ }
225
+ function pdfpagesize(options) {
226
+ const width = (options.paperwidth ?? defaultpaperwidth) * pdfpointsperinch;
227
+ const height = (options.paperheight ?? defaultpaperheight) * pdfpointsperinch;
228
+ return options.landscape === true ? { width: height, height: width } : { width, height };
229
+ }
230
+ function pdfmargins(options) {
231
+ const margins = options.margins ?? defaultmargins;
232
+ return { top: margins.top * pdfpointsperinch, right: margins.right * pdfpointsperinch, bottom: margins.bottom * pdfpointsperinch, left: margins.left * pdfpointsperinch };
233
+ }
234
+ function pdffontsize(options) {
235
+ return basefontsize * (options.scale ?? 1);
236
+ }
237
+ function pdftextlayout(text2, options) {
238
+ const size = pdfpagesize(options);
239
+ const margins = pdfmargins(options);
240
+ const fontsize = pdffontsize(options);
241
+ const leading = fontsize * 1.35;
242
+ const linesperpage = Math.max(1, Math.floor((size.height - margins.top - margins.bottom) / leading));
243
+ const columns = Math.max(1, Math.floor((size.width - margins.left - margins.right) / (fontsize * 0.5)));
244
+ const wrapped = [];
245
+ for (const paragraph of text2.split(/\r?\n/)) {
246
+ let line = "";
247
+ for (const word of paragraph.split(/\s+/).filter(Boolean)) {
248
+ const candidate = line ? `${line} ${word}` : word;
249
+ if (candidate.length <= columns) {
250
+ line = candidate;
251
+ continue;
252
+ }
253
+ if (line) wrapped.push(line);
254
+ if (word.length <= columns) {
255
+ line = word;
256
+ continue;
257
+ }
258
+ for (let index = 0; index < word.length; index += columns) wrapped.push(word.slice(index, index + columns));
259
+ line = "";
260
+ }
261
+ wrapped.push(line);
262
+ if (wrapped.length >= linesperpage) break;
263
+ }
264
+ return wrapped.slice(0, linesperpage);
265
+ }
266
+ function pdfsegments(scrollheight, viewportheight, breaks) {
267
+ if (scrollheight <= 0) return [];
268
+ const step = viewportheight > 0 ? viewportheight : scrollheight;
269
+ const cuts = [0, ...breaks.filter((top) => Number.isFinite(top) && top > 0 && top < scrollheight).map((top) => Math.round(top))].filter((top, index2, list) => list.indexOf(top) === index2).sort((left, right) => left - right);
270
+ const segments = [];
271
+ let index = 0;
272
+ let cursor = 0;
273
+ while (cursor < scrollheight) {
274
+ while (index < cuts.length && (cuts[index] ?? 0) <= cursor) index += 1;
275
+ const nextcut = index < cuts.length ? cuts[index] : void 0;
276
+ const next = nextcut !== void 0 ? Math.min(nextcut, scrollheight) : Math.min(cursor + step, scrollheight);
277
+ if (next <= cursor) break;
278
+ segments.push({ top: cursor, height: next - cursor });
279
+ cursor = next;
280
+ }
281
+ return segments.length > 0 ? segments : [{ top: 0, height: scrollheight }];
282
+ }
283
+ function pdfescape(text2) {
284
+ let escaped = "";
285
+ for (const character of text2) {
286
+ const code = character.charCodeAt(0);
287
+ if (character === "(" || character === ")" || character === "\\") escaped += `\\${character}`;
288
+ else if (code >= 32 && code <= 255) escaped += character;
289
+ else escaped += "?";
290
+ }
291
+ return escaped;
292
+ }
293
+ function buildpdf(pages, options) {
294
+ const size = pdfpagesize(options);
295
+ const margins = pdfmargins(options);
296
+ const fontsize = pdffontsize(options);
297
+ const leading = fontsize * 1.35;
298
+ const laidout = (pages.length > 0 ? pages : [""]).map((text2) => pdftextlayout(text2, options));
299
+ const objects = [];
300
+ const kids = laidout.map((_, index) => `${4 + index * 2} 0 R`).join(" ");
301
+ objects.push(`<< /Type /Catalog /Pages 2 0 R >>`);
302
+ objects.push(`<< /Type /Pages /Kids [${kids}] /Count ${laidout.length} >>`);
303
+ objects.push(`<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>`);
304
+ for (let pageindex = 0; pageindex < laidout.length; pageindex += 1) {
305
+ const lines = laidout[pageindex] ?? [];
306
+ const operators = ["BT", `/F1 ${fontsize} Tf`, `${leading.toFixed(2)} TL`, `${margins.left.toFixed(2)} ${(size.height - margins.top - fontsize).toFixed(2)} Td`];
307
+ for (let lineindex = 0; lineindex < lines.length; lineindex += 1) {
308
+ if (lineindex > 0) operators.push("T*");
309
+ operators.push(`(${pdfescape(lines[lineindex] ?? "")}) Tj`);
310
+ }
311
+ operators.push("ET");
312
+ const content = operators.join("\n");
313
+ objects.push(`<< /Type /Page /Parent 2 0 R /MediaBox [0 0 ${size.width.toFixed(2)} ${size.height.toFixed(2)}] /Resources << /Font << /F1 3 0 R >> >> /Contents ${5 + pageindex * 2} 0 R >>`);
314
+ objects.push(`<< /Length ${content.length} >>
315
+ stream
316
+ ${content}
317
+ endstream`);
318
+ }
319
+ let document = "%PDF-1.4\n";
320
+ const offsets = [];
321
+ for (let index = 0; index < objects.length; index += 1) {
322
+ offsets.push(document.length);
323
+ document += `${index + 1} 0 obj
324
+ ${objects[index]}
325
+ endobj
326
+ `;
327
+ }
328
+ const xrefstart = document.length;
329
+ document += `xref
330
+ 0 ${objects.length + 1}
331
+ 0000000000 65535 f
332
+ `;
333
+ for (const offset of offsets) document += `${String(offset).padStart(10, "0")} 00000 n
334
+ `;
335
+ document += `trailer
336
+ << /Size ${objects.length + 1} /Root 1 0 R >>
337
+ startxref
338
+ ${xrefstart}
339
+ %%EOF
340
+ `;
341
+ return { document, bytes: document.length, pages: laidout.length, pagewidth: Math.round(size.width), pageheight: Math.round(size.height) };
342
+ }
343
+ function recordingoptionsof(value) {
344
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
345
+ const options = value;
346
+ const normalized = {};
347
+ if (options.scope === "tab" || options.scope === "run") normalized.scope = options.scope;
348
+ if (typeof options.fps === "number" && Number.isFinite(options.fps)) normalized.fps = options.fps;
349
+ if (typeof options.bitrate === "number" && Number.isFinite(options.bitrate)) normalized.bitrate = options.bitrate;
350
+ if (typeof options.audio === "boolean") normalized.audio = options.audio;
351
+ return normalized;
352
+ }
353
+ function newrecording(input) {
354
+ return {
355
+ id: input.id,
356
+ runid: input.runid,
357
+ stepid: input.stepid,
358
+ tabid: input.tabid,
359
+ kind: input.kind,
360
+ scope: input.options.scope ?? "tab",
361
+ format: input.kind === "audio" ? "evidence" : "frames",
362
+ startedat: input.at,
363
+ at: input.at,
364
+ ...input.options.fps !== void 0 ? { fps: input.options.fps } : {},
365
+ ...input.options.bitrate !== void 0 ? { bitrate: input.options.bitrate } : {},
366
+ ...input.options.audio !== void 0 ? { audio: input.options.audio } : {},
367
+ frames: []
368
+ };
369
+ }
370
+ function finishrecording(record2, endat) {
371
+ return { ...record2, endedat: endat, duration: Math.max(0, endat - record2.startedat) };
372
+ }
373
+ function frameinterval(fps) {
374
+ if (!Number.isFinite(fps) || fps <= 0) return 1e3;
375
+ return Math.max(1, Math.round(1e3 / fps));
376
+ }
377
+ function imagefilterof(value) {
378
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
379
+ const options = value;
380
+ const normalized = {};
381
+ if (typeof options.selector === "string" && options.selector.trim()) normalized.selector = options.selector.trim();
382
+ if (typeof options.minwidth === "number" && Number.isFinite(options.minwidth)) normalized.minwidth = options.minwidth;
383
+ if (typeof options.minheight === "number" && Number.isFinite(options.minheight)) normalized.minheight = options.minheight;
384
+ if (Array.isArray(options.formats) && options.formats.every((item) => typeof item === "string" && item.trim())) normalized.formats = options.formats;
385
+ return normalized;
386
+ }
387
+ function imagematches(image, filter) {
388
+ if (filter.minwidth !== void 0 && image.width < filter.minwidth) return false;
389
+ if (filter.minheight !== void 0 && image.height < filter.minheight) return false;
390
+ if (filter.formats !== void 0 && filter.formats.length > 0) {
391
+ const mime = image.mime.toLowerCase();
392
+ const matches = filter.formats.some((format) => {
393
+ const wanted = format.toLowerCase().trim();
394
+ return mime === wanted || mime === `image/${wanted}` || mime.endsWith(`/${wanted}`);
395
+ });
396
+ if (!matches) return false;
397
+ }
398
+ return true;
399
+ }
400
+ function dedupeimages(images) {
401
+ const seen = /* @__PURE__ */ new Set();
402
+ const unique = [];
403
+ for (const image of images) {
404
+ if (seen.has(image.url)) continue;
405
+ seen.add(image.url);
406
+ unique.push(image);
407
+ }
408
+ return unique;
409
+ }
410
+ function imagenames(rule, run, step, count, extension) {
411
+ const names = [];
412
+ for (let index = 1; index <= Math.max(0, Math.round(count)); index += 1) names.push(buildname(rule, { run, step, sequence: index, kind: "image" }, extension));
413
+ return names;
414
+ }
415
+ function lapseplanof(value) {
416
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
417
+ const options = value;
418
+ if (typeof options.interval !== "number" || !Number.isFinite(options.interval)) return void 0;
419
+ if (typeof options.duration !== "number" || !Number.isFinite(options.duration)) return void 0;
420
+ const format = options.format === "jpeg" || options.format === "webp" ? options.format : "png";
421
+ return { interval: options.interval, duration: options.duration, format };
422
+ }
423
+ function lapseframes(plan) {
424
+ if (!(plan.interval > 0) || !(plan.duration > 0)) return [];
425
+ const frames = [];
426
+ for (let time = 0; time < plan.duration; time += plan.interval) frames.push(Math.round(time));
427
+ return frames;
428
+ }
429
+ function convertdirectiveof(value) {
430
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
431
+ const options = value;
432
+ if (options.target !== "png" && options.target !== "jpeg" && options.target !== "webp") return void 0;
433
+ const normalized = { target: options.target };
434
+ if (options.source === "png" || options.source === "jpeg" || options.source === "webp") normalized.source = options.source;
435
+ if (typeof options.quality === "number" && Number.isFinite(options.quality)) normalized.quality = options.quality;
436
+ return normalized;
437
+ }
438
+ function thumbdirectiveof(value) {
439
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
440
+ const options = value;
441
+ if (typeof options.size !== "number" || !Number.isFinite(options.size) || options.size <= 0) return void 0;
442
+ if (options.fit !== "cover" && options.fit !== "contain") return void 0;
443
+ if (typeof options.suffix !== "string" || !options.suffix.trim()) return void 0;
444
+ return { size: options.size, fit: options.fit, suffix: options.suffix.trim() };
445
+ }
446
+ function thumbgeometry(source, directive) {
447
+ const size = Math.max(1, Math.round(directive.size));
448
+ if (directive.fit === "contain") {
449
+ const scale2 = Math.min(size / Math.max(1, source.width), size / Math.max(1, source.height));
450
+ const dw = Math.max(1, Math.round(source.width * scale2));
451
+ const dh = Math.max(1, Math.round(source.height * scale2));
452
+ return { sx: 0, sy: 0, sw: source.width, sh: source.height, dx: Math.floor((size - dw) / 2), dy: Math.floor((size - dh) / 2), dw, dh, width: size, height: size };
453
+ }
454
+ const scale = Math.max(size / Math.max(1, source.width), size / Math.max(1, source.height));
455
+ const sw = Math.min(source.width, Math.round(size / scale));
456
+ const sh = Math.min(source.height, Math.round(size / scale));
457
+ return { sx: Math.floor((source.width - sw) / 2), sy: Math.floor((source.height - sh) / 2), sw, sh, dx: 0, dy: 0, dw: size, dh: size, width: size, height: size };
458
+ }
459
+ function mediaentries(raw) {
460
+ return raw.map((entry) => ({
461
+ url: typeof entry.url === "string" ? entry.url : "",
462
+ mime: typeof entry.mime === "string" ? entry.mime : "",
463
+ duration: typeof entry.duration === "number" && Number.isFinite(entry.duration) ? entry.duration : 0,
464
+ width: typeof entry.width === "number" && Number.isFinite(entry.width) ? Math.round(entry.width) : 0,
465
+ height: typeof entry.height === "number" && Number.isFinite(entry.height) ? Math.round(entry.height) : 0,
466
+ codecs: typeof entry.codecs === "string" ? entry.codecs : "",
467
+ tracks: Array.isArray(entry.tracks) ? entry.tracks.filter((item) => typeof item === "string") : []
468
+ }));
469
+ }
470
+ function assetentries(raw) {
471
+ return raw.map((entry) => ({
472
+ kind: entry.kind === "logo" ? "logo" : "favicon",
473
+ url: typeof entry.url === "string" ? entry.url : "",
474
+ bytes: typeof entry.bytes === "number" && Number.isFinite(entry.bytes) ? entry.bytes : 0,
475
+ ...typeof entry.sizes === "string" && entry.sizes.trim() ? { sizes: entry.sizes.trim() } : {}
476
+ }));
477
+ }
478
+ function streamsummaries(raw) {
479
+ return raw.map((entry) => {
480
+ const tracks = Array.isArray(entry.tracks) ? entry.tracks : [];
481
+ return {
482
+ kind: typeof entry.kind === "string" ? entry.kind : "stream",
483
+ tracks: tracks.length,
484
+ label: typeof entry.label === "string" ? entry.label : "",
485
+ live: entry.live === true,
486
+ detail: tracks.map((track) => {
487
+ const item = track;
488
+ return {
489
+ kind: typeof item.kind === "string" ? item.kind : "",
490
+ label: typeof item.label === "string" ? item.label : "",
491
+ ...typeof item.width === "number" && Number.isFinite(item.width) ? { width: Math.round(item.width) } : {},
492
+ ...typeof item.height === "number" && Number.isFinite(item.height) ? { height: Math.round(item.height) } : {},
493
+ ...typeof item.framerate === "number" && Number.isFinite(item.framerate) ? { framerate: item.framerate } : {},
494
+ state: typeof item.state === "string" ? item.state : ""
495
+ };
496
+ })
497
+ };
498
+ });
499
+ }
500
+
199
501
  // memory.ts
200
502
  var sessionmemory = class {
201
503
  constructor(adapter) {
@@ -963,7 +1265,78 @@ var sessionmemory = class {
963
1265
  for (const capture of await this.getcaptures()) runs.set(capture.id, capture.runid);
964
1266
  return records.filter((item) => runs.get(item.beforeid) === runid);
965
1267
  }
1268
+ /** Stores one media record of the 1.1.41 family with its bytes and step linkage, replacing the previous record of that id; the user configured media retention window expires the oldest bytes while the metadata and the recording index always survive. */
1269
+ async addmedia(record2) {
1270
+ const records = await this.getmediarecords();
1271
+ const retention = (await this.getsettings())?.mediaretention;
1272
+ const combined = [record2, ...records.filter((item) => item.id !== record2.id)];
1273
+ const stored = retention === void 0 ? combined : combined.map((item, index) => index < retention ? item : expiremediabytes(item));
1274
+ await this.adapter.set("media", stored);
1275
+ }
1276
+ /** Returns every stored media record, newest first. */
1277
+ async getmediarecords() {
1278
+ return await this.adapter.get("media") ?? [];
1279
+ }
1280
+ /** Returns the media records filtered by run and kind; an absent filter returns every record. */
1281
+ async listmedia(filter) {
1282
+ const records = await this.getmediarecords();
1283
+ return records.filter((item) => (filter.runid === void 0 || item.runid === filter.runid) && (filter.kind === void 0 || mediakindof(item) === filter.kind));
1284
+ }
1285
+ /** Returns one media record by its id. */
1286
+ async getmediarecord(id) {
1287
+ return (await this.getmediarecords()).find((item) => item.id === id);
1288
+ }
1289
+ /** Returns one recording with its file reference and frame index by its id. */
1290
+ async getrecording(id) {
1291
+ const found = await this.getmediarecord(id);
1292
+ return found !== void 0 && "startedat" in found ? found : void 0;
1293
+ }
1294
+ /** Removes one media record by its id; the audit trail keeps its outcome evidence. */
1295
+ async removemedia(id) {
1296
+ await this.adapter.set("media", (await this.getmediarecords()).filter((item) => item.id !== id));
1297
+ }
1298
+ /** Stores one observed image batch of a downloadimages step, replacing the previous batch of that id. */
1299
+ async addimagebatch(batch) {
1300
+ const records = await this.adapter.get("imagebatches") ?? [];
1301
+ await this.adapter.set("imagebatches", [batch, ...records.filter((item) => item.id !== batch.id)]);
1302
+ }
1303
+ /** Returns every observed image batch with its filter match counts, newest first. */
1304
+ async getimagebatches() {
1305
+ return await this.adapter.get("imagebatches") ?? [];
1306
+ }
1307
+ /** Stores one recording consent decision of an origin, replacing the previous record of that id. */
1308
+ async setrecordingconsent(record2) {
1309
+ const records = (await this.adapter.get("recordingconsents") ?? []).filter((item) => item.id !== record2.id);
1310
+ await this.adapter.set("recordingconsents", [record2, ...records]);
1311
+ }
1312
+ /** Returns every recording consent decision with its prompt and origin, newest first. */
1313
+ async getrecordingconsents() {
1314
+ return await this.adapter.get("recordingconsents") ?? [];
1315
+ }
966
1316
  };
1317
+ function mediakindof(record2) {
1318
+ if ("pages" in record2) return "pdf";
1319
+ if ("startedat" in record2) return "recording";
1320
+ if ("timestamp" in record2) return "frame";
1321
+ if ("context" in record2) return "canvas";
1322
+ if ("tracks" in record2) return "stream";
1323
+ return "asset";
1324
+ }
1325
+ function expiremediabytes(record2) {
1326
+ if ("dataurl" in record2) {
1327
+ const source = record2;
1328
+ const copy = { ...source };
1329
+ delete copy.dataurl;
1330
+ return { ...copy, bytesexpired: true };
1331
+ }
1332
+ if ("startedat" in record2) {
1333
+ const source = record2;
1334
+ const copy = { ...source };
1335
+ delete copy.bytes;
1336
+ return { ...copy, bytesexpired: true };
1337
+ }
1338
+ return record2;
1339
+ }
967
1340
  function expirecapturebytes(record2) {
968
1341
  const { bytes, ...metadata } = record2;
969
1342
  void bytes;
@@ -974,12 +1347,12 @@ function randomid() {
974
1347
  }
975
1348
 
976
1349
  // policy.ts
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"]);
1350
+ 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"]);
978
1351
  var interactionactions = /* @__PURE__ */ new Set(["focus", "scroll", "hover", "clickdeep", "rightclick", "doubleclick", "scrollpage", "scrollby", "scrollend", "scrolltop", "fullscreen", "zoomset", "movepointer", "clicktext", "clickaria", "clickname", "expanddetails", "pierceshadow", "retryaction"]);
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"]);
1352
+ 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"]);
980
1353
  var allowedactions = /* @__PURE__ */ new Set([...sensitiveactions, ...interactionactions, ...readactions]);
981
1354
  var watchactions = /* @__PURE__ */ new Set(["watchmutate", "watchbanner", "watchfocus", "watchtab"]);
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"]);
1355
+ 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"]);
983
1356
  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"]);
984
1357
  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"]);
985
1358
  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"]);
@@ -987,6 +1360,7 @@ var datasetactions = /* @__PURE__ */ new Set(["scrapetable", "exportcsv", "expor
987
1360
  var exportactions = /* @__PURE__ */ new Set(["exportcsv", "exportjson", "exportexcel", "copytable", "pushsheets", "streamdisk"]);
988
1361
  var filesactions = /* @__PURE__ */ new Set(["batchdownload", "pausedownload", "resumedownload", "verifydownload", "interceptmime", "exportnetlog", "readclipboard", "writeclipboard", "copyscreen", "quarantinedownload", "scanvirus", "namecaptures", "cleanupartifacts"]);
989
1362
  var captureactions = /* @__PURE__ */ new Set(["shotview", "shotfullpage", "shotelement", "shotregion", "contactsheet"]);
1363
+ var mediaactions = /* @__PURE__ */ new Set(["capturepdf", "recordscreen", "captureaudio", "captureframe", "downloadimages", "shotcanvas", "probestream", "readmedia", "readassets", "timelapse", "convertimage", "makethumbs"]);
990
1364
  var fieldkinds = ["text", "email", "phone", "date", "number", "select", "check", "radio", "file", "password", "card", "code"];
991
1365
  var layoutmutationactions = /* @__PURE__ */ new Set(["grouptabs", "colorgroup", "collapsegroup", "savelayout", "restorelayout"]);
992
1366
  var groupcolors = ["grey", "blue", "red", "yellow", "green", "pink", "purple", "cyan", "orange"];
@@ -1688,6 +2062,140 @@ function validatetabsgrammar(step, options) {
1688
2062
  if (kind === "reopenrun" && !isnonempty(options.run)) return { allowed: false, reason: "A reviewed run id is required in options to reopen its tabs." };
1689
2063
  return { allowed: true };
1690
2064
  }
2065
+ function ismediakind(kind) {
2066
+ return mediaactions.has(kind);
2067
+ }
2068
+ function isrecordingkind(kind) {
2069
+ return kind === "recordscreen" || kind === "captureaudio";
2070
+ }
2071
+ function mediagate(session, tabid, origin, now) {
2072
+ if (!session || session.stoppedat) return { allowed: false, reason: "No active browser session exists for the media capture." };
2073
+ if (session.expiresat <= now) return { allowed: false, reason: "The browser session has expired and cannot capture media." };
2074
+ if (session.pausedat) return { allowed: false, reason: "The browser session is paused and cannot capture media." };
2075
+ if (session.tabid !== tabid) return { allowed: false, reason: `The media capture needs the active tab grant of session tab ${session.tabid} and refuses tab ${tabid}.` };
2076
+ if (!origingranted(session, origin)) return { allowed: false, reason: `The media capture of ${origin} needs the session origin grants first.` };
2077
+ return { allowed: true };
2078
+ }
2079
+ function recordingconsentgranted(step) {
2080
+ let options = {};
2081
+ try {
2082
+ options = parseoptions(step);
2083
+ } catch {
2084
+ options = {};
2085
+ }
2086
+ const consentref = options.consentref;
2087
+ if (typeof consentref !== "string" || !consentref.trim()) return { allowed: false, reason: "A recording of user activity requires a reviewed consent ref in options before it starts." };
2088
+ return { allowed: true };
2089
+ }
2090
+ function lapsebudgetallowed(interval, duration, wait) {
2091
+ if (!(interval > 0)) return { allowed: false, reason: "The reviewed lapse interval must be a positive number of milliseconds." };
2092
+ if (!(duration > 0)) return { allowed: false, reason: "The reviewed lapse duration must be a positive number of milliseconds." };
2093
+ if (wait !== void 0 && !(wait >= 0)) return { allowed: false, reason: "The reviewed wait budget must be zero or a positive number of milliseconds." };
2094
+ if (wait !== void 0 && duration > wait) return { allowed: false, reason: `The lapse duration of ${duration} milliseconds exceeds the reviewed wait budget of ${wait} milliseconds; review a wider budget or a shorter duration.` };
2095
+ return { allowed: true };
2096
+ }
2097
+ function validatemediagrammar(step, options) {
2098
+ const kind = step.kind;
2099
+ if (kind === "capturepdf") {
2100
+ const pdf = options.pdf;
2101
+ if (pdf !== void 0) {
2102
+ if (!pdf || typeof pdf !== "object" || Array.isArray(pdf)) return { allowed: false, reason: "The reviewed pdf options must be an object in options.pdf." };
2103
+ const pdfoptions = pdf;
2104
+ if (pdfoptions.paperwidth !== void 0 && (typeof pdfoptions.paperwidth !== "number" || !Number.isFinite(pdfoptions.paperwidth) || pdfoptions.paperwidth <= 0)) return { allowed: false, reason: "The reviewed pdf paper width must be a positive number of inches with no code cap." };
2105
+ if (pdfoptions.paperheight !== void 0 && (typeof pdfoptions.paperheight !== "number" || !Number.isFinite(pdfoptions.paperheight) || pdfoptions.paperheight <= 0)) return { allowed: false, reason: "The reviewed pdf paper height must be a positive number of inches with no code cap." };
2106
+ if (pdfoptions.margins !== void 0) {
2107
+ const margins = pdfoptions.margins;
2108
+ if (!margins || typeof margins !== "object" || Array.isArray(margins)) return { allowed: false, reason: "The reviewed pdf margins must be an object with top, right, bottom and left inches." };
2109
+ for (const side of ["top", "right", "bottom", "left"]) {
2110
+ const value = margins[side];
2111
+ if (value === void 0) continue;
2112
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) return { allowed: false, reason: `The reviewed pdf ${side} margin must be zero or a positive number of inches; negative margins are refused.` };
2113
+ }
2114
+ }
2115
+ if (pdfoptions.scale !== void 0 && (typeof pdfoptions.scale !== "number" || !Number.isFinite(pdfoptions.scale) || pdfoptions.scale <= 0)) return { allowed: false, reason: "The reviewed pdf scale must be a positive number with no code cap." };
2116
+ if (pdfoptions.landscape !== void 0 && typeof pdfoptions.landscape !== "boolean") return { allowed: false, reason: "The reviewed pdf landscape flag must be a boolean." };
2117
+ if (pdfoptions.paginate !== void 0 && typeof pdfoptions.paginate !== "boolean") return { allowed: false, reason: "The reviewed pdf paginate flag must be a boolean." };
2118
+ }
2119
+ if (options.breakpoints !== void 0 && (!Array.isArray(options.breakpoints) || options.breakpoints.length === 0 || !options.breakpoints.every((item) => isnonempty(item)))) return { allowed: false, reason: "The reviewed pdf break points must be a non-empty list of selectors when present." };
2120
+ if (options.exporttarget !== void 0 && options.exporttarget !== "memory" && options.exporttarget !== "download") return { allowed: false, reason: "The reviewed pdf export target must be memory or download; pdf documents do not route to the clipboard." };
2121
+ if (options.name !== void 0 && !isnonempty(options.name)) return { allowed: false, reason: "The reviewed pdf artifact name must be a non-empty string." };
2122
+ }
2123
+ if (kind === "recordscreen" || kind === "captureaudio") {
2124
+ const recording = options.recording;
2125
+ if (recording !== void 0) {
2126
+ if (!recording || typeof recording !== "object" || Array.isArray(recording)) return { allowed: false, reason: "The reviewed recording options must be an object in options.recording." };
2127
+ const recordoptions = recording;
2128
+ if (recordoptions.scope !== void 0 && recordoptions.scope !== "tab" && recordoptions.scope !== "run") return { allowed: false, reason: "The reviewed recording scope must be tab or run." };
2129
+ if (recordoptions.fps !== void 0 && (typeof recordoptions.fps !== "number" || !Number.isFinite(recordoptions.fps) || recordoptions.fps <= 0)) return { allowed: false, reason: "The reviewed recording fps must be a positive number with no code ceiling." };
2130
+ if (recordoptions.bitrate !== void 0 && (typeof recordoptions.bitrate !== "number" || !Number.isFinite(recordoptions.bitrate) || recordoptions.bitrate <= 0)) return { allowed: false, reason: "The reviewed recording bitrate must be a positive number with no code ceiling." };
2131
+ if (recordoptions.audio !== void 0 && typeof recordoptions.audio !== "boolean") return { allowed: false, reason: "The reviewed recording audio flag must be a boolean." };
2132
+ }
2133
+ if (options.duration !== void 0 && (typeof options.duration !== "number" || !Number.isFinite(options.duration) || options.duration <= 0)) return { allowed: false, reason: "The reviewed recording duration must be a positive number of milliseconds with no code ceiling." };
2134
+ const consent = recordingconsentgranted(step);
2135
+ if (!consent.allowed) return consent;
2136
+ }
2137
+ if (kind === "captureframe") {
2138
+ if (options.timestamp !== void 0 && (typeof options.timestamp !== "number" || !Number.isFinite(options.timestamp) || options.timestamp < 0)) return { allowed: false, reason: "The reviewed frame timestamp must be zero or a positive number of seconds." };
2139
+ if (options.poster !== void 0 && typeof options.poster !== "boolean") return { allowed: false, reason: "The reviewed poster flag must be a boolean." };
2140
+ const capturecheck = validatecaptureoptions(options.capture);
2141
+ if (!capturecheck.allowed) return capturecheck;
2142
+ }
2143
+ if (kind === "downloadimages") {
2144
+ const filter = options.imagefilter;
2145
+ if (!filter || typeof filter !== "object" || Array.isArray(filter)) return { allowed: false, reason: "A reviewed imagefilter is required in options before any image downloads." };
2146
+ const imagefilter = filter;
2147
+ if (imagefilter.selector !== void 0 && !isnonempty(imagefilter.selector)) return { allowed: false, reason: "The reviewed imagefilter selector must be a non-empty selector from the reviewed selector grammar." };
2148
+ if (imagefilter.minwidth !== void 0 && (typeof imagefilter.minwidth !== "number" || !Number.isFinite(imagefilter.minwidth) || imagefilter.minwidth < 0)) return { allowed: false, reason: "The reviewed imagefilter minimum width must be zero or a positive number of pixels." };
2149
+ if (imagefilter.minheight !== void 0 && (typeof imagefilter.minheight !== "number" || !Number.isFinite(imagefilter.minheight) || imagefilter.minheight < 0)) return { allowed: false, reason: "The reviewed imagefilter minimum height must be zero or a positive number of pixels." };
2150
+ if (imagefilter.formats !== void 0 && (!Array.isArray(imagefilter.formats) || imagefilter.formats.length === 0 || !imagefilter.formats.every((item) => isnonempty(item)))) return { allowed: false, reason: "The reviewed imagefilter format list must be a non-empty list of mime or extension patterns when present." };
2151
+ if (options.naming !== void 0) {
2152
+ const namingcheck = validatecapturenaming(options.naming);
2153
+ if (!namingcheck.allowed) return namingcheck;
2154
+ }
2155
+ }
2156
+ if (kind === "shotcanvas") {
2157
+ const capturecheck = validatecaptureoptions(options.capture);
2158
+ if (!capturecheck.allowed) return capturecheck;
2159
+ }
2160
+ if (kind === "probestream" && options.selector !== void 0 && !isnonempty(options.selector)) return { allowed: false, reason: "The reviewed stream probe scope selector must be a non-empty string." };
2161
+ if (kind === "timelapse") {
2162
+ const lapse = options.lapse;
2163
+ if (!lapse || typeof lapse !== "object" || Array.isArray(lapse)) return { allowed: false, reason: "A reviewed lapse plan with interval, duration and format is required in options." };
2164
+ const plan = lapse;
2165
+ if (typeof plan.interval !== "number" || !Number.isFinite(plan.interval) || plan.interval <= 0) return { allowed: false, reason: "The reviewed lapse interval must be a positive number of milliseconds with no code ceiling." };
2166
+ if (typeof plan.duration !== "number" || !Number.isFinite(plan.duration) || plan.duration <= 0) return { allowed: false, reason: "The reviewed lapse duration must be a positive number of milliseconds with no code ceiling." };
2167
+ if (plan.format !== void 0 && plan.format !== "png" && plan.format !== "jpeg" && plan.format !== "webp") return { allowed: false, reason: "The reviewed lapse format must be png, jpeg or webp." };
2168
+ const budget = lapsebudgetallowed(plan.interval, plan.duration, typeof options.wait === "number" ? options.wait : void 0);
2169
+ if (!budget.allowed) return budget;
2170
+ const capturecheck = validatecaptureoptions(options.capture);
2171
+ if (!capturecheck.allowed) return capturecheck;
2172
+ }
2173
+ if (kind === "convertimage" || kind === "makethumbs") {
2174
+ const single = options.capture;
2175
+ const list = options.captures;
2176
+ const hasone = isnonempty(single);
2177
+ const haslist = Array.isArray(list) && list.length > 0 && list.every((item) => isnonempty(item));
2178
+ if (!hasone && !haslist) return { allowed: false, reason: "A reviewed capture id or a reviewed non-empty capture id list is required in options." };
2179
+ if (hasone && haslist) return { allowed: false, reason: "The reviewed step needs one capture id or a capture id list, not both." };
2180
+ }
2181
+ if (kind === "convertimage") {
2182
+ const convert = options.convert;
2183
+ if (!convert || typeof convert !== "object" || Array.isArray(convert)) return { allowed: false, reason: "A reviewed convert directive with a target format is required in options." };
2184
+ const directive = convert;
2185
+ if (directive.target !== "png" && directive.target !== "jpeg" && directive.target !== "webp") return { allowed: false, reason: "The reviewed conversion target must be png, jpeg or webp." };
2186
+ if (directive.source !== void 0 && directive.source !== "png" && directive.source !== "jpeg" && directive.source !== "webp") return { allowed: false, reason: "The reviewed conversion source must be png, jpeg or webp." };
2187
+ if (directive.quality !== void 0 && (typeof directive.quality !== "number" || !Number.isFinite(directive.quality) || directive.quality < 0 || directive.quality > 100)) return { allowed: false, reason: "The reviewed conversion quality must stay between zero and one hundred with no code cap inside that range." };
2188
+ }
2189
+ if (kind === "makethumbs") {
2190
+ const thumb = options.thumb;
2191
+ if (!thumb || typeof thumb !== "object" || Array.isArray(thumb)) return { allowed: false, reason: "A reviewed thumb directive with size, fit and suffix is required in options." };
2192
+ const directive = thumb;
2193
+ if (typeof directive.size !== "number" || !Number.isFinite(directive.size) || directive.size <= 0) return { allowed: false, reason: "The reviewed thumbnail size must be a positive number of pixels with no fixed set." };
2194
+ if (directive.fit !== "cover" && directive.fit !== "contain") return { allowed: false, reason: "The reviewed thumbnail fit must be cover or contain." };
2195
+ if (!isnonempty(directive.suffix)) return { allowed: false, reason: "The reviewed thumbnail naming suffix must be a non-empty string." };
2196
+ }
2197
+ return { allowed: true };
2198
+ }
1691
2199
  function validatestep(step, origin) {
1692
2200
  if (!allowedactions.has(step.kind)) return { allowed: false, reason: "Unsupported action kind." };
1693
2201
  if (!step.summary.trim()) return { allowed: false, reason: "A human-readable action summary is required." };
@@ -1909,6 +2417,10 @@ function validatestep(step, origin) {
1909
2417
  const capturecheck = validatecapturegrammar(step, options);
1910
2418
  if (!capturecheck.allowed) return capturecheck;
1911
2419
  }
2420
+ if (ismediakind(step.kind)) {
2421
+ const mediacheck = validatemediagrammar(step, options);
2422
+ if (!mediacheck.allowed) return mediacheck;
2423
+ }
1912
2424
  if (step.kind === "tabcreate") {
1913
2425
  if (options.background !== void 0 && typeof options.background !== "boolean") return { allowed: false, reason: "The reviewed background flag must be a boolean." };
1914
2426
  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." };
@@ -1980,6 +2492,14 @@ function canexecute(input) {
1980
2492
  const target = captureoptions.capture?.exporttarget;
1981
2493
  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
2494
  }
2495
+ if (ismediakind(input.step.kind)) {
2496
+ const mediagatecheck = mediagate(input.session, input.tabid, input.origin, now);
2497
+ if (!mediagatecheck.allowed) return mediagatecheck;
2498
+ }
2499
+ if (isrecordingkind(input.step.kind)) {
2500
+ const recordinggate = recordingconsentgranted(input.step);
2501
+ if (!recordinggate.allowed) return recordinggate;
2502
+ }
1983
2503
  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") {
1984
2504
  let options = {};
1985
2505
  try {
@@ -2001,7 +2521,7 @@ function canexecute(input) {
2001
2521
  }
2002
2522
 
2003
2523
  // version.ts
2004
- var packageversion = "1.1.40";
2524
+ var packageversion = "1.1.41";
2005
2525
 
2006
2526
  // types.ts
2007
2527
  var protocolversion = packageversion;
@@ -2065,7 +2585,7 @@ function requestbody(input) {
2065
2585
  return JSON.stringify({ version: protocolversion, objective: input.objective, session: input.session, observation: input.observation, capabilities: input.capabilities });
2066
2586
  }
2067
2587
  function outcomeresponse(input) {
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 } : {} });
2588
+ 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 } : {} });
2069
2589
  }
2070
2590
  function mapresponse(input) {
2071
2591
  return JSON.stringify({ version: protocolversion, planid: input.plan.id, planstate: input.plan.state, map: input.map });
@@ -2145,10 +2665,15 @@ function quarantinereport(input) {
2145
2665
  function capturereport(input) {
2146
2666
  return { version: protocolversion, records: input.records, pairs: input.pairs };
2147
2667
  }
2668
+ function mediareport(input) {
2669
+ return { version: protocolversion, records: input.records, images: input.images };
2670
+ }
2148
2671
  export {
2149
2672
  annotationplanof,
2673
+ assetentries,
2150
2674
  blendrows,
2151
2675
  buildname,
2676
+ buildpdf,
2152
2677
  buildsheet,
2153
2678
  buildstitchplan,
2154
2679
  canexecute,
@@ -2162,26 +2687,39 @@ export {
2162
2687
  capturestitched,
2163
2688
  capturetargets,
2164
2689
  capturevisible,
2690
+ convertdirectiveof,
2165
2691
  croprect,
2166
2692
  crossesviewport,
2167
2693
  datasetresponse,
2694
+ dedupeimages,
2168
2695
  actionrisk as deriveactionrisk,
2169
2696
  diffresponse,
2170
2697
  downloadreport,
2171
2698
  errorreportresponse,
2172
2699
  eventresponse,
2173
2700
  extractionreport,
2701
+ finishrecording,
2174
2702
  fixedheadermatch,
2175
2703
  formreportresponse,
2704
+ frameinterval,
2176
2705
  generatedvalueallowed,
2177
2706
  heldkeysreport,
2178
2707
  hostpattern,
2708
+ imagefilterof,
2709
+ imagematches,
2710
+ imagenames,
2179
2711
  isformkind,
2180
2712
  iswatchkind,
2713
+ lapseframes,
2714
+ lapseplanof,
2181
2715
  layoutreport,
2182
2716
  mapresponse,
2717
+ mediaentries,
2718
+ mediakinds,
2719
+ mediareport,
2183
2720
  navstateresponse,
2184
2721
  netlogreport,
2722
+ newrecording,
2185
2723
  normalizeendpoint,
2186
2724
  observationmodeof,
2187
2725
  observationresponse,
@@ -2189,11 +2727,16 @@ export {
2189
2727
  pairstates,
2190
2728
  parseproposal,
2191
2729
  passwordconsentgranted,
2730
+ pdfoptionsof,
2731
+ pdfpagesize,
2732
+ pdfsegments,
2733
+ pdftextlayout,
2192
2734
  profilegrantgranted,
2193
2735
  protocolversion,
2194
2736
  provenancereport,
2195
2737
  quarantinereport,
2196
2738
  randomid,
2739
+ recordingoptionsof,
2197
2740
  regionsteps,
2198
2741
  requestbody,
2199
2742
  resolutionverdict,
@@ -2203,8 +2746,11 @@ export {
2203
2746
  selectorresponse,
2204
2747
  sessionmemory,
2205
2748
  signalsreport,
2749
+ streamsummaries,
2206
2750
  submitreviewgranted,
2207
2751
  tabreportresponse,
2752
+ thumbdirectiveof,
2753
+ thumbgeometry,
2208
2754
  trailreport,
2209
2755
  transformgrammar,
2210
2756
  validatefieldmatch,