hunter-mate 0.1.17 → 0.1.19

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 (89) hide show
  1. package/dist/assets/extension/background/{service-worker.20261001153649.js → service-worker.20261008011501.js} +868 -142
  2. package/dist/assets/extension/background/service-worker.js +868 -142
  3. package/dist/assets/extension/build-info.json +1 -1
  4. package/dist/assets/extension/content/control-runtime.js +1028 -0
  5. package/dist/assets/extension/content/index.js +35 -0
  6. package/dist/assets/extension/manifest.json +4 -3
  7. package/dist/assets/extension/offscreen/offscreen.html +1 -1
  8. package/dist/assets/extension/offscreen/offscreen.js +2 -2
  9. package/dist/assets/extension/package.json +1 -1
  10. package/dist/assets/extension/sidepanel/index.css +1 -1
  11. package/dist/assets/extension/sidepanel/index.html +1 -1
  12. package/dist/assets/extension/sidepanel/index.js +23 -14
  13. package/dist/assets/server/main.mjs +10015 -4786
  14. package/dist/index.js +849 -318
  15. package/dist/web/dist/404.html +1 -1
  16. package/dist/web/dist/_next/static/{L4ZJv0swR7OTsvB_PaAB4 → 9Wm8FfXwBJyMk-wYf4l81}/_ssgManifest.js +1 -1
  17. package/dist/web/dist/_next/static/chunks/542-4a43545450151f1d.js +1 -0
  18. package/dist/web/dist/_next/static/chunks/670-750aa43678fb0d30.js +1 -0
  19. package/dist/web/dist/_next/static/chunks/852-5150a7ae95a599fb.js +1 -0
  20. package/dist/web/dist/_next/static/chunks/{935-bb4adb3868af4cd4.js → 935-4058f12c3d405b32.js} +4 -4
  21. package/dist/web/dist/_next/static/chunks/app/admin/data/page-a566c6b13c61f9d4.js +1 -0
  22. package/dist/web/dist/_next/static/chunks/app/companies/page-058047767bc162f4.js +1 -0
  23. package/dist/web/dist/_next/static/chunks/app/company/admin/page-a2088b59c3820800.js +1 -0
  24. package/dist/web/dist/_next/static/chunks/app/jobs/page-4fb6a67d044b238d.js +1 -0
  25. package/dist/web/dist/_next/static/chunks/app/layout-1feb99bf08beb3c8.js +1 -0
  26. package/dist/web/dist/_next/static/chunks/app/matching/jobs/[id]/talents/page-c6714cec1ffd7c5e.js +1 -0
  27. package/dist/web/dist/_next/static/chunks/app/matching/portraits/[id]/jobs/page-658eca1ae5ca29dc.js +1 -0
  28. package/dist/web/dist/_next/static/chunks/app/page-291cd145a56bd020.js +1 -0
  29. package/dist/web/dist/_next/static/chunks/app/parselog/page-b1b7ae9483273ce0.js +1 -0
  30. package/dist/web/dist/_next/static/chunks/app/recordings/page-c12948f01885099e.js +1 -0
  31. package/dist/web/dist/_next/static/chunks/app/resource-usage/{page-3b8bd27536a7889a.js → page-8394e96892688180.js} +1 -1
  32. package/dist/web/dist/_next/static/chunks/app/shared/[token]/page-e859e87f2301b120.js +1 -0
  33. package/dist/web/dist/_next/static/chunks/app/snapshots/[id]/agent-prompt/page-f519552be54e3bdf.js +1 -0
  34. package/dist/web/dist/_next/static/chunks/app/talents/page-75af05473ea322d9.js +1 -0
  35. package/dist/web/dist/_next/static/chunks/app/team/insights/page-7b8769e35cd9987b.js +1 -0
  36. package/dist/web/dist/_next/static/chunks/{main-ead3ac50aa4bc931.js → main-8d45182e1c21cb95.js} +1 -1
  37. package/dist/web/dist/_next/static/chunks/{main-app-d053d37cc3b76ace.js → main-app-70da092dee991648.js} +1 -1
  38. package/dist/web/dist/_next/static/chunks/pages/{_app-e11d02a41d9f3cb9.js → _app-8438560f1c1a7980.js} +3 -3
  39. package/dist/web/dist/_next/static/css/9eaf0c9cc1c24641.css +3 -0
  40. package/dist/web/dist/admin/data.html +1 -1
  41. package/dist/web/dist/admin/data.txt +3 -3
  42. package/dist/web/dist/auth/verify.html +1 -1
  43. package/dist/web/dist/auth/verify.txt +2 -2
  44. package/dist/web/dist/companies.html +1 -1
  45. package/dist/web/dist/companies.txt +7 -6
  46. package/dist/web/dist/company/admin.html +1 -1
  47. package/dist/web/dist/company/admin.txt +3 -3
  48. package/dist/web/dist/entity.html +1 -1
  49. package/dist/web/dist/entity.txt +2 -2
  50. package/dist/web/dist/index.html +1 -1
  51. package/dist/web/dist/index.txt +3 -3
  52. package/dist/web/dist/jobs.html +1 -1
  53. package/dist/web/dist/jobs.txt +3 -3
  54. package/dist/web/dist/logs.html +1 -1
  55. package/dist/web/dist/logs.txt +2 -2
  56. package/dist/web/dist/matching/jobs/placeholder/talents.html +1 -1
  57. package/dist/web/dist/matching/jobs/placeholder/talents.txt +3 -3
  58. package/dist/web/dist/matching/portraits/placeholder/jobs.html +1 -1
  59. package/dist/web/dist/matching/portraits/placeholder/jobs.txt +3 -3
  60. package/dist/web/dist/parselog.html +1 -1
  61. package/dist/web/dist/parselog.txt +3 -3
  62. package/dist/web/dist/recordings.html +1 -1
  63. package/dist/web/dist/recordings.txt +3 -3
  64. package/dist/web/dist/resource-usage.html +1 -1
  65. package/dist/web/dist/resource-usage.txt +3 -3
  66. package/dist/web/dist/shared/placeholder.html +1 -0
  67. package/dist/web/dist/shared/placeholder.txt +8 -0
  68. package/dist/web/dist/snapshots/placeholder/agent-prompt.html +1 -1
  69. package/dist/web/dist/snapshots/placeholder/agent-prompt.txt +3 -3
  70. package/dist/web/dist/talents.html +1 -1
  71. package/dist/web/dist/talents.txt +3 -3
  72. package/dist/web/dist/team/insights.html +1 -0
  73. package/dist/web/dist/team/insights.txt +7 -0
  74. package/package.json +1 -1
  75. package/dist/web/dist/_next/static/chunks/170-b66b6f731381943e.js +0 -1
  76. package/dist/web/dist/_next/static/chunks/app/admin/data/page-37e01dad70306bf3.js +0 -1
  77. package/dist/web/dist/_next/static/chunks/app/companies/page-985002eea5b295d0.js +0 -1
  78. package/dist/web/dist/_next/static/chunks/app/company/admin/page-8c7ecc92bef09e92.js +0 -1
  79. package/dist/web/dist/_next/static/chunks/app/jobs/page-e39b3e25f0a81254.js +0 -1
  80. package/dist/web/dist/_next/static/chunks/app/layout-d094dc654772bf32.js +0 -1
  81. package/dist/web/dist/_next/static/chunks/app/matching/jobs/[id]/talents/page-936f6190c968d20b.js +0 -1
  82. package/dist/web/dist/_next/static/chunks/app/matching/portraits/[id]/jobs/page-ea44a2236bd53cae.js +0 -1
  83. package/dist/web/dist/_next/static/chunks/app/page-41d8e008a9411221.js +0 -1
  84. package/dist/web/dist/_next/static/chunks/app/parselog/page-3f756bbd580f337e.js +0 -1
  85. package/dist/web/dist/_next/static/chunks/app/recordings/page-ffd507b12e67f2db.js +0 -1
  86. package/dist/web/dist/_next/static/chunks/app/snapshots/[id]/agent-prompt/page-c89b32aa2ef509f5.js +0 -1
  87. package/dist/web/dist/_next/static/chunks/app/talents/page-8e0b4072df138fa3.js +0 -1
  88. package/dist/web/dist/_next/static/css/1dd88e02ef1af7b9.css +0 -3
  89. /package/dist/web/dist/_next/static/{L4ZJv0swR7OTsvB_PaAB4 → 9Wm8FfXwBJyMk-wYf4l81}/_buildManifest.js +0 -0
@@ -0,0 +1,1028 @@
1
+ "use strict";
2
+ (() => {
3
+ // src/shared/control-runtime.ts
4
+ function getRefStore() {
5
+ const g2 = globalThis;
6
+ if (!g2.__cpRefs) {
7
+ g2.__cpRefs = { counter: 1, refs: /* @__PURE__ */ new Map(), cssPaths: /* @__PURE__ */ new Map() };
8
+ }
9
+ return g2.__cpRefs;
10
+ }
11
+ function allocRef(el) {
12
+ const store = getRefStore();
13
+ for (const [ref2, existing2] of store.refs) {
14
+ if (existing2 === el) return ref2;
15
+ }
16
+ const ref = store.counter++;
17
+ store.refs.set(ref, el);
18
+ store.cssPaths.set(ref, uniqueCssPath(el));
19
+ return ref;
20
+ }
21
+ function uniqueCssPath(el) {
22
+ if (el.id) return `#${CSS.escape(el.id)}`;
23
+ const parts = [];
24
+ let cur = el;
25
+ while (cur && cur !== document.body && cur !== document.documentElement) {
26
+ let sel = cur.tagName.toLowerCase();
27
+ if (cur.id) {
28
+ parts.unshift(`#${CSS.escape(cur.id)}`);
29
+ break;
30
+ }
31
+ const parent = cur.parentElement;
32
+ if (parent) {
33
+ const sameTag = Array.from(parent.children).filter((c) => c.tagName === cur.tagName);
34
+ if (sameTag.length > 1) {
35
+ const idx = sameTag.indexOf(cur) + 1;
36
+ sel += `:nth-of-type(${idx})`;
37
+ }
38
+ }
39
+ parts.unshift(sel);
40
+ cur = parent;
41
+ }
42
+ return parts.join(" > ");
43
+ }
44
+ function err(code, message, extra) {
45
+ return { error: { code, message, ...extra || {} } };
46
+ }
47
+ var ERROR_CODES = {
48
+ NOT_FOUND: "not_found",
49
+ STALE_REF: "stale_ref",
50
+ INVALID_SELECTOR: "invalid_selector",
51
+ SELECTOR_NOT_FOUND: "selector_not_found",
52
+ SELECTOR_AMBIGUOUS: "selector_ambiguous",
53
+ SELECTOR_NTH_OUT_OF_RANGE: "selector_nth_out_of_range",
54
+ OPTION_NOT_FOUND: "option_not_found",
55
+ NOT_A_SELECT: "not_a_select"
56
+ };
57
+ var IMPLICIT_ROLE = {
58
+ a: "link",
59
+ button: "button",
60
+ select: "combobox",
61
+ textarea: "textbox",
62
+ h1: "heading",
63
+ h2: "heading",
64
+ h3: "heading",
65
+ h4: "heading",
66
+ h5: "heading",
67
+ h6: "heading",
68
+ img: "img",
69
+ nav: "navigation",
70
+ ul: "list",
71
+ ol: "list",
72
+ li: "listitem",
73
+ main: "main",
74
+ article: "article",
75
+ aside: "complementary",
76
+ header: "banner",
77
+ footer: "contentinfo",
78
+ form: "form",
79
+ table: "table",
80
+ summary: "button",
81
+ option: "option",
82
+ output: "status"
83
+ };
84
+ function roleOf(el) {
85
+ const explicit = el.getAttribute("role");
86
+ if (explicit) return explicit.split(/\s+/)[0];
87
+ const tag = el.tagName.toLowerCase();
88
+ if (tag === "input") {
89
+ const type = el.type || "text";
90
+ if (type === "hidden") return null;
91
+ if (type === "checkbox") return "checkbox";
92
+ if (type === "radio") return "radio";
93
+ if (type === "button" || type === "submit" || type === "reset") return "button";
94
+ if (type === "range") return "slider";
95
+ return "textbox";
96
+ }
97
+ if (tag === "progress") return "progressbar";
98
+ if (tag === "meter") return "meter";
99
+ return IMPLICIT_ROLE[tag] ?? null;
100
+ }
101
+ function accessibleName(el) {
102
+ const aria = el.getAttribute("aria-label");
103
+ if (aria) return aria.trim();
104
+ const labelledby = el.getAttribute("aria-labelledby");
105
+ if (labelledby) {
106
+ const parts = labelledby.split(/\s+/).map((id2) => document.getElementById(id2)?.textContent?.trim() || "");
107
+ const joined = parts.filter(Boolean).join(" ");
108
+ if (joined) return joined.slice(0, 120);
109
+ }
110
+ const id = el.getAttribute("id");
111
+ if (id) {
112
+ const label = document.querySelector(`label[for="${CSS.escape(id)}"]`);
113
+ if (label?.textContent?.trim()) return label.textContent.trim().slice(0, 120);
114
+ }
115
+ if (el.tagName.toLowerCase() === "input") {
116
+ const type = el.type;
117
+ if (type === "button" || type === "submit" || type === "reset") {
118
+ const v = el.value;
119
+ if (v) return v;
120
+ }
121
+ }
122
+ const alt = el.getAttribute("alt");
123
+ if (alt) return alt;
124
+ const title = el.getAttribute("title");
125
+ if (title) return title;
126
+ const placeholder = el.getAttribute("placeholder");
127
+ if (placeholder) return placeholder;
128
+ return (el.textContent || "").replace(/\s+/g, " ").trim().slice(0, 120);
129
+ }
130
+ function isVisible(el) {
131
+ if (!(el instanceof HTMLElement) && !(el instanceof SVGElement)) return false;
132
+ const html = el;
133
+ if (html.hasAttribute("hidden")) return false;
134
+ if (html.closest("[hidden]")) return false;
135
+ const style = window.getComputedStyle(html);
136
+ if (style.display === "none" || style.visibility === "hidden" || style.opacity === "0") return false;
137
+ if (el instanceof HTMLElement && el.offsetParent === null) {
138
+ const pos = style.position;
139
+ if (pos !== "fixed" && pos !== "sticky") return false;
140
+ }
141
+ return true;
142
+ }
143
+ var INTERACTIVE_SELECTOR = "a[href], button, input, textarea, select, summary, [role], [contenteditable=''], [contenteditable='true'], [onclick], [tabindex]";
144
+ function isInteractive(el) {
145
+ return el.matches(INTERACTIVE_SELECTOR);
146
+ }
147
+ function testidSelector(testid) {
148
+ return `[data-testid="${CSS.escape(testid)}"], [data-test-id="${CSS.escape(testid)}"], [data-test="${CSS.escape(testid)}"], [data-cy="${CSS.escape(testid)}"]`;
149
+ }
150
+ function resolveTargetRich(sel) {
151
+ const targetDesc = sel.ref != null ? String(sel.ref) : sel.css ?? (sel.role || sel.name || sel.label || sel.testid || sel.text ? `${sel.role ? `role=${sel.role} ` : ""}${sel.name ? `name=${sel.name} ` : ""}${sel.label ? `label=${sel.label} ` : ""}${sel.testid ? `testid=${sel.testid} ` : ""}${sel.text ? `text=${sel.text}` : ""}`.trim() : "");
152
+ if (sel.ref != null) {
153
+ const store = getRefStore();
154
+ const el = store.refs.get(sel.ref);
155
+ if (el && document.contains(el) && isVisible(el)) {
156
+ return { el, matches_n: 1, match_level: "exact", target: targetDesc };
157
+ }
158
+ if (el && !document.contains(el)) {
159
+ const cssPath = store.cssPaths.get(sel.ref);
160
+ if (cssPath) {
161
+ const re = document.querySelector(cssPath);
162
+ if (re && isVisible(re)) {
163
+ store.refs.set(sel.ref, re);
164
+ return { el: re, matches_n: 1, match_level: "reidentified", target: targetDesc };
165
+ }
166
+ }
167
+ return { errorEnvelope: err(ERROR_CODES.STALE_REF, "Numeric ref is no longer in the DOM. Re-run state.") };
168
+ }
169
+ return { errorEnvelope: err(ERROR_CODES.NOT_FOUND, "Numeric ref is no longer in the DOM. Re-run state.") };
170
+ }
171
+ let candidates = [];
172
+ if (sel.css) {
173
+ try {
174
+ candidates = Array.from(document.querySelectorAll(sel.css));
175
+ } catch {
176
+ return { errorEnvelope: err(ERROR_CODES.INVALID_SELECTOR, "CSS was rejected by querySelectorAll.", { selector: sel.css }) };
177
+ }
178
+ if (candidates.length === 0) {
179
+ return { errorEnvelope: err(ERROR_CODES.SELECTOR_NOT_FOUND, "CSS matches 0 elements.", { selector: sel.css, candidates: suggestCandidates() }) };
180
+ }
181
+ } else if (sel.testid) {
182
+ try {
183
+ candidates = Array.from(document.querySelectorAll(testidSelector(sel.testid)));
184
+ } catch {
185
+ return { errorEnvelope: err(ERROR_CODES.INVALID_SELECTOR, "Invalid testid.", { testid: sel.testid }) };
186
+ }
187
+ } else if (sel.role || sel.name || sel.label || sel.text) {
188
+ const wantRole = sel.role ? sel.role.toLowerCase() : null;
189
+ const wantName = sel.name ? sel.name.toLowerCase() : null;
190
+ const wantText = sel.text ? sel.text.toLowerCase() : null;
191
+ let labelTargets = [];
192
+ if (sel.label) {
193
+ const lower = sel.label.toLowerCase();
194
+ labelTargets = Array.from(document.querySelectorAll("label")).filter((l) => (l.textContent || "").trim().toLowerCase().includes(lower)).map((l) => {
195
+ const forId = l.getAttribute("for");
196
+ if (forId) return document.getElementById(forId);
197
+ return l.querySelector("input, select, textarea");
198
+ }).filter((x) => !!x);
199
+ }
200
+ const all = Array.from(document.querySelectorAll("*"));
201
+ candidates = all.filter((el) => {
202
+ if (!isVisible(el)) return false;
203
+ const role = roleOf(el);
204
+ if (wantRole && (!role || role.toLowerCase() !== wantRole)) return false;
205
+ if (wantName) {
206
+ const name = accessibleName(el).toLowerCase();
207
+ if (!name.includes(wantName)) return false;
208
+ }
209
+ if (wantText) {
210
+ const t = (el.textContent || "").replace(/\s+/g, " ").trim().toLowerCase();
211
+ if (!t.includes(wantText)) return false;
212
+ }
213
+ return true;
214
+ });
215
+ if (labelTargets.length) {
216
+ const set = new Set(labelTargets);
217
+ candidates = labelTargets.concat(candidates.filter((c) => !set.has(c)));
218
+ }
219
+ if (candidates.length === 0) {
220
+ return {
221
+ errorEnvelope: err(
222
+ ERROR_CODES.SELECTOR_NOT_FOUND,
223
+ "Semantic locator matches 0 elements.",
224
+ { role: sel.role, name: sel.name, label: sel.label, text: sel.text, candidates: suggestCandidates() }
225
+ )
226
+ };
227
+ }
228
+ } else {
229
+ return { errorEnvelope: err("no_target", "Provide a numeric ref, CSS selector, or semantic locator (--role/--name/--label/--text/--testid).") };
230
+ }
231
+ const visible = candidates.filter(isVisible);
232
+ const pool = visible.length ? visible : candidates;
233
+ if (sel.nth != null) {
234
+ if (sel.nth < 0 || sel.nth >= pool.length) {
235
+ return { errorEnvelope: err(ERROR_CODES.SELECTOR_NTH_OUT_OF_RANGE, `--nth ${sel.nth} beyond match count ${pool.length}.`) };
236
+ }
237
+ const el = pool[sel.nth];
238
+ return { el, matches_n: pool.length, match_level: "reidentified", target: targetDesc };
239
+ }
240
+ if (pool.length > 1) {
241
+ return {
242
+ errorEnvelope: err(ERROR_CODES.SELECTOR_AMBIGUOUS, `CSS matches ${pool.length} elements and no --nth given.`, {
243
+ matches_n: pool.length,
244
+ candidates: pool.slice(0, 5).map((el) => uniqueCssPath(el))
245
+ })
246
+ };
247
+ }
248
+ return { el: pool[0], matches_n: 1, match_level: "reidentified", target: targetDesc };
249
+ }
250
+ function suggestCandidates() {
251
+ const store = getRefStore();
252
+ const recent = Array.from(store.refs.entries()).slice(-5).map(([, el]) => uniqueCssPath(el));
253
+ return recent;
254
+ }
255
+ function compoundOf(el) {
256
+ const tag = el.tagName.toLowerCase();
257
+ if (tag === "input") {
258
+ const input = el;
259
+ const type = input.type;
260
+ if (["date", "time", "datetime-local", "month", "week"].includes(type)) {
261
+ const formatMap = {
262
+ date: "YYYY-MM-DD",
263
+ time: "HH:mm",
264
+ "datetime-local": "YYYY-MM-DDTHH:mm",
265
+ month: "YYYY-MM",
266
+ week: "YYYY-Www"
267
+ };
268
+ return {
269
+ control: type,
270
+ format: formatMap[type] ?? type,
271
+ current: input.value || "",
272
+ min: input.min || null,
273
+ max: input.max || null
274
+ };
275
+ }
276
+ if (type === "file") {
277
+ const current = Array.from(input.files ?? []).map((f) => f.name);
278
+ return { control: "file", multiple: input.multiple, current, accept: input.accept || null };
279
+ }
280
+ return null;
281
+ }
282
+ if (tag === "select") {
283
+ const select = el;
284
+ const options = Array.from(select.options).slice(0, 50).map((o) => ({
285
+ label: (o.textContent || "").trim(),
286
+ value: o.value,
287
+ selected: o.selected
288
+ }));
289
+ return {
290
+ control: "select",
291
+ multiple: select.multiple,
292
+ current: select.selectedOptions[0] ? (select.selectedOptions[0].textContent || "").trim() : "",
293
+ options,
294
+ options_total: select.options.length
295
+ };
296
+ }
297
+ return null;
298
+ }
299
+ var SKIP_TAGS = /* @__PURE__ */ new Set(["script", "style", "noscript", "meta", "link", "head", "base", "template", "path", "circle", "rect", "g", "defs", "polygon", "line"]);
300
+ function describeElement(el, ref) {
301
+ const tag = el.tagName.toLowerCase();
302
+ const role = el.getAttribute("role") ?? null;
303
+ const name = accessibleName(el);
304
+ const parts = [];
305
+ if (ref != null) parts.push(`[${ref}]`);
306
+ parts.push(tag);
307
+ if (role && role !== IMPLICIT_ROLE[tag]) parts.push(`role=${role}`);
308
+ if (tag === "input") {
309
+ const input = el;
310
+ if (input.type && input.type !== "text") parts.push(`[${input.type}]`);
311
+ if (input.disabled) parts.push("(disabled)");
312
+ }
313
+ if (name) parts.push(JSON.stringify(name.length > 60 ? name.slice(0, 57) + "\u2026" : name));
314
+ if (tag === "a") {
315
+ const href = el.getAttribute("href");
316
+ if (href) parts.push(`\u2192 ${href.slice(0, 50)}`);
317
+ }
318
+ if (el.disabled) parts.push("(disabled)");
319
+ return parts.join(" ");
320
+ }
321
+ function buildStateTree() {
322
+ const lines = [];
323
+ const compounds = {};
324
+ const budget = { nodes: 0, chars: 0, truncated: false };
325
+ const MAX_NODES = 400;
326
+ const MAX_CHARS = 9e3;
327
+ let hiddenInteractive = 0;
328
+ function emit(depth, text) {
329
+ const line = " ".repeat(Math.min(depth, 12)) + text;
330
+ lines.push(line);
331
+ budget.chars += line.length;
332
+ }
333
+ function walk(el, depth) {
334
+ if (budget.nodes >= MAX_NODES || budget.chars >= MAX_CHARS) {
335
+ budget.truncated = true;
336
+ return;
337
+ }
338
+ const tag = el.tagName.toLowerCase();
339
+ if (SKIP_TAGS.has(tag)) return;
340
+ budget.nodes++;
341
+ const visible = isVisible(el);
342
+ const interactive = isInteractive(el);
343
+ if (interactive) {
344
+ if (visible) {
345
+ const ref = allocRef(el);
346
+ emit(depth, describeElement(el, ref));
347
+ const compound = compoundOf(el);
348
+ if (compound) compounds[String(ref)] = compound;
349
+ } else {
350
+ hiddenInteractive++;
351
+ return;
352
+ }
353
+ } else if (visible) {
354
+ if (/^h[1-6]$/.test(tag)) {
355
+ const t = accessibleName(el);
356
+ if (t) emit(depth, `${"#".repeat(Number(tag[1]))} ${t}`);
357
+ } else if (tag === "p" || tag === "li" || tag === "td" || tag === "th" || tag === "figcaption" || tag === "blockquote") {
358
+ const ownText = ownTextOf(el);
359
+ if (ownText) emit(depth, ownText.slice(0, 100));
360
+ } else if (tag === "img") {
361
+ const alt = el.getAttribute("alt") || "";
362
+ if (alt) emit(depth, `img ${JSON.stringify(alt.slice(0, 60))}`);
363
+ }
364
+ }
365
+ if (depth < 14) {
366
+ for (const child of Array.from(el.children)) {
367
+ walk(child, depth + 1);
368
+ if (budget.truncated) return;
369
+ }
370
+ }
371
+ }
372
+ function ownTextOf(el) {
373
+ let text = "";
374
+ for (const node of Array.from(el.childNodes)) {
375
+ if (node.nodeType === Node.TEXT_NODE) text += node.textContent || "";
376
+ }
377
+ return text.replace(/\s+/g, " ").trim();
378
+ }
379
+ const root = document.querySelector("main") || document.querySelector("#root") || document.body;
380
+ emit(0, `# ${document.title}`);
381
+ walk(root, 0);
382
+ const scrollable = document.documentElement.scrollHeight > window.innerHeight + 200;
383
+ if (scrollable) {
384
+ emit(0, "\u2195 page is scrollable \u2014 run cp.scroll down to reveal more");
385
+ }
386
+ if (hiddenInteractive > 0) {
387
+ emit(0, `\u2139 ${hiddenInteractive} hidden interactive element(s) not tagged`);
388
+ }
389
+ if (budget.truncated) {
390
+ emit(0, "\u2026 (snapshot truncated by budget \u2014 narrow with a selector or scroll)");
391
+ }
392
+ return {
393
+ url: location.href,
394
+ title: document.title,
395
+ text: lines.join("\n"),
396
+ compounds,
397
+ hints: { scroll: scrollable, hidden_interactive: hiddenInteractive },
398
+ truncated: budget.truncated
399
+ };
400
+ }
401
+ function runControl(command, args) {
402
+ const a = args || {};
403
+ function getVisibleText(el) {
404
+ return (el.textContent || "").trim().replace(/\s+/g, " ").slice(0, 120);
405
+ }
406
+ function getAttrs(el) {
407
+ const attrs = {};
408
+ for (const name of ["id", "class", "name", "type", "href", "src", "placeholder", "value", "role", "aria-label", "data-testid"]) {
409
+ attrs[name] = el.getAttribute(name);
410
+ }
411
+ return attrs;
412
+ }
413
+ function sel() {
414
+ return {
415
+ ref: a.ref,
416
+ css: a.css,
417
+ nth: a.nth,
418
+ role: a.role,
419
+ name: a.name,
420
+ label: a.label,
421
+ text: a.text,
422
+ testid: a.testid
423
+ };
424
+ }
425
+ function findElements(findArgs) {
426
+ const limit = findArgs.limit ?? 20;
427
+ const textMax = findArgs["text-max"] ?? 120;
428
+ let elements = [];
429
+ if (findArgs.css) {
430
+ try {
431
+ elements = Array.from(document.querySelectorAll(findArgs.css));
432
+ } catch {
433
+ return err(ERROR_CODES.INVALID_SELECTOR, "CSS was rejected by querySelectorAll.", { selector: findArgs.css });
434
+ }
435
+ } else if (findArgs.testid) {
436
+ try {
437
+ elements = Array.from(document.querySelectorAll(testidSelector(findArgs.testid)));
438
+ } catch {
439
+ return err(ERROR_CODES.INVALID_SELECTOR, "Invalid testid.");
440
+ }
441
+ } else if (findArgs.role || findArgs.name || findArgs.label) {
442
+ const r = resolveTargetRich({ role: findArgs.role, name: findArgs.name, label: findArgs.label, text: findArgs.text });
443
+ if ("errorEnvelope" in r) return r.errorEnvelope;
444
+ elements = document.querySelectorAll("*").length ? semanticCandidates(findArgs) : [];
445
+ } else if (findArgs.text) {
446
+ const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
447
+ const lower = findArgs.text.toLowerCase();
448
+ const seen = /* @__PURE__ */ new Set();
449
+ let node;
450
+ while (node = walker.nextNode()) {
451
+ if (node.textContent?.toLowerCase().includes(lower)) {
452
+ const el = node.parentElement;
453
+ if (el && !seen.has(el)) {
454
+ seen.add(el);
455
+ elements.push(el);
456
+ if (elements.length >= limit) break;
457
+ }
458
+ }
459
+ }
460
+ } else {
461
+ elements = Array.from(document.querySelectorAll(INTERACTIVE_SELECTOR));
462
+ }
463
+ const out = elements.slice(0, limit).map((el, i) => {
464
+ const ref = allocRef(el);
465
+ return {
466
+ nth: i,
467
+ ref,
468
+ tag: el.tagName.toLowerCase(),
469
+ role: roleOf(el),
470
+ text: getVisibleText(el).slice(0, textMax),
471
+ attrs: getAttrs(el),
472
+ visible: isVisible(el),
473
+ compound: compoundOf(el) ?? void 0
474
+ };
475
+ });
476
+ return out;
477
+ }
478
+ function semanticCandidates(findArgs) {
479
+ const wantRole = findArgs.role ? findArgs.role.toLowerCase() : null;
480
+ const wantName = findArgs.name ? findArgs.name.toLowerCase() : null;
481
+ const wantText = findArgs.text ? findArgs.text.toLowerCase() : null;
482
+ const all = Array.from(document.querySelectorAll("*"));
483
+ return all.filter((el) => {
484
+ if (!isVisible(el)) return false;
485
+ if (wantRole) {
486
+ const role = roleOf(el);
487
+ if (!role || role.toLowerCase() !== wantRole) return false;
488
+ }
489
+ if (wantName && !accessibleName(el).toLowerCase().includes(wantName)) return false;
490
+ if (wantText && !(el.textContent || "").toLowerCase().includes(wantText)) return false;
491
+ return true;
492
+ });
493
+ }
494
+ function pageState() {
495
+ return {
496
+ url: location.href,
497
+ title: document.title,
498
+ width: window.innerWidth,
499
+ height: window.innerHeight,
500
+ devicePixelRatio: window.devicePixelRatio
501
+ };
502
+ }
503
+ function goto(gotoArgs) {
504
+ if (!gotoArgs.url) return { error: "url_required" };
505
+ let sameUrl = false;
506
+ try {
507
+ sameUrl = new URL(gotoArgs.url, window.location.href).href === window.location.href;
508
+ } catch {
509
+ sameUrl = false;
510
+ }
511
+ if (sameUrl) {
512
+ if (gotoArgs.reload === true) {
513
+ window.location.reload();
514
+ return { navigated: true, reloaded: true, url: gotoArgs.url };
515
+ }
516
+ return { navigated: false, reused: true, url: gotoArgs.url };
517
+ }
518
+ window.location.href = gotoArgs.url;
519
+ return { navigated: true, url: gotoArgs.url };
520
+ }
521
+ function evalScript(evalArgs) {
522
+ if (!evalArgs.script) return { error: "script_required" };
523
+ try {
524
+ const fn = new Function(evalArgs.script);
525
+ const result = fn();
526
+ return { result };
527
+ } catch (e) {
528
+ return { error: String(e) };
529
+ }
530
+ }
531
+ function fillElement(fArgs) {
532
+ const r = resolveTargetRich(sel());
533
+ if ("errorEnvelope" in r) return r.errorEnvelope;
534
+ const { el, matches_n, match_level, target } = r;
535
+ const input = el;
536
+ if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.isContentEditable) {
537
+ const isContentEditable = el.isContentEditable;
538
+ if (isContentEditable) {
539
+ el.innerText = fArgs.text ?? "";
540
+ } else {
541
+ input.value = fArgs.text ?? "";
542
+ }
543
+ input.dispatchEvent(new Event("input", { bubbles: true }));
544
+ input.dispatchEvent(new Event("change", { bubbles: true }));
545
+ const actual = isContentEditable ? el.innerText : input.value;
546
+ return actual === (fArgs.text ?? "") ? { filled: true, verified: true, text: fArgs.text, actual, target, matches_n, match_level } : err("verify_failed", "Input value diverged after fill (controlled component?).", { actual });
547
+ }
548
+ return err("invalid_type", "fill only supports input, textarea, and contenteditable.");
549
+ }
550
+ function typeElement(tArgs) {
551
+ const r = resolveTargetRich(sel());
552
+ if ("errorEnvelope" in r) return r.errorEnvelope;
553
+ const { el, matches_n, match_level, target } = r;
554
+ const input = el;
555
+ el.focus({ preventScroll: true });
556
+ input.value = tArgs.text ?? "";
557
+ input.dispatchEvent(new Event("input", { bubbles: true }));
558
+ input.dispatchEvent(new Event("change", { bubbles: true }));
559
+ let autocomplete = false;
560
+ try {
561
+ autocomplete = !!document.querySelector("[role='listbox'], [role='combobox'] [role='listbox'], datalist, .ant-select-dropdown:not([style*='hidden']), [id^='listbox']");
562
+ } catch {
563
+ }
564
+ return { typed: true, text: tArgs.text, target, matches_n, match_level, autocomplete };
565
+ }
566
+ function clickElement() {
567
+ const r = resolveTargetRich(sel());
568
+ if ("errorEnvelope" in r) return r.errorEnvelope;
569
+ const { el, matches_n, match_level, target } = r;
570
+ el.scrollIntoView({ block: "center" });
571
+ if (a.full === true) {
572
+ const rect = el.getBoundingClientRect();
573
+ const opts = {
574
+ bubbles: true,
575
+ cancelable: true,
576
+ view: window,
577
+ clientX: rect.x + rect.width / 2,
578
+ clientY: rect.y + rect.height / 2,
579
+ button: 0,
580
+ buttons: 1,
581
+ pointerId: 1,
582
+ pointerType: "mouse",
583
+ isPrimary: true
584
+ };
585
+ el.dispatchEvent(new PointerEvent("pointerdown", opts));
586
+ el.dispatchEvent(new MouseEvent("mousedown", opts));
587
+ el.dispatchEvent(new PointerEvent("pointerup", { ...opts, buttons: 0 }));
588
+ el.dispatchEvent(new MouseEvent("mouseup", { ...opts, buttons: 0 }));
589
+ el.dispatchEvent(new MouseEvent("click", { ...opts, buttons: 0 }));
590
+ return { clicked: true, full: true, target, matches_n, match_level, tag: el.tagName.toLowerCase(), text: getVisibleText(el) };
591
+ }
592
+ el.click();
593
+ return { clicked: true, target, matches_n, match_level, tag: el.tagName.toLowerCase(), text: getVisibleText(el) };
594
+ }
595
+ function selectElement(sArgs) {
596
+ const r = resolveTargetRich(sel());
597
+ if ("errorEnvelope" in r) return r.errorEnvelope;
598
+ const { el, matches_n, match_level, target } = r;
599
+ if (el.tagName !== "SELECT") {
600
+ return err(ERROR_CODES.NOT_A_SELECT, "select was called on a non-<select> element.", { tag: el.tagName.toLowerCase() });
601
+ }
602
+ const select = el;
603
+ const want = sArgs.label ?? sArgs.value ?? sArgs.option;
604
+ if (!want) return err("option_required", "Provide label or value.");
605
+ const byLabel = Array.from(select.options).find((o) => (o.textContent || "").trim() === want);
606
+ const byValue = Array.from(select.options).find((o) => o.value === want);
607
+ const opt = byLabel ?? byValue;
608
+ if (!opt) {
609
+ const available = Array.from(select.options).slice(0, 50).map((o) => (o.textContent || "").trim());
610
+ return err(ERROR_CODES.OPTION_NOT_FOUND, "Option not found.", { available });
611
+ }
612
+ select.value = opt.value;
613
+ select.dispatchEvent(new Event("input", { bubbles: true }));
614
+ select.dispatchEvent(new Event("change", { bubbles: true }));
615
+ return { selected: true, value: select.value, target, matches_n, match_level };
616
+ }
617
+ function pressKeys(kArgs) {
618
+ const keyCombo = kArgs.keys ?? kArgs.key ?? "";
619
+ if (!keyCombo) return { error: "keys_required" };
620
+ const comboParts = keyCombo.split("+").map((s) => s.trim());
621
+ const main = comboParts[comboParts.length - 1];
622
+ const ctrl = comboParts.includes("Control") || comboParts.includes("Ctrl") || comboParts.includes("Meta") || comboParts.includes("Cmd");
623
+ const alt = comboParts.includes("Alt");
624
+ const shift = comboParts.includes("Shift");
625
+ const target = document.activeElement ?? document.body;
626
+ const opts = { key: main, bubbles: true, cancelable: true, ctrlKey: ctrl, altKey: alt, shiftKey: shift, metaKey: comboParts.includes("Meta") || comboParts.includes("Cmd") };
627
+ target.dispatchEvent(new KeyboardEvent("keydown", opts));
628
+ target.dispatchEvent(new KeyboardEvent("keypress", opts));
629
+ target.dispatchEvent(new KeyboardEvent("keyup", opts));
630
+ return { pressed: true, key: keyCombo };
631
+ }
632
+ function hoverElement() {
633
+ const r = resolveTargetRich(sel());
634
+ if ("errorEnvelope" in r) return r.errorEnvelope;
635
+ const { el, matches_n, match_level, target } = r;
636
+ const rect = el.getBoundingClientRect();
637
+ const opts = { bubbles: true, cancelable: true, clientX: rect.x + rect.width / 2, clientY: rect.y + rect.height / 2 };
638
+ el.dispatchEvent(new MouseEvent("mouseover", opts));
639
+ el.dispatchEvent(new MouseEvent("mousemove", opts));
640
+ return { hovered: true, target, matches_n, match_level };
641
+ }
642
+ function focusElement() {
643
+ const r = resolveTargetRich(sel());
644
+ if ("errorEnvelope" in r) return r.errorEnvelope;
645
+ const { el, matches_n, match_level, target } = r;
646
+ el.focus({ preventScroll: true });
647
+ return { focused: true, target, matches_n, match_level };
648
+ }
649
+ function dblclickElement() {
650
+ const r = resolveTargetRich(sel());
651
+ if ("errorEnvelope" in r) return r.errorEnvelope;
652
+ const { el, matches_n, match_level, target } = r;
653
+ el.dispatchEvent(new MouseEvent("dblclick", { bubbles: true, cancelable: true }));
654
+ return { dblclicked: true, target, matches_n, match_level };
655
+ }
656
+ function setChecked(want) {
657
+ const r = resolveTargetRich(sel());
658
+ if ("errorEnvelope" in r) return r.errorEnvelope;
659
+ const { el, matches_n, match_level, target } = r;
660
+ const input = el;
661
+ const isAria = input.type !== "checkbox" && input.type !== "radio" && el.getAttribute("aria-checked") != null;
662
+ if (!isAria && input.type !== "checkbox" && input.type !== "radio") {
663
+ return err("invalid_type", "Target is not a checkbox/radio/aria-checked control.", { tag: el.tagName.toLowerCase() });
664
+ }
665
+ if (isAria) {
666
+ el.setAttribute("aria-checked", String(want));
667
+ el.dispatchEvent(new Event("change", { bubbles: true }));
668
+ return { [want ? "checked" : "unchecked"]: true, changed: true, target, matches_n, match_level, kind: "aria" };
669
+ }
670
+ if (input.type === "radio" && !want) {
671
+ return err("invalid_type", "Radio buttons cannot be unchecked directly; select another radio in the group.");
672
+ }
673
+ const changed = input.checked !== want;
674
+ input.checked = want;
675
+ input.dispatchEvent(new Event("input", { bubbles: true }));
676
+ input.dispatchEvent(new Event("change", { bubbles: true }));
677
+ return { [want ? "checked" : "unchecked"]: true, changed, target, matches_n, match_level, kind: input.type };
678
+ }
679
+ function scrollElement(sArgs) {
680
+ const dir = sArgs.direction ?? "down";
681
+ const amount = sArgs.amount ?? 500;
682
+ if (dir !== "up" && dir !== "down") return { error: "invalid_direction" };
683
+ const dy = dir === "down" ? amount : -amount;
684
+ window.scrollBy({ top: dy, behavior: "instant" });
685
+ return {
686
+ scrolled: true,
687
+ direction: dir,
688
+ amount,
689
+ scrollY: Math.round(window.scrollY),
690
+ scrollHeight: document.documentElement.scrollHeight
691
+ };
692
+ }
693
+ function backNav() {
694
+ history.back();
695
+ return { back: true };
696
+ }
697
+ function htmlJsonTree(el, depth, maxDepth, childrenMax, textMax, truncated) {
698
+ const children = Array.from(el.children);
699
+ const ownText = (el.textContent || "").replace(/\s+/g, " ").trim();
700
+ const node = {
701
+ tag: el.tagName.toLowerCase(),
702
+ attrs: getAttrs(el),
703
+ text: ownText.length > textMax ? (ownText.slice(0, textMax), truncated.text_truncated = (truncated.text_truncated || 0) + 1, ownText.slice(0, textMax)) : ownText,
704
+ children: [],
705
+ compound: compoundOf(el) ?? void 0
706
+ };
707
+ if (depth < maxDepth) {
708
+ let kids = children;
709
+ if (children.length > childrenMax) {
710
+ truncated.children_dropped = (truncated.children_dropped || 0) + (children.length - childrenMax);
711
+ kids = children.slice(0, childrenMax);
712
+ }
713
+ node.children = kids.map((c) => htmlJsonTree(c, depth + 1, maxDepth, childrenMax, textMax, truncated));
714
+ } else if (children.length) {
715
+ truncated.depth = (truncated.depth || 0) + 1;
716
+ }
717
+ return node;
718
+ }
719
+ function getElement(gArgs) {
720
+ const what = gArgs.what ?? "text";
721
+ if (what === "title") return { value: document.title, matches_n: 1, match_level: "exact" };
722
+ if (what === "url") return { value: location.href, matches_n: 1, match_level: "exact" };
723
+ if (what === "html") {
724
+ if (gArgs["as"] === "json") {
725
+ const root2 = gArgs.css ? document.querySelector(gArgs.css) : document.body;
726
+ if (!root2) return err(ERROR_CODES.SELECTOR_NOT_FOUND, "CSS matches 0 elements.", { selector: gArgs.css });
727
+ const truncated = {};
728
+ const tree = htmlJsonTree(root2, 0, gArgs.depth ?? 6, gArgs["children-max"] ?? 20, gArgs["text-max"] ?? 200, truncated);
729
+ return {
730
+ value: tree,
731
+ truncated: Object.keys(truncated).length ? truncated : void 0
732
+ };
733
+ }
734
+ const root = gArgs.css ? document.querySelector(gArgs.css) : document.body;
735
+ if (!root) return err(ERROR_CODES.SELECTOR_NOT_FOUND, "CSS matches 0 elements.", { selector: gArgs.css });
736
+ let html = root.outerHTML;
737
+ if (gArgs.max && html.length > gArgs.max) html = html.slice(0, gArgs.max) + "\u2026";
738
+ return { value: html };
739
+ }
740
+ const r = resolveTargetRich(gArgs);
741
+ if ("errorEnvelope" in r) return r.errorEnvelope;
742
+ const { el, matches_n, match_level } = r;
743
+ switch (what) {
744
+ case "text": {
745
+ const t = getVisibleText(el);
746
+ return { value: t.length > 2e3 ? t.slice(0, 2e3) : t, matches_n, match_level };
747
+ }
748
+ case "value":
749
+ return { value: el.value ?? el.innerText ?? null, matches_n, match_level };
750
+ case "attributes":
751
+ return { value: getAttrs(el), matches_n, match_level };
752
+ default:
753
+ return { error: `unknown_what: ${what}` };
754
+ }
755
+ }
756
+ function extractMarkdown(eArgs) {
757
+ const chunkSize = eArgs["chunk-size"] ?? 0;
758
+ const start = eArgs.start ?? 0;
759
+ const scope = eArgs.selector ? document.querySelector(eArgs.selector) : document.querySelector("main") || document.querySelector("article") || document.body;
760
+ if (!scope) return { error: "scope_not_found" };
761
+ const parts = [];
762
+ const walker = document.createTreeWalker(scope, NodeFilter.SHOW_ELEMENT);
763
+ let node;
764
+ while (node = walker.nextNode()) {
765
+ const el = node;
766
+ const tag = el.tagName.toLowerCase();
767
+ const text = getVisibleText(el);
768
+ if (!text) continue;
769
+ if (tag === "h1") parts.push(`# ${text}`);
770
+ else if (tag === "h2") parts.push(`## ${text}`);
771
+ else if (tag === "h3") parts.push(`### ${text}`);
772
+ else if (tag === "p" || tag === "li") parts.push(text);
773
+ else if (tag === "a") parts.push(`[${text}](${el.getAttribute("href") ?? ""})`);
774
+ }
775
+ const full = parts.join("\n\n");
776
+ const sliced = chunkSize > 0 ? full.slice(start, start + chunkSize) : full.slice(start);
777
+ return {
778
+ url: location.href,
779
+ title: document.title,
780
+ selector: eArgs.selector ?? "auto",
781
+ total_chars: full.length,
782
+ chunk_size: chunkSize,
783
+ start,
784
+ end: start + sliced.length,
785
+ next_start_char: start + sliced.length < full.length ? start + sliced.length : null,
786
+ content: sliced
787
+ };
788
+ }
789
+ function listFrames() {
790
+ const frames = Array.from(document.querySelectorAll("iframe")).map((f, index) => {
791
+ const src = f.getAttribute("src") ?? "";
792
+ let crossOrigin = false;
793
+ try {
794
+ if (src && /^https?:/.test(src)) crossOrigin = new URL(src, location.href).origin !== location.origin;
795
+ } catch {
796
+ }
797
+ return { index, url: src, name: f.getAttribute("name") ?? "", cross_origin: crossOrigin };
798
+ });
799
+ return { frames };
800
+ }
801
+ function screenshotMeta() {
802
+ return {
803
+ width: window.innerWidth,
804
+ height: window.innerHeight,
805
+ url: location.href,
806
+ title: document.title
807
+ };
808
+ }
809
+ function startTitleMarquee(tArgs) {
810
+ const g2 = globalThis;
811
+ if (g2.__cpMarquee) {
812
+ clearInterval(g2.__cpMarquee.interval);
813
+ } else {
814
+ g2.__cpMarquee = { original: document.title, interval: 0 };
815
+ }
816
+ const prefix = tArgs.text ?? "\u{1F916}";
817
+ const base = g2.__cpMarquee.original;
818
+ const full = `${prefix} ${base}`;
819
+ const speed = Math.max(100, Math.min(2e3, tArgs.speed ?? 300));
820
+ let pos = 0;
821
+ const tick = () => {
822
+ const display = full.slice(pos) + " " + full.slice(0, pos);
823
+ document.title = display.slice(0, 60);
824
+ pos = (pos + 1) % (full.length + 1 || 1);
825
+ };
826
+ tick();
827
+ g2.__cpMarquee.interval = window.setInterval(tick, speed);
828
+ return { started: true, original: base, prefix, speed };
829
+ }
830
+ function stopTitleMarquee() {
831
+ const g2 = globalThis;
832
+ const state = g2.__cpMarquee;
833
+ if (!state) return { restored: false, reason: "no_active_marquee" };
834
+ clearInterval(state.interval);
835
+ document.title = state.original;
836
+ delete g2.__cpMarquee;
837
+ return { restored: true, original: state.original };
838
+ }
839
+ function networkEntriesLegacy(nArgs) {
840
+ const all = performance.getEntriesByType("resource").map((e) => ({
841
+ url: e.name,
842
+ type: e.initiatorType ?? "unknown",
843
+ duration: Math.round(e.duration)
844
+ }));
845
+ let entries = all;
846
+ if (nArgs.filter) {
847
+ const keywords = nArgs.filter.split(",").map((s) => s.trim().toLowerCase());
848
+ entries = all.filter((e) => keywords.some((kw) => e.url.toLowerCase().includes(kw)));
849
+ }
850
+ return { entries, count: entries.length, source: "performance-api" };
851
+ }
852
+ async function waitForCondition(wArgs) {
853
+ const timeout = wArgs.timeout ?? 1e4;
854
+ if (wArgs.time != null) {
855
+ await new Promise((res) => setTimeout(res, Math.min(wArgs.time * 1e3, 3e4)));
856
+ return { waited: true, kind: "time", seconds: wArgs.time };
857
+ }
858
+ const deadline = Date.now() + timeout;
859
+ const pollInterval = 200;
860
+ if (wArgs.selector) {
861
+ while (Date.now() < deadline) {
862
+ if (document.querySelector(wArgs.selector)) return { waited: true, kind: "selector", selector: wArgs.selector, elapsedMs: timeout - (deadline - Date.now()) };
863
+ await new Promise((res) => setTimeout(res, pollInterval));
864
+ }
865
+ return err("wait_timeout", `Selector not found within ${timeout}ms.`, { selector: wArgs.selector });
866
+ }
867
+ if (wArgs.text) {
868
+ const lower = wArgs.text.toLowerCase();
869
+ while (Date.now() < deadline) {
870
+ if ((document.body.textContent || "").toLowerCase().includes(lower)) {
871
+ return { waited: true, kind: "text", text: wArgs.text, elapsedMs: timeout - (deadline - Date.now()) };
872
+ }
873
+ await new Promise((res) => setTimeout(res, pollInterval));
874
+ }
875
+ return err("wait_timeout", `Text not found within ${timeout}ms.`, { text: wArgs.text });
876
+ }
877
+ return { error: "no_condition" };
878
+ }
879
+ function uploadFiles(uArgs) {
880
+ const r = resolveTargetRich(sel());
881
+ if ("errorEnvelope" in r) return r.errorEnvelope;
882
+ const { el, matches_n, match_level, target } = r;
883
+ const input = el;
884
+ if (input.type !== "file") return err("invalid_type", "Target is not an input[type=file].", { tag: el.tagName.toLowerCase() });
885
+ try {
886
+ const dt = new DataTransfer();
887
+ for (const name of uArgs.files ?? []) {
888
+ dt.items.add(new File([""], name.split("/").pop() || name));
889
+ }
890
+ input.files = dt.files;
891
+ } catch {
892
+ }
893
+ input.dispatchEvent(new Event("change", { bubbles: true }));
894
+ return {
895
+ uploaded: true,
896
+ files: uArgs.files ?? [],
897
+ file_names: (uArgs.files ?? []).map((f) => f.split("/").pop()),
898
+ target,
899
+ matches_n,
900
+ match_level,
901
+ multiple: input.multiple,
902
+ accept: input.accept || null
903
+ };
904
+ }
905
+ function dragElements(dArgs) {
906
+ const r1 = resolveTargetRich(sel());
907
+ if ("errorEnvelope" in r1) return r1.errorEnvelope;
908
+ const r2 = resolveTargetRich({ ref: dArgs.ref2, css: dArgs.css2 });
909
+ if ("errorEnvelope" in r2) return r2.errorEnvelope;
910
+ const src = r1.el;
911
+ const tgt = r2.el;
912
+ const make = (type) => {
913
+ const r1rect = src.getBoundingClientRect();
914
+ return new DragEvent(type, { bubbles: true, cancelable: true, clientX: r1rect.x + r1rect.width / 2, clientY: r1rect.y + r1rect.height / 2 });
915
+ };
916
+ src.dispatchEvent(make("dragstart"));
917
+ tgt.dispatchEvent(new DragEvent("dragenter", { bubbles: true }));
918
+ tgt.dispatchEvent(new DragEvent("dragover", { bubbles: true, cancelable: true }));
919
+ tgt.dispatchEvent(new DragEvent("drop", { bubbles: true, cancelable: true }));
920
+ src.dispatchEvent(new DragEvent("dragend", { bubbles: true }));
921
+ return { dragged: true, source: String(sel().ref ?? sel().css ?? ""), target: String(dArgs.ref2 ?? dArgs.css2 ?? ""), source_matches_n: r1.matches_n, target_matches_n: r2.matches_n };
922
+ }
923
+ switch (command) {
924
+ case "cp.state":
925
+ return a.tree === false ? pageState() : buildStateTree();
926
+ case "cp.snapshot":
927
+ return buildStateTree();
928
+ case "cp.find":
929
+ return findElements({
930
+ css: a.css,
931
+ text: a.text,
932
+ limit: a.limit,
933
+ role: a.role,
934
+ name: a.name,
935
+ label: a.label,
936
+ testid: a.testid,
937
+ "text-max": a["text-max"]
938
+ });
939
+ case "cp.click":
940
+ return clickElement();
941
+ case "cp.type":
942
+ return typeElement({ text: a.text });
943
+ case "cp.goto":
944
+ return goto({ url: a.url });
945
+ case "cp.eval":
946
+ return evalScript({ script: a.script });
947
+ case "cp.fill":
948
+ return fillElement({ text: a.text });
949
+ case "cp.select":
950
+ return selectElement({ label: a.label, value: a.value, option: a.option });
951
+ case "cp.keys":
952
+ return pressKeys({ keys: a.keys, key: a.key });
953
+ case "cp.hover":
954
+ return hoverElement();
955
+ case "cp.focus":
956
+ return focusElement();
957
+ case "cp.dblclick":
958
+ return dblclickElement();
959
+ case "cp.check":
960
+ return setChecked(true);
961
+ case "cp.uncheck":
962
+ return setChecked(false);
963
+ case "cp.scroll":
964
+ return scrollElement({ direction: a.direction, amount: a.amount });
965
+ case "cp.back":
966
+ return backNav();
967
+ case "cp.get":
968
+ return getElement({
969
+ what: a.what,
970
+ css: a.css,
971
+ ref: a.ref,
972
+ nth: a.nth,
973
+ "as": a["as"],
974
+ depth: a.depth,
975
+ "children-max": a["children-max"],
976
+ "text-max": a["text-max"],
977
+ max: a.max,
978
+ role: a.role,
979
+ name: a.name,
980
+ label: a.label,
981
+ text: a.text,
982
+ testid: a.testid
983
+ });
984
+ case "cp.extract":
985
+ return extractMarkdown({
986
+ "chunk-size": a["chunk-size"],
987
+ start: a.start,
988
+ selector: a.selector
989
+ });
990
+ case "cp.frames":
991
+ return listFrames();
992
+ case "cp.screenshot":
993
+ return screenshotMeta();
994
+ case "cp.network":
995
+ return networkEntriesLegacy({ filter: a.filter });
996
+ case "cp.wait":
997
+ return waitForCondition({
998
+ selector: a.selector,
999
+ text: a.text,
1000
+ time: a.time,
1001
+ timeout: a.timeout
1002
+ });
1003
+ case "cp.upload":
1004
+ return uploadFiles({ files: a.files });
1005
+ case "cp.drag":
1006
+ return dragElements({ ref2: a.ref2, css2: a.css2 });
1007
+ case "cp.title.marquee":
1008
+ return startTitleMarquee({ text: a.text, speed: a.speed });
1009
+ case "cp.title.restore":
1010
+ return stopTitleMarquee();
1011
+ default:
1012
+ return { error: `unknown_command: ${command}` };
1013
+ }
1014
+ }
1015
+ var RUNTIME_VERSION = "0.3.0-opencli-parity";
1016
+ globalThis.__cpRunControl = runControl;
1017
+ globalThis.__cpRuntimeVersion = RUNTIME_VERSION;
1018
+
1019
+ // src/background/control-runtime-bridge.ts
1020
+ var g = globalThis;
1021
+ var existing = g.__hmControlRuntime;
1022
+ if (!existing || existing.version !== RUNTIME_VERSION) {
1023
+ g.__hmControlRuntime = {
1024
+ version: RUNTIME_VERSION,
1025
+ runControl
1026
+ };
1027
+ }
1028
+ })();