opensteer 0.6.8 → 0.6.11

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.
@@ -324,7 +324,7 @@ function normalizeNonEmptyString(value) {
324
324
  // src/config.ts
325
325
  var DEFAULT_CONFIG = {
326
326
  browser: {
327
- headless: false,
327
+ headless: void 0,
328
328
  executablePath: void 0,
329
329
  slowMo: 0,
330
330
  mode: void 0,
@@ -1344,7 +1344,17 @@ function formatFieldPath(field, parent) {
1344
1344
  return parent ? `"${parent}.${field}"` : `"${field}"`;
1345
1345
  }
1346
1346
  function formatAllowedValues(values) {
1347
- return values.map((value) => `"${value}"`).join(", ");
1347
+ if (values.length === 0) {
1348
+ return "";
1349
+ }
1350
+ if (values.length === 1) {
1351
+ return `"${values[0]}"`;
1352
+ }
1353
+ if (values.length === 2) {
1354
+ return `"${values[0]}" or "${values[1]}"`;
1355
+ }
1356
+ const quotedValues = values.map((value) => `"${value}"`);
1357
+ return `${quotedValues.slice(0, -1).join(", ")}, or ${quotedValues[quotedValues.length - 1]}`;
1348
1358
  }
1349
1359
  function zeroImportResponse() {
1350
1360
  return {
@@ -14,7 +14,7 @@ import {
14
14
  resolveNamespaceDir,
15
15
  selectCloudCredential,
16
16
  withTokenQuery
17
- } from "./chunk-LTREUXLO.js";
17
+ } from "./chunk-2ES46WCO.js";
18
18
  import {
19
19
  detectChromePaths,
20
20
  expandHome,
@@ -3077,6 +3077,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
3077
3077
  };
3078
3078
  }
3079
3079
 
3080
+ // src/html/interactive-patterns.ts
3081
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
3082
+ "a",
3083
+ "button",
3084
+ "input",
3085
+ "select",
3086
+ "textarea"
3087
+ ]);
3088
+ var INTERACTIVE_SELECTOR_PARTS = [
3089
+ "a[href]",
3090
+ "button",
3091
+ "input",
3092
+ "textarea",
3093
+ "select",
3094
+ '[role="button"]',
3095
+ '[role="link"]',
3096
+ '[role="menuitem"]',
3097
+ '[role="option"]',
3098
+ '[role="radio"]',
3099
+ '[role="checkbox"]',
3100
+ '[role="tab"]',
3101
+ '[contenteditable="true"]',
3102
+ "[onclick]",
3103
+ "[onmousedown]",
3104
+ "[onmouseup]"
3105
+ ];
3106
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
3107
+ var INTERACTIVE_ROLE_TOKENS = [
3108
+ "button",
3109
+ "link",
3110
+ "menuitem",
3111
+ "option",
3112
+ "radio",
3113
+ "checkbox",
3114
+ "tab",
3115
+ "textbox",
3116
+ "combobox",
3117
+ "slider",
3118
+ "spinbutton",
3119
+ "search",
3120
+ "searchbox"
3121
+ ];
3122
+ var INTERACTIVE_ROLE_SET = new Set(
3123
+ INTERACTIVE_ROLE_TOKENS
3124
+ );
3125
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
3126
+ function hasNonNegativeTabIndex(value) {
3127
+ if (value == null) return false;
3128
+ const parsed = Number.parseInt(value, 10);
3129
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
3130
+ }
3131
+
3080
3132
  // src/html/interactivity.ts
3081
3133
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
3082
3134
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -3091,42 +3143,59 @@ async function markInteractiveElements(page, {
3091
3143
  markAttribute: markAttribute2,
3092
3144
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
3093
3145
  hiddenAttr,
3094
- scrollableAttr
3146
+ scrollableAttr,
3147
+ interactiveSelector,
3148
+ interactiveRoles,
3149
+ nonNegativeTabIndexMin
3095
3150
  }) => {
3096
- const interactiveSelector = [
3097
- "a[href]",
3098
- "button",
3099
- "input",
3100
- "textarea",
3101
- "select",
3102
- '[role="button"]',
3103
- '[role="link"]',
3104
- '[role="menuitem"]',
3105
- '[role="option"]',
3106
- '[role="radio"]',
3107
- '[role="checkbox"]',
3108
- '[role="tab"]',
3109
- '[contenteditable="true"]',
3110
- "[onclick]",
3111
- "[onmousedown]",
3112
- "[onmouseup]",
3113
- "[tabindex]"
3114
- ].join(",");
3115
- const interactiveRoles = /* @__PURE__ */ new Set([
3116
- "button",
3117
- "link",
3118
- "menuitem",
3119
- "option",
3120
- "radio",
3121
- "checkbox",
3122
- "tab",
3123
- "textbox",
3124
- "combobox",
3125
- "slider",
3126
- "spinbutton",
3127
- "search",
3128
- "searchbox"
3129
- ]);
3151
+ const interactiveRolesSet = new Set(interactiveRoles);
3152
+ function isExplicitlyHidden(el, style) {
3153
+ if (el.hasAttribute("hidden")) {
3154
+ return true;
3155
+ }
3156
+ if (el.getAttribute("aria-hidden") === "true") {
3157
+ return true;
3158
+ }
3159
+ if (style.display === "none") {
3160
+ return true;
3161
+ }
3162
+ if (style.visibility === "hidden" || style.visibility === "collapse") {
3163
+ return true;
3164
+ }
3165
+ const opacity = Number.parseFloat(style.opacity);
3166
+ return Number.isFinite(opacity) && opacity <= 0;
3167
+ }
3168
+ function hasVisibleOutOfFlowChild(el) {
3169
+ const children = el.children;
3170
+ for (let i = 0; i < children.length; i++) {
3171
+ const child = children[i];
3172
+ const childStyle = window.getComputedStyle(child);
3173
+ if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
3174
+ continue;
3175
+ }
3176
+ const childRect = child.getBoundingClientRect();
3177
+ if (childRect.width > 0 && childRect.height > 0) {
3178
+ return true;
3179
+ }
3180
+ }
3181
+ return false;
3182
+ }
3183
+ function isHiddenByOwnRect(el, style) {
3184
+ if (style.display === "contents") {
3185
+ return false;
3186
+ }
3187
+ const rect = el.getBoundingClientRect();
3188
+ if (rect.width > 0 && rect.height > 0) {
3189
+ return false;
3190
+ }
3191
+ return !hasVisibleOutOfFlowChild(el);
3192
+ }
3193
+ function hasInteractiveTabIndex(el) {
3194
+ const value = el.getAttribute("tabindex");
3195
+ if (value == null) return false;
3196
+ const parsed = Number.parseInt(value, 10);
3197
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
3198
+ }
3130
3199
  const roots = [document];
3131
3200
  while (roots.length) {
3132
3201
  const root = roots.pop();
@@ -3142,42 +3211,7 @@ async function markInteractiveElements(page, {
3142
3211
  continue;
3143
3212
  }
3144
3213
  const style = window.getComputedStyle(el);
3145
- let hidden = false;
3146
- if (el.hasAttribute("hidden")) {
3147
- hidden = true;
3148
- } else if (el.getAttribute("aria-hidden") === "true") {
3149
- hidden = true;
3150
- } else if (style.display === "none") {
3151
- hidden = true;
3152
- } else if (style.visibility === "hidden" || style.visibility === "collapse") {
3153
- hidden = true;
3154
- }
3155
- if (!hidden) {
3156
- const opacity = Number.parseFloat(style.opacity);
3157
- if (Number.isFinite(opacity) && opacity <= 0) {
3158
- hidden = true;
3159
- }
3160
- }
3161
- if (!hidden) {
3162
- const rect = el.getBoundingClientRect();
3163
- if (rect.width <= 0 || rect.height <= 0) {
3164
- hidden = true;
3165
- const children = el.children;
3166
- for (let i = 0; i < children.length; i++) {
3167
- const childStyle = window.getComputedStyle(
3168
- children[i]
3169
- );
3170
- if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
3171
- continue;
3172
- }
3173
- const childRect = children[i].getBoundingClientRect();
3174
- if (childRect.width > 0 && childRect.height > 0) {
3175
- hidden = false;
3176
- break;
3177
- }
3178
- }
3179
- }
3180
- }
3214
+ const hidden = isExplicitlyHidden(el, style) || isHiddenByOwnRect(el, style);
3181
3215
  if (hidden) {
3182
3216
  el.setAttribute(hiddenAttr, "1");
3183
3217
  el.removeAttribute(markAttribute2);
@@ -3187,11 +3221,13 @@ async function markInteractiveElements(page, {
3187
3221
  let interactive = false;
3188
3222
  if (el.matches(interactiveSelector)) {
3189
3223
  interactive = true;
3224
+ } else if (hasInteractiveTabIndex(el)) {
3225
+ interactive = true;
3190
3226
  } else if (style.cursor === "pointer") {
3191
3227
  interactive = true;
3192
3228
  } else {
3193
3229
  const role = (el.getAttribute("role") || "").toLowerCase();
3194
- if (interactiveRoles.has(role)) {
3230
+ if (interactiveRolesSet.has(role)) {
3195
3231
  interactive = true;
3196
3232
  }
3197
3233
  }
@@ -3236,7 +3272,10 @@ async function markInteractiveElements(page, {
3236
3272
  markAttribute,
3237
3273
  skipIfAlreadyMarked,
3238
3274
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
3239
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
3275
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
3276
+ interactiveSelector: INTERACTIVE_SELECTOR,
3277
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
3278
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
3240
3279
  }
3241
3280
  );
3242
3281
  };
@@ -3323,7 +3362,7 @@ function isClickable($, el, context) {
3323
3362
  }
3324
3363
  const tag = (el[0]?.tagName || "").toLowerCase();
3325
3364
  if (!tag || ROOT_TAGS.has(tag)) return false;
3326
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
3365
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
3327
3366
  if (tag === "input") {
3328
3367
  const inputType = String(el.attr("type") || "").toLowerCase();
3329
3368
  if (inputType === "hidden") return false;
@@ -3337,26 +3376,11 @@ function isClickable($, el, context) {
3337
3376
  if (attrs["data-action"] !== void 0) return true;
3338
3377
  if (attrs["data-click"] !== void 0) return true;
3339
3378
  if (attrs["data-toggle"] !== void 0) return true;
3340
- if (attrs.tabindex !== void 0) {
3341
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
3342
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
3379
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
3380
+ return true;
3343
3381
  }
3344
3382
  const role = String(attrs.role || "").toLowerCase();
3345
- if ([
3346
- "button",
3347
- "link",
3348
- "menuitem",
3349
- "option",
3350
- "radio",
3351
- "checkbox",
3352
- "tab",
3353
- "textbox",
3354
- "combobox",
3355
- "slider",
3356
- "spinbutton",
3357
- "search",
3358
- "searchbox"
3359
- ].includes(role)) {
3383
+ if (INTERACTIVE_ROLE_SET.has(role)) {
3360
3384
  return true;
3361
3385
  }
3362
3386
  const className = String(attrs.class || "").toLowerCase();
@@ -5,7 +5,7 @@ import {
5
5
  resolveConfigWithEnv,
6
6
  selectCloudCredential,
7
7
  stripTrailingSlashes
8
- } from "./chunk-LTREUXLO.js";
8
+ } from "./chunk-2ES46WCO.js";
9
9
 
10
10
  // src/cli/auth.ts
11
11
  import open from "open";
@@ -2,7 +2,7 @@ import {
2
2
  cloudAuthHeaders,
3
3
  normalizeCloudBaseUrl,
4
4
  parseCloudHttpError
5
- } from "./chunk-LTREUXLO.js";
5
+ } from "./chunk-2ES46WCO.js";
6
6
 
7
7
  // src/cloud/browser-profile-client.ts
8
8
  var BrowserProfileClient = class {
package/dist/cli/auth.cjs CHANGED
@@ -238,7 +238,7 @@ function normalizeNonEmptyString(value) {
238
238
  // src/config.ts
239
239
  var DEFAULT_CONFIG = {
240
240
  browser: {
241
- headless: false,
241
+ headless: void 0,
242
242
  executablePath: void 0,
243
243
  slowMo: 0,
244
244
  mode: void 0,
package/dist/cli/auth.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  isCloudModeEnabledForRootDir,
5
5
  parseOpensteerAuthArgs,
6
6
  runOpensteerAuthCli
7
- } from "../chunk-UQYVMJOZ.js";
8
- import "../chunk-LTREUXLO.js";
7
+ } from "../chunk-U724TBY6.js";
8
+ import "../chunk-2ES46WCO.js";
9
9
  export {
10
10
  ensureCloudCredentialsForCommand,
11
11
  ensureCloudCredentialsForOpenCommand,
@@ -753,7 +753,7 @@ function sanitizeNamespaceSegment(segment) {
753
753
  // src/config.ts
754
754
  var DEFAULT_CONFIG = {
755
755
  browser: {
756
- headless: false,
756
+ headless: void 0,
757
757
  executablePath: void 0,
758
758
  slowMo: 0,
759
759
  mode: void 0,
@@ -4446,6 +4446,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4446
4446
  };
4447
4447
  }
4448
4448
 
4449
+ // src/html/interactive-patterns.ts
4450
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4451
+ "a",
4452
+ "button",
4453
+ "input",
4454
+ "select",
4455
+ "textarea"
4456
+ ]);
4457
+ var INTERACTIVE_SELECTOR_PARTS = [
4458
+ "a[href]",
4459
+ "button",
4460
+ "input",
4461
+ "textarea",
4462
+ "select",
4463
+ '[role="button"]',
4464
+ '[role="link"]',
4465
+ '[role="menuitem"]',
4466
+ '[role="option"]',
4467
+ '[role="radio"]',
4468
+ '[role="checkbox"]',
4469
+ '[role="tab"]',
4470
+ '[contenteditable="true"]',
4471
+ "[onclick]",
4472
+ "[onmousedown]",
4473
+ "[onmouseup]"
4474
+ ];
4475
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4476
+ var INTERACTIVE_ROLE_TOKENS = [
4477
+ "button",
4478
+ "link",
4479
+ "menuitem",
4480
+ "option",
4481
+ "radio",
4482
+ "checkbox",
4483
+ "tab",
4484
+ "textbox",
4485
+ "combobox",
4486
+ "slider",
4487
+ "spinbutton",
4488
+ "search",
4489
+ "searchbox"
4490
+ ];
4491
+ var INTERACTIVE_ROLE_SET = new Set(
4492
+ INTERACTIVE_ROLE_TOKENS
4493
+ );
4494
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4495
+ function hasNonNegativeTabIndex(value) {
4496
+ if (value == null) return false;
4497
+ const parsed = Number.parseInt(value, 10);
4498
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4499
+ }
4500
+
4449
4501
  // src/html/interactivity.ts
4450
4502
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4451
4503
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4460,42 +4512,59 @@ async function markInteractiveElements(page, {
4460
4512
  markAttribute: markAttribute2,
4461
4513
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4462
4514
  hiddenAttr,
4463
- scrollableAttr
4515
+ scrollableAttr,
4516
+ interactiveSelector,
4517
+ interactiveRoles,
4518
+ nonNegativeTabIndexMin
4464
4519
  }) => {
4465
- const interactiveSelector = [
4466
- "a[href]",
4467
- "button",
4468
- "input",
4469
- "textarea",
4470
- "select",
4471
- '[role="button"]',
4472
- '[role="link"]',
4473
- '[role="menuitem"]',
4474
- '[role="option"]',
4475
- '[role="radio"]',
4476
- '[role="checkbox"]',
4477
- '[role="tab"]',
4478
- '[contenteditable="true"]',
4479
- "[onclick]",
4480
- "[onmousedown]",
4481
- "[onmouseup]",
4482
- "[tabindex]"
4483
- ].join(",");
4484
- const interactiveRoles = /* @__PURE__ */ new Set([
4485
- "button",
4486
- "link",
4487
- "menuitem",
4488
- "option",
4489
- "radio",
4490
- "checkbox",
4491
- "tab",
4492
- "textbox",
4493
- "combobox",
4494
- "slider",
4495
- "spinbutton",
4496
- "search",
4497
- "searchbox"
4498
- ]);
4520
+ const interactiveRolesSet = new Set(interactiveRoles);
4521
+ function isExplicitlyHidden(el, style) {
4522
+ if (el.hasAttribute("hidden")) {
4523
+ return true;
4524
+ }
4525
+ if (el.getAttribute("aria-hidden") === "true") {
4526
+ return true;
4527
+ }
4528
+ if (style.display === "none") {
4529
+ return true;
4530
+ }
4531
+ if (style.visibility === "hidden" || style.visibility === "collapse") {
4532
+ return true;
4533
+ }
4534
+ const opacity = Number.parseFloat(style.opacity);
4535
+ return Number.isFinite(opacity) && opacity <= 0;
4536
+ }
4537
+ function hasVisibleOutOfFlowChild(el) {
4538
+ const children = el.children;
4539
+ for (let i = 0; i < children.length; i++) {
4540
+ const child = children[i];
4541
+ const childStyle = window.getComputedStyle(child);
4542
+ if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4543
+ continue;
4544
+ }
4545
+ const childRect = child.getBoundingClientRect();
4546
+ if (childRect.width > 0 && childRect.height > 0) {
4547
+ return true;
4548
+ }
4549
+ }
4550
+ return false;
4551
+ }
4552
+ function isHiddenByOwnRect(el, style) {
4553
+ if (style.display === "contents") {
4554
+ return false;
4555
+ }
4556
+ const rect = el.getBoundingClientRect();
4557
+ if (rect.width > 0 && rect.height > 0) {
4558
+ return false;
4559
+ }
4560
+ return !hasVisibleOutOfFlowChild(el);
4561
+ }
4562
+ function hasInteractiveTabIndex(el) {
4563
+ const value = el.getAttribute("tabindex");
4564
+ if (value == null) return false;
4565
+ const parsed = Number.parseInt(value, 10);
4566
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4567
+ }
4499
4568
  const roots = [document];
4500
4569
  while (roots.length) {
4501
4570
  const root = roots.pop();
@@ -4511,42 +4580,7 @@ async function markInteractiveElements(page, {
4511
4580
  continue;
4512
4581
  }
4513
4582
  const style = window.getComputedStyle(el);
4514
- let hidden = false;
4515
- if (el.hasAttribute("hidden")) {
4516
- hidden = true;
4517
- } else if (el.getAttribute("aria-hidden") === "true") {
4518
- hidden = true;
4519
- } else if (style.display === "none") {
4520
- hidden = true;
4521
- } else if (style.visibility === "hidden" || style.visibility === "collapse") {
4522
- hidden = true;
4523
- }
4524
- if (!hidden) {
4525
- const opacity = Number.parseFloat(style.opacity);
4526
- if (Number.isFinite(opacity) && opacity <= 0) {
4527
- hidden = true;
4528
- }
4529
- }
4530
- if (!hidden) {
4531
- const rect = el.getBoundingClientRect();
4532
- if (rect.width <= 0 || rect.height <= 0) {
4533
- hidden = true;
4534
- const children = el.children;
4535
- for (let i = 0; i < children.length; i++) {
4536
- const childStyle = window.getComputedStyle(
4537
- children[i]
4538
- );
4539
- if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4540
- continue;
4541
- }
4542
- const childRect = children[i].getBoundingClientRect();
4543
- if (childRect.width > 0 && childRect.height > 0) {
4544
- hidden = false;
4545
- break;
4546
- }
4547
- }
4548
- }
4549
- }
4583
+ const hidden = isExplicitlyHidden(el, style) || isHiddenByOwnRect(el, style);
4550
4584
  if (hidden) {
4551
4585
  el.setAttribute(hiddenAttr, "1");
4552
4586
  el.removeAttribute(markAttribute2);
@@ -4556,11 +4590,13 @@ async function markInteractiveElements(page, {
4556
4590
  let interactive = false;
4557
4591
  if (el.matches(interactiveSelector)) {
4558
4592
  interactive = true;
4593
+ } else if (hasInteractiveTabIndex(el)) {
4594
+ interactive = true;
4559
4595
  } else if (style.cursor === "pointer") {
4560
4596
  interactive = true;
4561
4597
  } else {
4562
4598
  const role = (el.getAttribute("role") || "").toLowerCase();
4563
- if (interactiveRoles.has(role)) {
4599
+ if (interactiveRolesSet.has(role)) {
4564
4600
  interactive = true;
4565
4601
  }
4566
4602
  }
@@ -4605,7 +4641,10 @@ async function markInteractiveElements(page, {
4605
4641
  markAttribute,
4606
4642
  skipIfAlreadyMarked,
4607
4643
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4608
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4644
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4645
+ interactiveSelector: INTERACTIVE_SELECTOR,
4646
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4647
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4609
4648
  }
4610
4649
  );
4611
4650
  };
@@ -4692,7 +4731,7 @@ function isClickable($, el, context) {
4692
4731
  }
4693
4732
  const tag = (el[0]?.tagName || "").toLowerCase();
4694
4733
  if (!tag || ROOT_TAGS.has(tag)) return false;
4695
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4734
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4696
4735
  if (tag === "input") {
4697
4736
  const inputType = String(el.attr("type") || "").toLowerCase();
4698
4737
  if (inputType === "hidden") return false;
@@ -4706,26 +4745,11 @@ function isClickable($, el, context) {
4706
4745
  if (attrs["data-action"] !== void 0) return true;
4707
4746
  if (attrs["data-click"] !== void 0) return true;
4708
4747
  if (attrs["data-toggle"] !== void 0) return true;
4709
- if (attrs.tabindex !== void 0) {
4710
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4711
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4748
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4749
+ return true;
4712
4750
  }
4713
4751
  const role = String(attrs.role || "").toLowerCase();
4714
- if ([
4715
- "button",
4716
- "link",
4717
- "menuitem",
4718
- "option",
4719
- "radio",
4720
- "checkbox",
4721
- "tab",
4722
- "textbox",
4723
- "combobox",
4724
- "slider",
4725
- "spinbutton",
4726
- "search",
4727
- "searchbox"
4728
- ].includes(role)) {
4752
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4729
4753
  return true;
4730
4754
  }
4731
4755
  const className = String(attrs.class || "").toLowerCase();
@@ -9628,7 +9652,17 @@ function formatFieldPath(field, parent) {
9628
9652
  return parent ? `"${parent}.${field}"` : `"${field}"`;
9629
9653
  }
9630
9654
  function formatAllowedValues(values) {
9631
- return values.map((value) => `"${value}"`).join(", ");
9655
+ if (values.length === 0) {
9656
+ return "";
9657
+ }
9658
+ if (values.length === 1) {
9659
+ return `"${values[0]}"`;
9660
+ }
9661
+ if (values.length === 2) {
9662
+ return `"${values[0]}" or "${values[1]}"`;
9663
+ }
9664
+ const quotedValues = values.map((value) => `"${value}"`);
9665
+ return `${quotedValues.slice(0, -1).join(", ")}, or ${quotedValues[quotedValues.length - 1]}`;
9632
9666
  }
9633
9667
  function zeroImportResponse() {
9634
9668
  return {
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "../chunk-O4HVMKX2.js";
3
+ } from "../chunk-ZRCFF546.js";
4
4
  import {
5
5
  createKeychainStore,
6
6
  ensureCloudCredentialsForCommand
7
- } from "../chunk-UQYVMJOZ.js";
7
+ } from "../chunk-U724TBY6.js";
8
8
  import {
9
9
  Opensteer
10
- } from "../chunk-C6AJL5XU.js";
10
+ } from "../chunk-JZF2WC7U.js";
11
11
  import {
12
12
  resolveConfigWithEnv
13
- } from "../chunk-LTREUXLO.js";
13
+ } from "../chunk-2ES46WCO.js";
14
14
  import {
15
15
  expandHome
16
16
  } from "../chunk-K5CL76MG.js";
@@ -1881,7 +1881,7 @@ function sanitizeNamespaceSegment(segment) {
1881
1881
  // src/config.ts
1882
1882
  var DEFAULT_CONFIG = {
1883
1883
  browser: {
1884
- headless: false,
1884
+ headless: void 0,
1885
1885
  executablePath: void 0,
1886
1886
  slowMo: 0,
1887
1887
  mode: void 0,
@@ -4439,6 +4439,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4439
4439
  };
4440
4440
  }
4441
4441
 
4442
+ // src/html/interactive-patterns.ts
4443
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4444
+ "a",
4445
+ "button",
4446
+ "input",
4447
+ "select",
4448
+ "textarea"
4449
+ ]);
4450
+ var INTERACTIVE_SELECTOR_PARTS = [
4451
+ "a[href]",
4452
+ "button",
4453
+ "input",
4454
+ "textarea",
4455
+ "select",
4456
+ '[role="button"]',
4457
+ '[role="link"]',
4458
+ '[role="menuitem"]',
4459
+ '[role="option"]',
4460
+ '[role="radio"]',
4461
+ '[role="checkbox"]',
4462
+ '[role="tab"]',
4463
+ '[contenteditable="true"]',
4464
+ "[onclick]",
4465
+ "[onmousedown]",
4466
+ "[onmouseup]"
4467
+ ];
4468
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4469
+ var INTERACTIVE_ROLE_TOKENS = [
4470
+ "button",
4471
+ "link",
4472
+ "menuitem",
4473
+ "option",
4474
+ "radio",
4475
+ "checkbox",
4476
+ "tab",
4477
+ "textbox",
4478
+ "combobox",
4479
+ "slider",
4480
+ "spinbutton",
4481
+ "search",
4482
+ "searchbox"
4483
+ ];
4484
+ var INTERACTIVE_ROLE_SET = new Set(
4485
+ INTERACTIVE_ROLE_TOKENS
4486
+ );
4487
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4488
+ function hasNonNegativeTabIndex(value) {
4489
+ if (value == null) return false;
4490
+ const parsed = Number.parseInt(value, 10);
4491
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4492
+ }
4493
+
4442
4494
  // src/html/interactivity.ts
4443
4495
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4444
4496
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4453,42 +4505,59 @@ async function markInteractiveElements(page, {
4453
4505
  markAttribute: markAttribute2,
4454
4506
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4455
4507
  hiddenAttr,
4456
- scrollableAttr
4508
+ scrollableAttr,
4509
+ interactiveSelector,
4510
+ interactiveRoles,
4511
+ nonNegativeTabIndexMin
4457
4512
  }) => {
4458
- const interactiveSelector = [
4459
- "a[href]",
4460
- "button",
4461
- "input",
4462
- "textarea",
4463
- "select",
4464
- '[role="button"]',
4465
- '[role="link"]',
4466
- '[role="menuitem"]',
4467
- '[role="option"]',
4468
- '[role="radio"]',
4469
- '[role="checkbox"]',
4470
- '[role="tab"]',
4471
- '[contenteditable="true"]',
4472
- "[onclick]",
4473
- "[onmousedown]",
4474
- "[onmouseup]",
4475
- "[tabindex]"
4476
- ].join(",");
4477
- const interactiveRoles = /* @__PURE__ */ new Set([
4478
- "button",
4479
- "link",
4480
- "menuitem",
4481
- "option",
4482
- "radio",
4483
- "checkbox",
4484
- "tab",
4485
- "textbox",
4486
- "combobox",
4487
- "slider",
4488
- "spinbutton",
4489
- "search",
4490
- "searchbox"
4491
- ]);
4513
+ const interactiveRolesSet = new Set(interactiveRoles);
4514
+ function isExplicitlyHidden(el, style) {
4515
+ if (el.hasAttribute("hidden")) {
4516
+ return true;
4517
+ }
4518
+ if (el.getAttribute("aria-hidden") === "true") {
4519
+ return true;
4520
+ }
4521
+ if (style.display === "none") {
4522
+ return true;
4523
+ }
4524
+ if (style.visibility === "hidden" || style.visibility === "collapse") {
4525
+ return true;
4526
+ }
4527
+ const opacity = Number.parseFloat(style.opacity);
4528
+ return Number.isFinite(opacity) && opacity <= 0;
4529
+ }
4530
+ function hasVisibleOutOfFlowChild(el) {
4531
+ const children = el.children;
4532
+ for (let i = 0; i < children.length; i++) {
4533
+ const child = children[i];
4534
+ const childStyle = window.getComputedStyle(child);
4535
+ if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4536
+ continue;
4537
+ }
4538
+ const childRect = child.getBoundingClientRect();
4539
+ if (childRect.width > 0 && childRect.height > 0) {
4540
+ return true;
4541
+ }
4542
+ }
4543
+ return false;
4544
+ }
4545
+ function isHiddenByOwnRect(el, style) {
4546
+ if (style.display === "contents") {
4547
+ return false;
4548
+ }
4549
+ const rect = el.getBoundingClientRect();
4550
+ if (rect.width > 0 && rect.height > 0) {
4551
+ return false;
4552
+ }
4553
+ return !hasVisibleOutOfFlowChild(el);
4554
+ }
4555
+ function hasInteractiveTabIndex(el) {
4556
+ const value = el.getAttribute("tabindex");
4557
+ if (value == null) return false;
4558
+ const parsed = Number.parseInt(value, 10);
4559
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4560
+ }
4492
4561
  const roots = [document];
4493
4562
  while (roots.length) {
4494
4563
  const root = roots.pop();
@@ -4504,42 +4573,7 @@ async function markInteractiveElements(page, {
4504
4573
  continue;
4505
4574
  }
4506
4575
  const style = window.getComputedStyle(el);
4507
- let hidden = false;
4508
- if (el.hasAttribute("hidden")) {
4509
- hidden = true;
4510
- } else if (el.getAttribute("aria-hidden") === "true") {
4511
- hidden = true;
4512
- } else if (style.display === "none") {
4513
- hidden = true;
4514
- } else if (style.visibility === "hidden" || style.visibility === "collapse") {
4515
- hidden = true;
4516
- }
4517
- if (!hidden) {
4518
- const opacity = Number.parseFloat(style.opacity);
4519
- if (Number.isFinite(opacity) && opacity <= 0) {
4520
- hidden = true;
4521
- }
4522
- }
4523
- if (!hidden) {
4524
- const rect = el.getBoundingClientRect();
4525
- if (rect.width <= 0 || rect.height <= 0) {
4526
- hidden = true;
4527
- const children = el.children;
4528
- for (let i = 0; i < children.length; i++) {
4529
- const childStyle = window.getComputedStyle(
4530
- children[i]
4531
- );
4532
- if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4533
- continue;
4534
- }
4535
- const childRect = children[i].getBoundingClientRect();
4536
- if (childRect.width > 0 && childRect.height > 0) {
4537
- hidden = false;
4538
- break;
4539
- }
4540
- }
4541
- }
4542
- }
4576
+ const hidden = isExplicitlyHidden(el, style) || isHiddenByOwnRect(el, style);
4543
4577
  if (hidden) {
4544
4578
  el.setAttribute(hiddenAttr, "1");
4545
4579
  el.removeAttribute(markAttribute2);
@@ -4549,11 +4583,13 @@ async function markInteractiveElements(page, {
4549
4583
  let interactive = false;
4550
4584
  if (el.matches(interactiveSelector)) {
4551
4585
  interactive = true;
4586
+ } else if (hasInteractiveTabIndex(el)) {
4587
+ interactive = true;
4552
4588
  } else if (style.cursor === "pointer") {
4553
4589
  interactive = true;
4554
4590
  } else {
4555
4591
  const role = (el.getAttribute("role") || "").toLowerCase();
4556
- if (interactiveRoles.has(role)) {
4592
+ if (interactiveRolesSet.has(role)) {
4557
4593
  interactive = true;
4558
4594
  }
4559
4595
  }
@@ -4598,7 +4634,10 @@ async function markInteractiveElements(page, {
4598
4634
  markAttribute,
4599
4635
  skipIfAlreadyMarked,
4600
4636
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4601
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4637
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4638
+ interactiveSelector: INTERACTIVE_SELECTOR,
4639
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4640
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4602
4641
  }
4603
4642
  );
4604
4643
  };
@@ -4685,7 +4724,7 @@ function isClickable($, el, context) {
4685
4724
  }
4686
4725
  const tag = (el[0]?.tagName || "").toLowerCase();
4687
4726
  if (!tag || ROOT_TAGS.has(tag)) return false;
4688
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4727
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4689
4728
  if (tag === "input") {
4690
4729
  const inputType = String(el.attr("type") || "").toLowerCase();
4691
4730
  if (inputType === "hidden") return false;
@@ -4699,26 +4738,11 @@ function isClickable($, el, context) {
4699
4738
  if (attrs["data-action"] !== void 0) return true;
4700
4739
  if (attrs["data-click"] !== void 0) return true;
4701
4740
  if (attrs["data-toggle"] !== void 0) return true;
4702
- if (attrs.tabindex !== void 0) {
4703
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4704
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4741
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4742
+ return true;
4705
4743
  }
4706
4744
  const role = String(attrs.role || "").toLowerCase();
4707
- if ([
4708
- "button",
4709
- "link",
4710
- "menuitem",
4711
- "option",
4712
- "radio",
4713
- "checkbox",
4714
- "tab",
4715
- "textbox",
4716
- "combobox",
4717
- "slider",
4718
- "spinbutton",
4719
- "search",
4720
- "searchbox"
4721
- ].includes(role)) {
4745
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4722
4746
  return true;
4723
4747
  }
4724
4748
  const className = String(attrs.class || "").toLowerCase();
@@ -9621,7 +9645,17 @@ function formatFieldPath(field, parent) {
9621
9645
  return parent ? `"${parent}.${field}"` : `"${field}"`;
9622
9646
  }
9623
9647
  function formatAllowedValues(values) {
9624
- return values.map((value) => `"${value}"`).join(", ");
9648
+ if (values.length === 0) {
9649
+ return "";
9650
+ }
9651
+ if (values.length === 1) {
9652
+ return `"${values[0]}"`;
9653
+ }
9654
+ if (values.length === 2) {
9655
+ return `"${values[0]}" or "${values[1]}"`;
9656
+ }
9657
+ const quotedValues = values.map((value) => `"${value}"`);
9658
+ return `${quotedValues.slice(0, -1).join(", ")}, or ${quotedValues[quotedValues.length - 1]}`;
9625
9659
  }
9626
9660
  function zeroImportResponse() {
9627
9661
  return {
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Opensteer
3
- } from "../chunk-C6AJL5XU.js";
3
+ } from "../chunk-JZF2WC7U.js";
4
4
  import {
5
5
  normalizeError,
6
6
  resolveCloudSelection,
7
7
  resolveConfigWithEnv
8
- } from "../chunk-LTREUXLO.js";
8
+ } from "../chunk-2ES46WCO.js";
9
9
  import "../chunk-K5CL76MG.js";
10
10
  import "../chunk-3H5RRIMZ.js";
11
11
 
package/dist/index.cjs CHANGED
@@ -1986,7 +1986,7 @@ function sanitizeNamespaceSegment(segment) {
1986
1986
  // src/config.ts
1987
1987
  var DEFAULT_CONFIG = {
1988
1988
  browser: {
1989
- headless: false,
1989
+ headless: void 0,
1990
1990
  executablePath: void 0,
1991
1991
  slowMo: 0,
1992
1992
  mode: void 0,
@@ -4544,6 +4544,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4544
4544
  };
4545
4545
  }
4546
4546
 
4547
+ // src/html/interactive-patterns.ts
4548
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4549
+ "a",
4550
+ "button",
4551
+ "input",
4552
+ "select",
4553
+ "textarea"
4554
+ ]);
4555
+ var INTERACTIVE_SELECTOR_PARTS = [
4556
+ "a[href]",
4557
+ "button",
4558
+ "input",
4559
+ "textarea",
4560
+ "select",
4561
+ '[role="button"]',
4562
+ '[role="link"]',
4563
+ '[role="menuitem"]',
4564
+ '[role="option"]',
4565
+ '[role="radio"]',
4566
+ '[role="checkbox"]',
4567
+ '[role="tab"]',
4568
+ '[contenteditable="true"]',
4569
+ "[onclick]",
4570
+ "[onmousedown]",
4571
+ "[onmouseup]"
4572
+ ];
4573
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4574
+ var INTERACTIVE_ROLE_TOKENS = [
4575
+ "button",
4576
+ "link",
4577
+ "menuitem",
4578
+ "option",
4579
+ "radio",
4580
+ "checkbox",
4581
+ "tab",
4582
+ "textbox",
4583
+ "combobox",
4584
+ "slider",
4585
+ "spinbutton",
4586
+ "search",
4587
+ "searchbox"
4588
+ ];
4589
+ var INTERACTIVE_ROLE_SET = new Set(
4590
+ INTERACTIVE_ROLE_TOKENS
4591
+ );
4592
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4593
+ function hasNonNegativeTabIndex(value) {
4594
+ if (value == null) return false;
4595
+ const parsed = Number.parseInt(value, 10);
4596
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4597
+ }
4598
+
4547
4599
  // src/html/interactivity.ts
4548
4600
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4549
4601
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4558,42 +4610,59 @@ async function markInteractiveElements(page, {
4558
4610
  markAttribute: markAttribute2,
4559
4611
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4560
4612
  hiddenAttr,
4561
- scrollableAttr
4613
+ scrollableAttr,
4614
+ interactiveSelector,
4615
+ interactiveRoles,
4616
+ nonNegativeTabIndexMin
4562
4617
  }) => {
4563
- const interactiveSelector = [
4564
- "a[href]",
4565
- "button",
4566
- "input",
4567
- "textarea",
4568
- "select",
4569
- '[role="button"]',
4570
- '[role="link"]',
4571
- '[role="menuitem"]',
4572
- '[role="option"]',
4573
- '[role="radio"]',
4574
- '[role="checkbox"]',
4575
- '[role="tab"]',
4576
- '[contenteditable="true"]',
4577
- "[onclick]",
4578
- "[onmousedown]",
4579
- "[onmouseup]",
4580
- "[tabindex]"
4581
- ].join(",");
4582
- const interactiveRoles = /* @__PURE__ */ new Set([
4583
- "button",
4584
- "link",
4585
- "menuitem",
4586
- "option",
4587
- "radio",
4588
- "checkbox",
4589
- "tab",
4590
- "textbox",
4591
- "combobox",
4592
- "slider",
4593
- "spinbutton",
4594
- "search",
4595
- "searchbox"
4596
- ]);
4618
+ const interactiveRolesSet = new Set(interactiveRoles);
4619
+ function isExplicitlyHidden(el, style) {
4620
+ if (el.hasAttribute("hidden")) {
4621
+ return true;
4622
+ }
4623
+ if (el.getAttribute("aria-hidden") === "true") {
4624
+ return true;
4625
+ }
4626
+ if (style.display === "none") {
4627
+ return true;
4628
+ }
4629
+ if (style.visibility === "hidden" || style.visibility === "collapse") {
4630
+ return true;
4631
+ }
4632
+ const opacity = Number.parseFloat(style.opacity);
4633
+ return Number.isFinite(opacity) && opacity <= 0;
4634
+ }
4635
+ function hasVisibleOutOfFlowChild(el) {
4636
+ const children = el.children;
4637
+ for (let i = 0; i < children.length; i++) {
4638
+ const child = children[i];
4639
+ const childStyle = window.getComputedStyle(child);
4640
+ if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4641
+ continue;
4642
+ }
4643
+ const childRect = child.getBoundingClientRect();
4644
+ if (childRect.width > 0 && childRect.height > 0) {
4645
+ return true;
4646
+ }
4647
+ }
4648
+ return false;
4649
+ }
4650
+ function isHiddenByOwnRect(el, style) {
4651
+ if (style.display === "contents") {
4652
+ return false;
4653
+ }
4654
+ const rect = el.getBoundingClientRect();
4655
+ if (rect.width > 0 && rect.height > 0) {
4656
+ return false;
4657
+ }
4658
+ return !hasVisibleOutOfFlowChild(el);
4659
+ }
4660
+ function hasInteractiveTabIndex(el) {
4661
+ const value = el.getAttribute("tabindex");
4662
+ if (value == null) return false;
4663
+ const parsed = Number.parseInt(value, 10);
4664
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4665
+ }
4597
4666
  const roots = [document];
4598
4667
  while (roots.length) {
4599
4668
  const root = roots.pop();
@@ -4609,42 +4678,7 @@ async function markInteractiveElements(page, {
4609
4678
  continue;
4610
4679
  }
4611
4680
  const style = window.getComputedStyle(el);
4612
- let hidden = false;
4613
- if (el.hasAttribute("hidden")) {
4614
- hidden = true;
4615
- } else if (el.getAttribute("aria-hidden") === "true") {
4616
- hidden = true;
4617
- } else if (style.display === "none") {
4618
- hidden = true;
4619
- } else if (style.visibility === "hidden" || style.visibility === "collapse") {
4620
- hidden = true;
4621
- }
4622
- if (!hidden) {
4623
- const opacity = Number.parseFloat(style.opacity);
4624
- if (Number.isFinite(opacity) && opacity <= 0) {
4625
- hidden = true;
4626
- }
4627
- }
4628
- if (!hidden) {
4629
- const rect = el.getBoundingClientRect();
4630
- if (rect.width <= 0 || rect.height <= 0) {
4631
- hidden = true;
4632
- const children = el.children;
4633
- for (let i = 0; i < children.length; i++) {
4634
- const childStyle = window.getComputedStyle(
4635
- children[i]
4636
- );
4637
- if (childStyle.position !== "fixed" && childStyle.position !== "absolute") {
4638
- continue;
4639
- }
4640
- const childRect = children[i].getBoundingClientRect();
4641
- if (childRect.width > 0 && childRect.height > 0) {
4642
- hidden = false;
4643
- break;
4644
- }
4645
- }
4646
- }
4647
- }
4681
+ const hidden = isExplicitlyHidden(el, style) || isHiddenByOwnRect(el, style);
4648
4682
  if (hidden) {
4649
4683
  el.setAttribute(hiddenAttr, "1");
4650
4684
  el.removeAttribute(markAttribute2);
@@ -4654,11 +4688,13 @@ async function markInteractiveElements(page, {
4654
4688
  let interactive = false;
4655
4689
  if (el.matches(interactiveSelector)) {
4656
4690
  interactive = true;
4691
+ } else if (hasInteractiveTabIndex(el)) {
4692
+ interactive = true;
4657
4693
  } else if (style.cursor === "pointer") {
4658
4694
  interactive = true;
4659
4695
  } else {
4660
4696
  const role = (el.getAttribute("role") || "").toLowerCase();
4661
- if (interactiveRoles.has(role)) {
4697
+ if (interactiveRolesSet.has(role)) {
4662
4698
  interactive = true;
4663
4699
  }
4664
4700
  }
@@ -4703,7 +4739,10 @@ async function markInteractiveElements(page, {
4703
4739
  markAttribute,
4704
4740
  skipIfAlreadyMarked,
4705
4741
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4706
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4742
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4743
+ interactiveSelector: INTERACTIVE_SELECTOR,
4744
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4745
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4707
4746
  }
4708
4747
  );
4709
4748
  };
@@ -4790,7 +4829,7 @@ function isClickable($, el, context) {
4790
4829
  }
4791
4830
  const tag = (el[0]?.tagName || "").toLowerCase();
4792
4831
  if (!tag || ROOT_TAGS.has(tag)) return false;
4793
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4832
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4794
4833
  if (tag === "input") {
4795
4834
  const inputType = String(el.attr("type") || "").toLowerCase();
4796
4835
  if (inputType === "hidden") return false;
@@ -4804,26 +4843,11 @@ function isClickable($, el, context) {
4804
4843
  if (attrs["data-action"] !== void 0) return true;
4805
4844
  if (attrs["data-click"] !== void 0) return true;
4806
4845
  if (attrs["data-toggle"] !== void 0) return true;
4807
- if (attrs.tabindex !== void 0) {
4808
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4809
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4846
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4847
+ return true;
4810
4848
  }
4811
4849
  const role = String(attrs.role || "").toLowerCase();
4812
- if ([
4813
- "button",
4814
- "link",
4815
- "menuitem",
4816
- "option",
4817
- "radio",
4818
- "checkbox",
4819
- "tab",
4820
- "textbox",
4821
- "combobox",
4822
- "slider",
4823
- "spinbutton",
4824
- "search",
4825
- "searchbox"
4826
- ].includes(role)) {
4850
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4827
4851
  return true;
4828
4852
  }
4829
4853
  const className = String(attrs.class || "").toLowerCase();
@@ -9739,7 +9763,17 @@ function formatFieldPath(field, parent) {
9739
9763
  return parent ? `"${parent}.${field}"` : `"${field}"`;
9740
9764
  }
9741
9765
  function formatAllowedValues(values) {
9742
- return values.map((value) => `"${value}"`).join(", ");
9766
+ if (values.length === 0) {
9767
+ return "";
9768
+ }
9769
+ if (values.length === 1) {
9770
+ return `"${values[0]}"`;
9771
+ }
9772
+ if (values.length === 2) {
9773
+ return `"${values[0]}" or "${values[1]}"`;
9774
+ }
9775
+ const quotedValues = values.map((value) => `"${value}"`);
9776
+ return `${quotedValues.slice(0, -1).join(", ")}, or ${quotedValues[quotedValues.length - 1]}`;
9743
9777
  }
9744
9778
  function zeroImportResponse() {
9745
9779
  return {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "./chunk-O4HVMKX2.js";
3
+ } from "./chunk-ZRCFF546.js";
4
4
  import {
5
5
  ActionWsClient,
6
6
  BrowserPool,
@@ -80,7 +80,7 @@ import {
80
80
  switchTab,
81
81
  typeText,
82
82
  waitForVisualStability
83
- } from "./chunk-C6AJL5XU.js";
83
+ } from "./chunk-JZF2WC7U.js";
84
84
  import {
85
85
  CloudCdpClient,
86
86
  CloudSessionClient,
@@ -98,7 +98,7 @@ import {
98
98
  isCloudSessionStatus,
99
99
  normalizeNamespace,
100
100
  resolveNamespaceDir
101
- } from "./chunk-LTREUXLO.js";
101
+ } from "./chunk-2ES46WCO.js";
102
102
  import {
103
103
  detectChromePaths,
104
104
  expandHome,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opensteer",
3
- "version": "0.6.8",
3
+ "version": "0.6.11",
4
4
  "description": "Open-source browser automation SDK and CLI that lets AI agents build complex scrapers directly in your codebase.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -12,6 +12,24 @@ const opensteer = new Opensteer({
12
12
  await opensteer.launch({ headless: false });
13
13
  await opensteer.close();
14
14
 
15
+ // Use the user's local Chrome profile state:
16
+ const opensteer = new Opensteer({
17
+ name: "my-scraper",
18
+ browser: {
19
+ mode: "real",
20
+ profileDirectory: "Default",
21
+ headless: false,
22
+ },
23
+ });
24
+ await opensteer.launch();
25
+
26
+ // Or pass real-browser mode at launch time:
27
+ await opensteer.launch({
28
+ mode: "real",
29
+ profileDirectory: "Default",
30
+ headless: false,
31
+ });
32
+
15
33
  // Wrap an existing page instance:
16
34
  const opensteer = Opensteer.from(existingPage, { name: "my-scraper" });
17
35
  ```