@cyberstrike-io/cyberstrike-darwin-arm64 1.1.14 → 1.1.15-beta.1

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/bin/cyberstrike CHANGED
Binary file
@@ -30981,7 +30981,8 @@ async function handle2FA(page) {
30981
30981
  }
30982
30982
  return false;
30983
30983
  }
30984
- async function waitForManualLogin(page, label) {
30984
+ var savedBtnPos = null;
30985
+ async function waitForManualLogin(page, label, progress) {
30985
30986
  let resolveReady;
30986
30987
  const readyPromise = new Promise((resolve3) => {
30987
30988
  resolveReady = resolve3;
@@ -30990,12 +30991,19 @@ async function waitForManualLogin(page, label) {
30990
30991
  await page.exposeFunction(callbackName, () => {
30991
30992
  resolveReady();
30992
30993
  });
30993
- const topLine = label ? `// ${label.toUpperCase()} · LOGIN MANUALLY ⟶ CLICK` : `// LOGIN MANUALLY ⟶ CLICK`;
30994
- const buttonText = "START SCAN";
30994
+ const posCallbackName = label ? `__cyberstrikePos_${label}` : "__cyberstrikePos";
30995
+ await page.exposeFunction(posCallbackName, (left, top) => {
30996
+ savedBtnPos = { left, top };
30997
+ });
30998
+ const isFinal = !progress || progress.index >= progress.total - 1;
30999
+ const step = progress ? ` (${progress.index + 1}/${progress.total})` : "";
31000
+ const who = label ? label.toUpperCase() : "LOGIN";
31001
+ const topLine = isFinal ? `// ${who}${step} · LOGIN MANUALLY ⟶ START SCAN` : `// ${who}${step} · LOGIN MANUALLY ⟶ CONFIRM & NEXT`;
31002
+ const buttonText = isFinal ? "START SCAN" : "CONFIRM & NEXT ⟶";
30995
31003
  const buttonId = label ? `__cyberstrike-ready-btn-${label}` : "__cyberstrike-ready-btn";
30996
31004
  const styleId = "__cyberstrike-ready-btn-style";
30997
31005
  const injectButton = async () => {
30998
- await page.evaluate(({ btnId, btnText, topText, cbName, styleElId }) => {
31006
+ await page.evaluate(({ btnId, btnText, topText, cbName, styleElId, posCb, savedPos, isFinal: isFinal2 }) => {
30999
31007
  if (document.getElementById(btnId))
31000
31008
  return;
31001
31009
  if (!document.getElementById(styleElId)) {
@@ -31022,9 +31030,8 @@ async function waitForManualLogin(page, label) {
31022
31030
  `;
31023
31031
  document.head.appendChild(style);
31024
31032
  }
31025
- const btn = document.createElement("button");
31033
+ const btn = document.createElement("div");
31026
31034
  btn.id = btnId;
31027
- btn.type = "button";
31028
31035
  btn.style.cssText = [
31029
31036
  "all: initial",
31030
31037
  "position: fixed",
@@ -31040,17 +31047,29 @@ async function waitForManualLogin(page, label) {
31040
31047
  "border: 1px solid #1f2937",
31041
31048
  "color: #e5e7eb",
31042
31049
  "font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, Consolas, ui-monospace, monospace",
31043
- "cursor: pointer",
31050
+ "cursor: grab",
31044
31051
  "user-select: none",
31052
+ "touch-action: none",
31045
31053
  "box-shadow: 0 0 0 1px rgba(34,211,238,0.15), 0 0 20px rgba(34,211,238,0.25), 0 8px 24px rgba(0,0,0,0.5)",
31046
31054
  "transition: box-shadow 180ms ease-out, background 180ms ease-out",
31047
31055
  "-webkit-font-smoothing: antialiased"
31048
31056
  ].join(";");
31057
+ if (savedPos) {
31058
+ btn.style.left = savedPos.left + "px";
31059
+ btn.style.top = savedPos.top + "px";
31060
+ btn.style.right = "auto";
31061
+ }
31049
31062
  for (const corner of ["tl", "tr", "bl", "br"]) {
31050
31063
  const b = document.createElement("span");
31051
31064
  b.className = `__cs-br ${corner}`;
31052
31065
  btn.appendChild(b);
31053
31066
  }
31067
+ const topRow = document.createElement("span");
31068
+ topRow.style.cssText = "display: flex; align-items: center; gap: 8px;";
31069
+ const grip = document.createElement("span");
31070
+ grip.textContent = "⠿";
31071
+ grip.setAttribute("aria-hidden", "true");
31072
+ grip.style.cssText = "font-size: 12px; color: #22d3ee; opacity: 0.55; cursor: grab;";
31054
31073
  const meta = document.createElement("span");
31055
31074
  meta.textContent = topText;
31056
31075
  meta.style.cssText = [
@@ -31060,9 +31079,20 @@ async function waitForManualLogin(page, label) {
31060
31079
  "opacity: 0.75",
31061
31080
  "text-transform: uppercase"
31062
31081
  ].join(";");
31063
- btn.appendChild(meta);
31064
- const row = document.createElement("span");
31065
- row.style.cssText = "display: flex; align-items: center; gap: 8px;";
31082
+ topRow.appendChild(grip);
31083
+ topRow.appendChild(meta);
31084
+ btn.appendChild(topRow);
31085
+ const action = document.createElement("button");
31086
+ action.type = "button";
31087
+ action.setAttribute("aria-label", isFinal2 ? "Start scan" : "Confirm login and open next");
31088
+ action.style.cssText = [
31089
+ "all: unset",
31090
+ "display: flex",
31091
+ "align-items: center",
31092
+ "gap: 8px",
31093
+ "cursor: pointer",
31094
+ "padding: 2px 0"
31095
+ ].join(";");
31066
31096
  const dot = document.createElement("span");
31067
31097
  dot.style.cssText = [
31068
31098
  "display: inline-block",
@@ -31082,23 +31112,102 @@ async function waitForManualLogin(page, label) {
31082
31112
  "color: #22d3ee",
31083
31113
  "text-transform: uppercase"
31084
31114
  ].join(";");
31085
- row.appendChild(dot);
31086
- row.appendChild(txt);
31087
- btn.appendChild(row);
31088
- btn.addEventListener("click", () => {
31115
+ action.appendChild(dot);
31116
+ action.appendChild(txt);
31117
+ btn.appendChild(action);
31118
+ const hint = document.createElement("span");
31119
+ hint.textContent = "drag ⠿ to move";
31120
+ hint.style.cssText = ["font-size: 8px", "letter-spacing: 0.1em", "color: #6b7280", "margin-top: 1px"].join(";");
31121
+ btn.appendChild(hint);
31122
+ let dragging = false;
31123
+ let moved = false;
31124
+ let sx = 0;
31125
+ let sy = 0;
31126
+ let ox = 0;
31127
+ let oy = 0;
31128
+ let dragEndedAt = 0;
31129
+ btn.addEventListener("pointerdown", (e) => {
31130
+ if (action.contains(e.target))
31131
+ return;
31132
+ dragging = true;
31133
+ moved = false;
31134
+ const r = btn.getBoundingClientRect();
31135
+ ox = r.left;
31136
+ oy = r.top;
31137
+ sx = e.clientX;
31138
+ sy = e.clientY;
31139
+ btn.style.left = ox + "px";
31140
+ btn.style.top = oy + "px";
31141
+ btn.style.right = "auto";
31142
+ btn.style.cursor = "grabbing";
31143
+ btn.setPointerCapture(e.pointerId);
31144
+ e.preventDefault();
31145
+ });
31146
+ btn.addEventListener("pointermove", (e) => {
31147
+ if (!dragging)
31148
+ return;
31149
+ const dx = e.clientX - sx;
31150
+ const dy = e.clientY - sy;
31151
+ if (Math.abs(dx) + Math.abs(dy) > 4)
31152
+ moved = true;
31153
+ const w = btn.offsetWidth;
31154
+ const h = btn.offsetHeight;
31155
+ btn.style.left = Math.max(0, Math.min(window.innerWidth - w, ox + dx)) + "px";
31156
+ btn.style.top = Math.max(0, Math.min(window.innerHeight - h, oy + dy)) + "px";
31157
+ });
31158
+ const endDrag = (e) => {
31159
+ if (!dragging)
31160
+ return;
31161
+ dragging = false;
31162
+ btn.style.cursor = "grab";
31163
+ try {
31164
+ btn.releasePointerCapture(e.pointerId);
31165
+ } catch {}
31166
+ if (moved) {
31167
+ dragEndedAt = Date.now();
31168
+ const r = btn.getBoundingClientRect();
31169
+ window[posCb](r.left, r.top);
31170
+ }
31171
+ };
31172
+ btn.addEventListener("pointerup", endDrag);
31173
+ btn.addEventListener("pointercancel", endDrag);
31174
+ action.addEventListener("click", () => {
31175
+ if (Date.now() - dragEndedAt < 350)
31176
+ return;
31089
31177
  window[cbName]();
31090
- meta.textContent = "// SCANNING…";
31091
- txt.textContent = "INITIATED";
31178
+ meta.textContent = isFinal2 ? "// SCANNING…" : "// LOGIN CONFIRMED";
31179
+ txt.textContent = isFinal2 ? "INITIATED" : "NEXT LOGIN ⟶";
31092
31180
  dot.style.animation = "none";
31093
31181
  dot.style.background = "#6b7280";
31094
31182
  dot.style.boxShadow = "none";
31095
31183
  txt.style.color = "#9ca3af";
31096
31184
  meta.style.color = "#6b7280";
31185
+ action.style.cursor = "default";
31097
31186
  btn.style.cursor = "default";
31098
31187
  btn.style.opacity = "0.7";
31188
+ hint.style.display = "none";
31099
31189
  });
31100
31190
  document.body.appendChild(btn);
31101
- }, { btnId: buttonId, btnText: buttonText, topText: topLine, cbName: callbackName, styleElId: styleId }).catch(() => {});
31191
+ {
31192
+ const w = btn.offsetWidth;
31193
+ const h = btn.offsetHeight;
31194
+ const curLeft = parseFloat(btn.style.left || "");
31195
+ const curTop = parseFloat(btn.style.top || "");
31196
+ if (!Number.isNaN(curLeft))
31197
+ btn.style.left = Math.max(0, Math.min(window.innerWidth - w, curLeft)) + "px";
31198
+ if (!Number.isNaN(curTop))
31199
+ btn.style.top = Math.max(0, Math.min(window.innerHeight - h, curTop)) + "px";
31200
+ }
31201
+ }, {
31202
+ btnId: buttonId,
31203
+ btnText: buttonText,
31204
+ topText: topLine,
31205
+ cbName: callbackName,
31206
+ styleElId: styleId,
31207
+ posCb: posCallbackName,
31208
+ savedPos: savedBtnPos,
31209
+ isFinal
31210
+ }).catch(() => {});
31102
31211
  };
31103
31212
  await injectButton();
31104
31213
  page.on("load", injectButton);
@@ -40912,8 +41021,9 @@ function classifyAuthUrl(url2) {
40912
41021
  return null;
40913
41022
  }
40914
41023
  var INPUT_ROLES = new Set(["textbox", "combobox", "checkbox", "radio", "slider"]);
41024
+ var ACTION_ROLES = new Set(["button", "menuitem", "tab"]);
40915
41025
  function generateFingerprint(elements) {
40916
- return elements.filter((e) => INPUT_ROLES.has(e.role)).map((e) => `${e.role}:${e.label}:${e.type}:${e.enabled}`).sort().join("|");
41026
+ return elements.filter((e) => INPUT_ROLES.has(e.role) || ACTION_ROLES.has(e.role) && !e.inChrome).map((e) => `${e.role}:${e.label}:${e.type}:${e.enabled}`).sort().join("|");
40917
41027
  }
40918
41028
  function generateFullFingerprint(elements) {
40919
41029
  return elements.filter((e) => e.label && e.role !== "link" && e.role !== "info").map((e) => [e.role, e.label, e.type, e.enabled, e.options || "", e.placeholder || ""].join(":")).sort().join("|");
@@ -41000,8 +41110,31 @@ function buildPlannerSnapshot(url2, elements, globalState, credId, viewportCente
41000
41110
  // ../hackbrowser/src/scanner.ts
41001
41111
  var log4 = Log.create({ service: "hackbrowser:scanner" });
41002
41112
  var MAX_ELEMENTS = 50;
41113
+ var MAX_PER_TEMPLATE = 5;
41114
+ var REVEAL_MAX_STEPS = 10;
41115
+ var REVEAL_STEP_WAIT = 250;
41116
+ var EXPAND_MAX = 20;
41003
41117
  async function collectInteractiveElements(page) {
41004
41118
  return page.evaluate(() => {
41119
+ const FRAMEWORK_CLICK_ATTRS = [
41120
+ "wire:click",
41121
+ "hx-get",
41122
+ "hx-post",
41123
+ "hx-put",
41124
+ "hx-patch",
41125
+ "hx-delete",
41126
+ "ng-click",
41127
+ "x-on:click",
41128
+ "@click",
41129
+ "data-toggle",
41130
+ "data-bs-toggle",
41131
+ "data-hx-get",
41132
+ "data-hx-post",
41133
+ "data-hx-put",
41134
+ "data-hx-patch",
41135
+ "data-hx-delete",
41136
+ "data-ng-click"
41137
+ ];
41005
41138
  function isStructurallyVisible(el) {
41006
41139
  const rect = el.getBoundingClientRect();
41007
41140
  if (rect.width === 0 && rect.height === 0)
@@ -41011,7 +41144,9 @@ async function collectInteractiveElements(page) {
41011
41144
  return false;
41012
41145
  if (style.visibility === "hidden")
41013
41146
  return false;
41014
- if (parseFloat(style.opacity) === 0)
41147
+ const tag = el.tagName.toLowerCase();
41148
+ const isFormControl = tag === "input" || tag === "select" || tag === "textarea";
41149
+ if (parseFloat(style.opacity) === 0 && !isFormControl)
41015
41150
  return false;
41016
41151
  if (el.getAttribute("aria-hidden") === "true")
41017
41152
  return false;
@@ -41052,6 +41187,32 @@ async function collectInteractiveElements(page) {
41052
41187
  const placeholder = el.placeholder;
41053
41188
  if (placeholder)
41054
41189
  return placeholder;
41190
+ if (el.tagName.toLowerCase() === "input") {
41191
+ const itype = el.type?.toLowerCase();
41192
+ if (itype === "image") {
41193
+ const alt = el.getAttribute("alt")?.trim();
41194
+ if (alt)
41195
+ return alt;
41196
+ }
41197
+ if (itype === "submit" || itype === "button" || itype === "image") {
41198
+ const val = el.value?.trim();
41199
+ if (val)
41200
+ return val;
41201
+ }
41202
+ }
41203
+ const root = el.getRootNode();
41204
+ if (root instanceof ShadowRoot && root.host) {
41205
+ const host = root.host;
41206
+ const hostAria = host.getAttribute("aria-label")?.trim();
41207
+ if (hostAria)
41208
+ return hostAria;
41209
+ const hostLabelAttr = host.getAttribute("label")?.trim();
41210
+ if (hostLabelAttr)
41211
+ return hostLabelAttr;
41212
+ const hostText = host.innerText?.trim();
41213
+ if (hostText && hostText.length < 80)
41214
+ return hostText;
41215
+ }
41055
41216
  const name19 = el.getAttribute("name") || el.getAttribute("data-testid");
41056
41217
  if (name19)
41057
41218
  return name19;
@@ -41065,10 +41226,12 @@ async function collectInteractiveElements(page) {
41065
41226
  const type = el.type?.toLowerCase();
41066
41227
  if (tag === "button")
41067
41228
  return "button";
41229
+ if (tag === "summary")
41230
+ return "button";
41068
41231
  if (tag === "a" && el.getAttribute("href"))
41069
41232
  return "link";
41070
41233
  if (tag === "input") {
41071
- if (type === "submit" || type === "button")
41234
+ if (type === "submit" || type === "button" || type === "image")
41072
41235
  return "button";
41073
41236
  if (type === "checkbox")
41074
41237
  return "checkbox";
@@ -41088,12 +41251,20 @@ async function collectInteractiveElements(page) {
41088
41251
  return "menuitem";
41089
41252
  if (el.hasAttribute("onclick"))
41090
41253
  return "button";
41254
+ for (const a of FRAMEWORK_CLICK_ATTRS)
41255
+ if (el.hasAttribute(a))
41256
+ return "button";
41091
41257
  return "";
41092
41258
  }
41259
+ function isEphemeralId(id) {
41260
+ if (/^:/.test(id) || /:r[0-9a-z]+:/i.test(id))
41261
+ return true;
41262
+ return /^(mui-\d|radix-|headlessui-|react-aria-|rc-_?\d|ember\d)/i.test(id);
41263
+ }
41093
41264
  function buildCSSSelector(el) {
41094
41265
  const tag = el.tagName.toLowerCase();
41095
41266
  const id = el.getAttribute("id");
41096
- if (id)
41267
+ if (id && !isEphemeralId(id))
41097
41268
  return `${tag}#${CSS.escape(id)}`;
41098
41269
  const name19 = el.getAttribute("name");
41099
41270
  if (name19)
@@ -41103,7 +41274,7 @@ async function collectInteractiveElements(page) {
41103
41274
  while (current && current !== document.documentElement) {
41104
41275
  const aTag = current.tagName.toLowerCase();
41105
41276
  const aId = current.getAttribute("id");
41106
- if (aId)
41277
+ if (aId && !isEphemeralId(aId))
41107
41278
  return `${aTag}#${CSS.escape(aId)} `;
41108
41279
  const aCls = typeof current.className === "string" ? current.className.trim().split(/\s+/).filter((c) => c.length > 2)[0] : undefined;
41109
41280
  if (aCls)
@@ -41153,8 +41324,26 @@ async function collectInteractiveElements(page) {
41153
41324
  "[role=combobox]",
41154
41325
  "[role=option]",
41155
41326
  "[role=slider]",
41156
- "[onclick]"
41327
+ "[onclick]",
41328
+ "summary",
41329
+ ...FRAMEWORK_CLICK_ATTRS.map((a) => `[${CSS.escape(a)}]`)
41157
41330
  ].join(", ");
41331
+ function queryAllDeep(selector) {
41332
+ const out = [];
41333
+ const walk = (root) => {
41334
+ for (const el of root.querySelectorAll(selector))
41335
+ out.push(el);
41336
+ for (const host of root.querySelectorAll("*")) {
41337
+ if (host.closest("[data-cyberstrike-ui]"))
41338
+ continue;
41339
+ const sr = host.shadowRoot;
41340
+ if (sr)
41341
+ walk(sr);
41342
+ }
41343
+ };
41344
+ walk(document);
41345
+ return out;
41346
+ }
41158
41347
  function serializeConstraints(el, type) {
41159
41348
  const tag = el.tagName.toLowerCase();
41160
41349
  if (tag !== "input" && tag !== "textarea")
@@ -41191,19 +41380,12 @@ async function collectInteractiveElements(page) {
41191
41380
  const elements = [];
41192
41381
  const seenCount = new Map;
41193
41382
  const seenRoleSelectors = new Map;
41194
- for (const el of document.querySelectorAll(INTERACTIVE_SELECTORS)) {
41195
- if (el.closest("[data-cyberstrike-ui]"))
41196
- continue;
41197
- const role = getRole(el);
41198
- if (!role)
41199
- continue;
41200
- const isSlider = role === "slider";
41201
- if (!isSlider && !isStructurallyVisible(el))
41202
- continue;
41383
+ function addElement(el, role, syntheticRole = false) {
41203
41384
  const label = getLabel(el);
41204
41385
  const tag = el.tagName.toLowerCase();
41205
41386
  const type = el.type?.toLowerCase() || "";
41206
41387
  const href = el.href || "";
41388
+ const isSlider = role === "slider";
41207
41389
  const value = isSlider ? el.getAttribute("aria-valuenow") ?? el.value ?? "" : el.value || "";
41208
41390
  const placeholder = el.placeholder || "";
41209
41391
  const enabled = !el.disabled;
@@ -41214,12 +41396,13 @@ async function collectInteractiveElements(page) {
41214
41396
  const count = (seenCount.get(dedupKey) ?? 0) + 1;
41215
41397
  seenCount.set(dedupKey, count);
41216
41398
  if (count > 3)
41217
- continue;
41399
+ return;
41218
41400
  const disambiguatedLabel = count > 1 ? `${label} (${count})` : label;
41219
41401
  const ariaLabelRaw = (el.getAttribute("aria-label") || "").trim();
41220
41402
  const safeAriaLabel = ariaLabelRaw.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
41221
- const selectorRole = count > 1 ? "" : safeAriaLabel ? `role=${role}[name="${safeAriaLabel}"]` : `role=${role}`;
41403
+ const selectorRole = syntheticRole || count > 1 ? "" : safeAriaLabel ? `role=${role}[name="${safeAriaLabel}"]` : `role=${role}`;
41222
41404
  const selectorCSS = buildCSSSelector(el);
41405
+ const inChrome = !!el.closest("nav, header, footer, aside, [role=navigation], [role=banner], [role=contentinfo], [role=complementary]");
41223
41406
  const roleCount = (seenRoleSelectors.get(selectorRole) ?? 0) + 1;
41224
41407
  seenRoleSelectors.set(selectorRole, roleCount);
41225
41408
  elements.push({
@@ -41234,9 +41417,45 @@ async function collectInteractiveElements(page) {
41234
41417
  options,
41235
41418
  constraints,
41236
41419
  selectorRole,
41237
- selectorCSS
41420
+ selectorCSS,
41421
+ inChrome
41238
41422
  });
41239
41423
  }
41424
+ for (const el of queryAllDeep(INTERACTIVE_SELECTORS)) {
41425
+ if (el.closest("[data-cyberstrike-ui]"))
41426
+ continue;
41427
+ const role = getRole(el);
41428
+ if (!role)
41429
+ continue;
41430
+ const isSlider = role === "slider";
41431
+ if (!isSlider && !isStructurallyVisible(el))
41432
+ continue;
41433
+ addElement(el, role);
41434
+ }
41435
+ for (const el of queryAllDeep("div, span, li")) {
41436
+ if (el.closest("[data-cyberstrike-ui]"))
41437
+ continue;
41438
+ if (el.getAttribute("role"))
41439
+ continue;
41440
+ if (el.hasAttribute("onclick"))
41441
+ continue;
41442
+ if (!isStructurallyVisible(el))
41443
+ continue;
41444
+ const text2 = el.innerText?.trim() || "";
41445
+ if (!text2 || text2.length > 80)
41446
+ continue;
41447
+ if (el.querySelector(INTERACTIVE_SELECTORS))
41448
+ continue;
41449
+ if (window.getComputedStyle(el).cursor !== "pointer")
41450
+ continue;
41451
+ const parent = el.parentElement;
41452
+ if (parent && window.getComputedStyle(parent).cursor === "pointer")
41453
+ continue;
41454
+ const rect = el.getBoundingClientRect();
41455
+ if (rect.width >= window.innerWidth * 0.9 && rect.height >= window.innerHeight * 0.5)
41456
+ continue;
41457
+ addElement(el, "button", true);
41458
+ }
41240
41459
  const INTERACTIVE_TAGS = new Set(["input", "button", "a", "select", "textarea"]);
41241
41460
  const INTERACTIVE_ROLES = new Set([
41242
41461
  "button",
@@ -41285,7 +41504,8 @@ async function collectInteractiveElements(page) {
41285
41504
  options: "",
41286
41505
  constraints: "",
41287
41506
  selectorRole: "",
41288
- selectorCSS: ""
41507
+ selectorCSS: "",
41508
+ inChrome: false
41289
41509
  });
41290
41510
  }
41291
41511
  for (const el of elements) {
@@ -41309,12 +41529,75 @@ function assignIds(browserElements, startId) {
41309
41529
  placeholder: el.placeholder,
41310
41530
  options: el.options,
41311
41531
  constraints: el.constraints,
41312
- selector: el.selectorRole.includes("[name=") ? el.selectorRole : el.selectorCSS || el.selectorRole
41532
+ selector: el.selectorRole.includes("[name=") ? el.selectorRole : el.selectorCSS || el.selectorRole,
41533
+ inChrome: el.inChrome
41313
41534
  }));
41314
41535
  }
41315
41536
  async function collectElements(page) {
41316
41537
  const browserElements = await collectInteractiveElements(page);
41317
- return assignIds(browserElements, 1).slice(0, MAX_ELEMENTS);
41538
+ const sampled = sampleTemplates(browserElements);
41539
+ return assignIds(sampled, 1).slice(0, MAX_ELEMENTS);
41540
+ }
41541
+ function sampleTemplates(elements) {
41542
+ const clusterCount = new Map;
41543
+ const out = [];
41544
+ for (const el of elements) {
41545
+ const masked = el.label.replace(/\d+/g, "#");
41546
+ if (masked === el.label) {
41547
+ out.push(el);
41548
+ continue;
41549
+ }
41550
+ const key = `${el.role}::${masked}`;
41551
+ const n = (clusterCount.get(key) ?? 0) + 1;
41552
+ clusterCount.set(key, n);
41553
+ if (n <= MAX_PER_TEMPLATE)
41554
+ out.push(el);
41555
+ }
41556
+ return out;
41557
+ }
41558
+ async function revealLazyContent(page) {
41559
+ try {
41560
+ for (let i = 0;i < REVEAL_MAX_STEPS; i++) {
41561
+ const advanced = await page.evaluate(() => {
41562
+ const before = window.scrollY;
41563
+ window.scrollBy(0, Math.round(window.innerHeight * 0.9));
41564
+ return window.scrollY > before;
41565
+ });
41566
+ await page.waitForTimeout(REVEAL_STEP_WAIT);
41567
+ if (!advanced)
41568
+ break;
41569
+ }
41570
+ await page.evaluate(() => window.scrollTo(0, 0));
41571
+ await page.waitForTimeout(REVEAL_STEP_WAIT);
41572
+ } catch {}
41573
+ }
41574
+ async function expandDisclosures(page) {
41575
+ try {
41576
+ await page.evaluate((max) => {
41577
+ let budget = max;
41578
+ for (const d of Array.from(document.querySelectorAll("details:not([open])"))) {
41579
+ if (budget <= 0)
41580
+ break;
41581
+ if (d.closest("[data-cyberstrike-ui]"))
41582
+ continue;
41583
+ d.open = true;
41584
+ budget--;
41585
+ }
41586
+ for (const c of Array.from(document.querySelectorAll('[aria-expanded="false"]'))) {
41587
+ if (budget <= 0)
41588
+ break;
41589
+ if (c.closest("[data-cyberstrike-ui]"))
41590
+ continue;
41591
+ if (c.getAttribute("role") === "tab")
41592
+ continue;
41593
+ if (c.hasAttribute("aria-haspopup") && c.getAttribute("aria-haspopup") !== "false")
41594
+ continue;
41595
+ c.click();
41596
+ budget--;
41597
+ }
41598
+ }, EXPAND_MAX);
41599
+ await page.waitForTimeout(REVEAL_STEP_WAIT);
41600
+ } catch {}
41318
41601
  }
41319
41602
  async function isViewportCenterBlocked(page) {
41320
41603
  try {
@@ -41588,7 +41871,13 @@ var PANEL_CSS = `
41588
41871
  width: 360px;
41589
41872
  background: #0b0f14;
41590
41873
  border: 1px solid #1f2937;
41591
- pointer-events: auto;
41874
+ /* Non-blocking HUD: the agent's own observability overlay must NEVER intercept
41875
+ clicks meant for the page. The card sits bottom-right where page chrome
41876
+ (cookie banners, chat widgets, FABs) commonly lives — pointer-events:auto here
41877
+ silently blocked those page elements (Playwright hit-test returns the panel →
41878
+ 2s timeout per click). The panel is display-only; click-to-expand is sacrificed
41879
+ (re-add later via a keydown shortcut, which needs no pointer-events). */
41880
+ pointer-events: none;
41592
41881
  transition: width 200ms ease-out, height 200ms ease-out;
41593
41882
  box-shadow: 0 10px 40px -10px rgba(0,0,0,0.8);
41594
41883
  overflow: hidden;
@@ -53190,7 +53479,12 @@ async function executeClickTask(task, page, elements, interceptor, semanticActio
53190
53479
  targetSelector: el.selector,
53191
53480
  credential: credentialId
53192
53481
  });
53193
- const result = await execute(page, el, "click", undefined, interceptor.setPendingUI, elements.length);
53482
+ let result = await execute(page, el, "click", undefined, interceptor.setPendingUI, elements.length);
53483
+ if (!result.success && await isViewportCenterBlocked(page)) {
53484
+ log6.debug("click blocked by a stray overlay — closing it and retrying once", { label: el.label });
53485
+ await closeOverlay(page);
53486
+ result = await execute(page, el, "click", undefined, interceptor.setPendingUI, elements.length);
53487
+ }
53194
53488
  interceptor.clearPendingTrigger();
53195
53489
  trackResult(result, interceptor, globalState, credentialId, task.triggersMutation, page);
53196
53490
  csEmit(page, { type: "action-end", ok: result.success, credential: credentialId });
@@ -53530,7 +53824,7 @@ async function runMultiCredential(config2, credentials) {
53530
53824
  const contexts = [];
53531
53825
  const captureQueues = new Map;
53532
53826
  const lastAuthHeaders = new Map;
53533
- for (const cred of credentials) {
53827
+ for (const [credIndex, cred] of credentials.entries()) {
53534
53828
  const browserContext = await browser.newContext({
53535
53829
  userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0.0.0 Safari/537.36"
53536
53830
  });
@@ -53547,7 +53841,7 @@ async function runMultiCredential(config2, credentials) {
53547
53841
  startedAt: Date.now()
53548
53842
  });
53549
53843
  csEmit(page, { type: "credential-switch", from: null, to: cred.id });
53550
- await waitForManualLogin(page, cred.id);
53844
+ await waitForManualLogin(page, cred.id, { index: credIndex, total: credentials.length });
53551
53845
  let credentialId = cred.id;
53552
53846
  if (!dryRun) {
53553
53847
  const registeredId = await registerCredential(serverUrl, sessionId, cred.id);
@@ -53662,6 +53956,8 @@ async function runMultiCredential(config2, credentials) {
53662
53956
  await ctx.page.keyboard.press("Escape").catch(() => {});
53663
53957
  await ctx.page.waitForTimeout(OVERLAY_ESCAPE_WAIT);
53664
53958
  await dismissCookieBanner(ctx.page);
53959
+ await revealLazyContent(ctx.page);
53960
+ await expandDisclosures(ctx.page);
53665
53961
  }
53666
53962
  const elementsByContext = new Map;
53667
53963
  const fingerprintsByContext = new Map;
@@ -53898,6 +54194,8 @@ async function run(config2) {
53898
54194
  await page.waitForTimeout(OVERLAY_ESCAPE_WAIT);
53899
54195
  }
53900
54196
  await dismissCookieBanner(page);
54197
+ await revealLazyContent(page);
54198
+ await expandDisclosures(page);
53901
54199
  const intel = getIntelligence(globalState, SINGLE_CRED);
53902
54200
  const oldFingerprint = intel.pageFingerprints.get(currentUrl);
53903
54201
  log6.debug("fingerprint check", { url: currentUrl, hasOld: !!oldFingerprint });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyberstrike-io/cyberstrike-darwin-arm64",
3
- "version": "1.1.14",
3
+ "version": "1.1.15-beta.1",
4
4
  "os": [
5
5
  "darwin"
6
6
  ],