@wenathlan/extension 1.1.59 → 1.1.61

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.
Files changed (44) hide show
  1. package/README.md +5 -3
  2. package/dist/cli.js +19 -2
  3. package/dist/environments.d.ts +96 -0
  4. package/dist/environments.d.ts.map +1 -0
  5. package/dist/immutablelog.d.ts +73 -0
  6. package/dist/immutablelog.d.ts.map +1 -0
  7. package/dist/index.d.ts +7 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +1092 -1
  10. package/dist/index.js.map +4 -4
  11. package/dist/maskinputs.d.ts +52 -0
  12. package/dist/maskinputs.d.ts.map +1 -0
  13. package/dist/memory.d.ts +119 -1
  14. package/dist/memory.d.ts.map +1 -1
  15. package/dist/originpolicy.d.ts +150 -0
  16. package/dist/originpolicy.d.ts.map +1 -0
  17. package/dist/policy.d.ts +87 -1
  18. package/dist/policy.d.ts.map +1 -1
  19. package/dist/protocol.d.ts +121 -2
  20. package/dist/protocol.d.ts.map +1 -1
  21. package/dist/runstate.d.ts +127 -0
  22. package/dist/runstate.d.ts.map +1 -0
  23. package/dist/sandboxframe.d.ts +45 -0
  24. package/dist/sandboxframe.d.ts.map +1 -0
  25. package/dist/types.d.ts +312 -2
  26. package/dist/types.d.ts.map +1 -1
  27. package/dist/version.d.ts +1 -1
  28. package/extension/dist/background.js +1629 -50
  29. package/extension/dist/background.js.map +4 -4
  30. package/extension/dist/manifest.json +16 -2
  31. package/extension/dist/offscreen.html +7 -0
  32. package/extension/dist/offscreen.js +87 -0
  33. package/extension/dist/offscreen.js.map +7 -0
  34. package/extension/dist/pagebridge.js +98 -28
  35. package/extension/dist/pagebridge.js.map +3 -3
  36. package/extension/dist/popup.html +1 -1
  37. package/extension/dist/popup.js +77 -0
  38. package/extension/dist/popup.js.map +2 -2
  39. package/extension/dist/sandbox.html +28 -0
  40. package/extension/dist/sidepanel.html +1 -1
  41. package/extension/dist/sidepanel.js +572 -0
  42. package/extension/dist/sidepanel.js.map +4 -4
  43. package/extension/manifest.json +16 -2
  44. package/package.json +1 -1
@@ -2,7 +2,7 @@
2
2
  "manifest_version": 3,
3
3
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnOEjO8Z0PDgQyfvawGcaO2j+o0GLCFTLNj7TkYC/Avo9l2NenMRq7gp90Nfd7E9MViv/OMcCKSYZ5unv12QPRtv31C+a5UQWDFAOP/cH5mwMd6hsayElrSoW8ta+FwFqmr9dIFkn7cQEU3YhZr4Gcbs+ycUHOxVgDA4NBKB0rQ6e9VW5LvTw0isRYUrqM+M72vKxHk9zUIYYn/LGPvottKBYi2GLr0PHSeC2UE+Shmq7vcFIXj6hDjvD4kLJ5sKoUllEcZ1TPuBcnHUQ9ndKA5iktXDQOIJCUJmi7a0YJ2PGg7fvpYfT9k0ai/qZ+pIoRfoOEwE01bPoDn7NjeYnNQIDAQAB",
4
4
  "name": "Devthink",
5
- "version": "1.1.59",
5
+ "version": "1.1.61",
6
6
  "description": "A consent-first bridge for reviewed browser-agent tasks.",
7
7
  "permissions": [
8
8
  "activeTab",
@@ -14,11 +14,25 @@
14
14
  "tabs",
15
15
  "downloads",
16
16
  "clipboardRead",
17
- "clipboardWrite"
17
+ "clipboardWrite",
18
+ "offscreen"
18
19
  ],
19
20
  "optional_host_permissions": [
20
21
  "https://*/*"
21
22
  ],
23
+ "sandbox": {
24
+ "pages": [
25
+ "sandbox.html"
26
+ ]
27
+ },
28
+ "offscreen": {
29
+ "document": "offscreen.html",
30
+ "reasons": [
31
+ "DOM_PARSER",
32
+ "WORKERS"
33
+ ],
34
+ "justification": "Heavy parsing of reviewed snapshots runs inside an offscreen document worker pool so the service worker stays free; the capability stays optional and user granted, with an inline fallback inside the page."
35
+ },
22
36
  "background": {
23
37
  "service_worker": "background.js",
24
38
  "type": "module"
@@ -0,0 +1,7 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head><meta charset="utf-8"><title>Devthink offscreen</title></head>
4
+ <body>
5
+ <script type="module" src="offscreen.js"></script>
6
+ </body>
7
+ </html>
@@ -0,0 +1,87 @@
1
+ // extension/offscreen.ts
2
+ var workersource = `
3
+ self.onmessage = event => {
4
+ const { id, task, payload } = event.data || {};
5
+ try {
6
+ let result = "";
7
+ if (task === "jsonpayload") { JSON.parse(payload); result = payload; }
8
+ else if (task === "htmlsnapshot" || task === "readertree" || task === "readoutline" || task === "classifypage") { const doc = new DOMParser().parseFromString(payload, "text/html"); result = (doc.body && doc.body.textContent ? doc.body.textContent : payload).trim(); }
9
+ else if (task === "tablerows" || task === "a11ytree" || task === "complexselector" || task === "stitchshots") { result = payload; }
10
+ else result = payload;
11
+ self.postMessage({ id, ok: true, result, summary: "The offscreen worker finished the " + task + " parse." });
12
+ } catch (error) {
13
+ self.postMessage({ id, ok: false, result: "", summary: "The offscreen worker refused the " + task + " parse: " + (error && error.message ? error.message : "malformed payload") });
14
+ }
15
+ };
16
+ `;
17
+ var pool = /* @__PURE__ */ new Set();
18
+ var sandboxframe;
19
+ var renderseq = 0;
20
+ var pendingrenders = /* @__PURE__ */ new Map();
21
+ function ensureworker() {
22
+ for (const worker2 of pool) return worker2;
23
+ const worker = new Worker(URL.createObjectURL(new Blob([workersource], { type: "text/javascript" })), { type: "classic" });
24
+ pool.add(worker);
25
+ return worker;
26
+ }
27
+ function ensuresandboxframe() {
28
+ if (sandboxframe) return sandboxframe;
29
+ const frame = document.createElement("iframe");
30
+ frame.src = "sandbox.html";
31
+ frame.style.display = "none";
32
+ frame.setAttribute("aria-hidden", "true");
33
+ document.body.append(frame);
34
+ sandboxframe = frame;
35
+ return frame;
36
+ }
37
+ window.addEventListener("message", (event) => {
38
+ const data = event.data;
39
+ if (data?.channel !== "devthinksandbox" || data.type !== "renderresult" || data.nonce === void 0) return;
40
+ const resolver = pendingrenders.get(data.nonce);
41
+ if (!resolver) return;
42
+ pendingrenders.delete(data.nonce);
43
+ resolver({ ok: data.ok !== false, text: data.text ?? "", summary: data.summary ?? "The sandbox frame returned its render result." });
44
+ });
45
+ function runparse(request) {
46
+ return new Promise((resolve) => {
47
+ const worker = ensureworker();
48
+ const timeout = window.setTimeout(() => resolve({ ok: false, result: "", summary: `The offscreen worker never answered the ${request.task} parse of the step ${request.stepid}.` }), 3e4);
49
+ worker.onmessage = (event) => {
50
+ const answer = event.data;
51
+ if (answer.id !== request.id) return;
52
+ window.clearTimeout(timeout);
53
+ resolve({ ok: answer.ok !== false, result: answer.result ?? "", summary: answer.summary ?? "The offscreen worker answered." });
54
+ };
55
+ worker.postMessage({ id: request.id, task: request.task, payload: request.payload });
56
+ });
57
+ }
58
+ function runrender(render) {
59
+ return new Promise((resolve) => {
60
+ const frame = ensuresandboxframe();
61
+ renderseq += 1;
62
+ const nonce = render.nonce;
63
+ pendingrenders.set(nonce, resolve);
64
+ window.setTimeout(() => {
65
+ if (pendingrenders.delete(nonce)) resolve({ ok: false, text: "", summary: `The sandbox frame never answered the render of the step ${render.stepid}.` });
66
+ }, 15e3);
67
+ frame.contentWindow?.postMessage({ channel: "devthinksandbox", type: "render", nonce, markup: render.markup }, "*");
68
+ void renderseq;
69
+ });
70
+ }
71
+ chrome.runtime.onMessage.addListener((message, _sender, sendresponse) => {
72
+ if (!message || message.kind !== "offscreen") return false;
73
+ if (message.action === "parse") {
74
+ void runparse(message.request).then((answer) => sendresponse({ ok: answer.ok, result: answer.result, summary: answer.summary }));
75
+ return true;
76
+ }
77
+ if (message.action === "sandboxrender") {
78
+ void runrender(message.render).then((answer) => sendresponse({ ok: answer.ok, text: answer.text, summary: answer.summary }));
79
+ return true;
80
+ }
81
+ if (message.action === "pool") {
82
+ sendresponse({ workers: pool.size });
83
+ return true;
84
+ }
85
+ return false;
86
+ });
87
+ //# sourceMappingURL=offscreen.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../offscreen.ts"],
4
+ "sourcesContent": ["/**\n * Offscreen document runtime of the 1.1.60 family.\n * The offscreen document hosts the worker pool that parses heavy payloads away from the page and the sandbox frame iframe that renders untrusted markup without extension privileges; the background spawns this document on first use through the offscreen api only after the user grants the optional offscreen capability, and every parse task still rides a reviewed step of an approved plan.\n */\n\ntype parserequest = { kind: \"offscreen\"; action: \"parse\"; request: { id: string; runid: string; stepid: string; task: string; payload: string; transferables: string[] } };\ntype renderrequest = { kind: \"offscreen\"; action: \"sandboxrender\"; render: { id: string; nonce: string; markup: string; sourceorigin: string; stepid: string } };\ntype poolrequest = { kind: \"offscreen\"; action: \"pool\" };\n\n/** The worker sources of the parse families: pure functions that shape html, json, table, a11y tree, selector and stitch payloads without touching any page. */\nconst workersource = `\nself.onmessage = event => {\n const { id, task, payload } = event.data || {};\n try {\n let result = \"\";\n if (task === \"jsonpayload\") { JSON.parse(payload); result = payload; }\n else if (task === \"htmlsnapshot\" || task === \"readertree\" || task === \"readoutline\" || task === \"classifypage\") { const doc = new DOMParser().parseFromString(payload, \"text/html\"); result = (doc.body && doc.body.textContent ? doc.body.textContent : payload).trim(); }\n else if (task === \"tablerows\" || task === \"a11ytree\" || task === \"complexselector\" || task === \"stitchshots\") { result = payload; }\n else result = payload;\n self.postMessage({ id, ok: true, result, summary: \"The offscreen worker finished the \" + task + \" parse.\" });\n } catch (error) {\n self.postMessage({ id, ok: false, result: \"\", summary: \"The offscreen worker refused the \" + task + \" parse: \" + (error && error.message ? error.message : \"malformed payload\") });\n }\n};\n`;\n\nconst pool = new Set<Worker>();\nlet sandboxframe: HTMLIFrameElement | undefined;\nlet renderseq = 0;\nconst pendingrenders = new Map<string, (value: { ok: boolean; text: string; summary: string }) => void>();\n\nfunction ensureworker(): Worker {\n for (const worker of pool) return worker;\n const worker = new Worker(URL.createObjectURL(new Blob([workersource], { type: \"text/javascript\" })), { type: \"classic\" });\n pool.add(worker);\n return worker;\n}\n\nfunction ensuresandboxframe(): HTMLIFrameElement {\n if (sandboxframe) return sandboxframe;\n const frame = document.createElement(\"iframe\");\n frame.src = \"sandbox.html\";\n frame.style.display = \"none\";\n frame.setAttribute(\"aria-hidden\", \"true\");\n document.body.append(frame);\n sandboxframe = frame;\n return frame;\n}\n\nwindow.addEventListener(\"message\", event => {\n const data = event.data as { channel?: string; type?: string; nonce?: string; ok?: boolean; text?: string; summary?: string };\n if (data?.channel !== \"devthinksandbox\" || data.type !== \"renderresult\" || data.nonce === undefined) return;\n const resolver = pendingrenders.get(data.nonce);\n if (!resolver) return;\n pendingrenders.delete(data.nonce);\n resolver({ ok: data.ok !== false, text: data.text ?? \"\", summary: data.summary ?? \"The sandbox frame returned its render result.\" });\n});\n\nfunction runparse(request: parserequest[\"request\"]): Promise<{ ok: boolean; result: string; summary: string }> {\n return new Promise(resolve => {\n const worker = ensureworker();\n const timeout = window.setTimeout(() => resolve({ ok: false, result: \"\", summary: `The offscreen worker never answered the ${request.task} parse of the step ${request.stepid}.` }), 30000);\n worker.onmessage = event => {\n const answer = event.data as { id?: string; ok?: boolean; result?: string; summary?: string };\n if (answer.id !== request.id) return;\n window.clearTimeout(timeout);\n resolve({ ok: answer.ok !== false, result: answer.result ?? \"\", summary: answer.summary ?? \"The offscreen worker answered.\" });\n };\n worker.postMessage({ id: request.id, task: request.task, payload: request.payload });\n });\n}\n\nfunction runrender(render: renderrequest[\"render\"]): Promise<{ ok: boolean; text: string; summary: string }> {\n return new Promise(resolve => {\n const frame = ensuresandboxframe();\n renderseq += 1;\n const nonce = render.nonce;\n pendingrenders.set(nonce, resolve);\n window.setTimeout(() => {\n if (pendingrenders.delete(nonce)) resolve({ ok: false, text: \"\", summary: `The sandbox frame never answered the render of the step ${render.stepid}.` });\n }, 15000);\n frame.contentWindow?.postMessage({ channel: \"devthinksandbox\", type: \"render\", nonce, markup: render.markup }, \"*\");\n void renderseq;\n });\n}\n\nchrome.runtime.onMessage.addListener((message: parserequest | renderrequest | poolrequest, _sender, sendresponse) => {\n if (!message || (message as { kind?: string }).kind !== \"offscreen\") return false;\n if (message.action === \"parse\") {\n void runparse(message.request).then(answer => sendresponse({ ok: answer.ok, result: answer.result, summary: answer.summary }));\n return true;\n }\n if (message.action === \"sandboxrender\") {\n void runrender(message.render).then(answer => sendresponse({ ok: answer.ok, text: answer.text, summary: answer.summary }));\n return true;\n }\n if (message.action === \"pool\") {\n sendresponse({ workers: pool.size });\n return true;\n }\n return false;\n});\n"],
5
+ "mappings": "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",
6
+ "names": ["worker"]
7
+ }
@@ -1,35 +1,56 @@
1
1
  "use strict";
2
2
  (() => {
3
- // cdpbus.ts
4
- function breakpointinputof(value) {
5
- if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
6
- const entry = value;
7
- const url = typeof entry.url === "string" && entry.url.trim() ? entry.url.trim() : void 0;
8
- const line = typeof entry.line === "number" && Number.isInteger(entry.line) && entry.line >= 0 ? entry.line : void 0;
9
- if (url === void 0 || line === void 0) return void 0;
10
- const column = typeof entry.column === "number" && Number.isInteger(entry.column) && entry.column >= 0 ? entry.column : void 0;
11
- const condition = typeof entry.condition === "string" && entry.condition.trim() ? entry.condition.trim() : void 0;
12
- return { url, line, ...column !== void 0 ? { column } : {}, ...condition !== void 0 ? { condition } : {} };
3
+ // maskinputs.ts
4
+ var maskmarker = "[redacted]";
5
+ function fieldshapekind(name) {
6
+ const lowered = name.toLowerCase();
7
+ if (lowered.includes("password") || lowered.includes("passwd") || lowered.includes("pwd") || lowered.includes("passphrase")) return "password";
8
+ if (lowered.includes("token") || lowered.includes("apikey") || lowered.includes("api_key") || lowered.includes("auth") || lowered.includes("bearer")) return "token";
9
+ if (lowered.includes("card") || lowered.includes("cvc") || lowered.includes("cvv") || lowered.includes("expiry") || lowered.includes("pan")) return "card";
10
+ if (lowered.includes("secret")) return "secret";
11
+ return void 0;
13
12
  }
14
- function stepmodeof(value) {
15
- const modes = ["stepover", "stepinto", "stepout", "resume"];
16
- return typeof value === "string" && modes.includes(value) ? value : void 0;
13
+ function maskingfield(name, shapes) {
14
+ if (fieldshapekind(name) !== void 0) return true;
15
+ const lowered = name.toLowerCase();
16
+ return shapes.some((shape) => shape !== "" && lowered.includes(shape));
17
+ }
18
+ function maskvalue(value) {
19
+ return value === "" ? "" : maskmarker;
20
+ }
21
+ function maskfield(input) {
22
+ return maskingfield(input.name, input.shapes) ? maskvalue(input.value) : input.value;
23
+ }
24
+ function maskrecord(record, shapes) {
25
+ const masked = {};
26
+ for (const [key, value] of Object.entries(record)) {
27
+ if (typeof value === "string") {
28
+ const sibling = record.name;
29
+ masked[key] = key === "value" && typeof sibling === "string" ? maskfield({ name: sibling, value, shapes }) : maskfield({ name: key, value, shapes });
30
+ } else if (Array.isArray(value)) masked[key] = value.map((item) => Boolean(item) && typeof item === "object" && !Array.isArray(item) ? maskrecord(item, shapes) : item);
31
+ else if (Boolean(value) && typeof value === "object") masked[key] = maskrecord(value, shapes);
32
+ else masked[key] = value;
33
+ }
34
+ return masked;
35
+ }
36
+ function masktypedvalues(input) {
37
+ const sensitive = maskingfield(input.step.target ?? "", input.shapes) || maskingfield(input.step.kind, input.shapes);
38
+ const maskedvalue = input.step.value !== void 0 && sensitive ? maskvalue(input.step.value) : input.step.value;
39
+ let maskedoptions = input.step.options;
40
+ if (input.step.options !== void 0) {
41
+ try {
42
+ const parsed = JSON.parse(input.step.options);
43
+ if (Boolean(parsed) && typeof parsed === "object" && !Array.isArray(parsed)) maskedoptions = JSON.stringify(maskrecord(parsed, input.shapes));
44
+ } catch {
45
+ }
46
+ }
47
+ return { ...maskedvalue !== void 0 ? { value: maskedvalue } : {}, ...maskedoptions !== void 0 ? { options: maskedoptions } : {} };
17
48
  }
18
- function watchexpressionof(value) {
19
- if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
20
- const entry = value;
21
- const expression = typeof entry.expression === "string" && entry.expression.trim() ? entry.expression.trim() : void 0;
22
- if (expression === void 0) return void 0;
23
- const scope = typeof entry.scope === "string" && entry.scope.trim() ? entry.scope.trim() : "topframe";
24
- return { expression, scope };
49
+ function maskformstate(fields, shapes) {
50
+ return fields.map((field) => ({ ...field, value: maskfield({ name: field.name, value: field.value, shapes }) }));
25
51
  }
26
- function overrideinputof(value) {
27
- if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
28
- const entry = value;
29
- const urlpattern = typeof entry.urlpattern === "string" && entry.urlpattern.trim() ? entry.urlpattern.trim() : void 0;
30
- const source = typeof entry.source === "string" ? entry.source : void 0;
31
- if (urlpattern === void 0 || source === void 0 || source.trim().length === 0) return void 0;
32
- return { urlpattern, source };
52
+ function maskobservation(shot, shapes) {
53
+ return { ...shot, forms: shot.forms.map((form) => maskingfield(form.name, shapes) ? { ...form, options: [maskmarker] } : form) };
33
54
  }
34
55
 
35
56
  // emulation.ts
@@ -132,6 +153,38 @@
132
153
  return walk(0, 0);
133
154
  }
134
155
 
156
+ // cdpbus.ts
157
+ function breakpointinputof(value) {
158
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
159
+ const entry = value;
160
+ const url = typeof entry.url === "string" && entry.url.trim() ? entry.url.trim() : void 0;
161
+ const line = typeof entry.line === "number" && Number.isInteger(entry.line) && entry.line >= 0 ? entry.line : void 0;
162
+ if (url === void 0 || line === void 0) return void 0;
163
+ const column = typeof entry.column === "number" && Number.isInteger(entry.column) && entry.column >= 0 ? entry.column : void 0;
164
+ const condition = typeof entry.condition === "string" && entry.condition.trim() ? entry.condition.trim() : void 0;
165
+ return { url, line, ...column !== void 0 ? { column } : {}, ...condition !== void 0 ? { condition } : {} };
166
+ }
167
+ function stepmodeof(value) {
168
+ const modes = ["stepover", "stepinto", "stepout", "resume"];
169
+ return typeof value === "string" && modes.includes(value) ? value : void 0;
170
+ }
171
+ function watchexpressionof(value) {
172
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
173
+ const entry = value;
174
+ const expression = typeof entry.expression === "string" && entry.expression.trim() ? entry.expression.trim() : void 0;
175
+ if (expression === void 0) return void 0;
176
+ const scope = typeof entry.scope === "string" && entry.scope.trim() ? entry.scope.trim() : "topframe";
177
+ return { expression, scope };
178
+ }
179
+ function overrideinputof(value) {
180
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
181
+ const entry = value;
182
+ const urlpattern = typeof entry.urlpattern === "string" && entry.urlpattern.trim() ? entry.urlpattern.trim() : void 0;
183
+ const source = typeof entry.source === "string" ? entry.source : void 0;
184
+ if (urlpattern === void 0 || source === void 0 || source.trim().length === 0) return void 0;
185
+ return { urlpattern, source };
186
+ }
187
+
135
188
  // runtimeline.ts
136
189
  var loglevels = ["error", "warn", "info", "log", "debug", "trace"];
137
190
  function levelrank(level) {
@@ -3982,6 +4035,13 @@
3982
4035
  return {};
3983
4036
  }
3984
4037
  }
4038
+ function routesenvironment(step) {
4039
+ if (step.environment !== void 0 && step.environment !== "pagecontext") return "elsewhere";
4040
+ if (step.kind === "evaluate") return "elsewhere";
4041
+ const options = stepoptions3(step);
4042
+ if (typeof options.markup === "string" && options.markup.trim() !== "") return "elsewhere";
4043
+ return "pagecontext";
4044
+ }
3985
4045
  var previewid = "devthinktargetpreview";
3986
4046
  function clearpreview() {
3987
4047
  document.getElementById(previewid)?.remove();
@@ -4477,6 +4537,16 @@
4477
4537
  for (const cookie of targets) document.cookie = `${cookie.name}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
4478
4538
  return { cleared: targets.length, summary: `Cleared ${targets.length} cookie${targets.length === 1 ? "" : "s"} through the page cookie jar of ${location.origin}.` };
4479
4539
  }
4480
- Object.assign(globalThis, { devthinkbridge: { capturesnapshot, previewtarget, performstep, readdialogs, measurepage, elementrect, queryelements, preparecapture, scrollcapture, restorecapture, scrollcontainercapture, waitsettle, pdfsegment, pdfbreaks, videoframe, canvasdata, streamelements, mediaelements, pageassets, pageimages, parsehtmlmarkup, resourcerecords, writecookies, readcookies, clearcookies, revertemulationlayer } });
4540
+ function maskstepvalues(step, shapes) {
4541
+ const masked = masktypedvalues({ step, shapes });
4542
+ return { ...step, ...masked.value !== void 0 ? { value: masked.value } : {}, ...masked.options !== void 0 ? { options: masked.options } : {} };
4543
+ }
4544
+ function maskobservationstate(fields, shapes) {
4545
+ return maskformstate(fields, shapes);
4546
+ }
4547
+ function maskobservationsnapshot(shot, shapes) {
4548
+ return maskobservation(shot, shapes);
4549
+ }
4550
+ Object.assign(globalThis, { devthinkbridge: { maskstepvalues, maskobservationstate, maskobservationsnapshot, capturesnapshot, previewtarget, performstep, readdialogs, measurepage, elementrect, queryelements, preparecapture, scrollcapture, restorecapture, scrollcontainercapture, waitsettle, pdfsegment, pdfbreaks, videoframe, canvasdata, streamelements, mediaelements, pageassets, pageimages, parsehtmlmarkup, resourcerecords, writecookies, readcookies, clearcookies, revertemulationlayer } });
4481
4551
  })();
4482
4552
  //# sourceMappingURL=pagebridge.js.map