@nuanu-ai/agentbrowse 0.2.46 → 0.2.48

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 (190) hide show
  1. package/README.md +69 -10
  2. package/dist/agentpay-gateway.d.ts +9 -0
  3. package/dist/agentpay-gateway.d.ts.map +1 -1
  4. package/dist/agentpay-gateway.js +30 -0
  5. package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
  6. package/dist/agentpay-stagehand-llm.js +9 -1
  7. package/dist/command-api-tracing.d.ts +19 -0
  8. package/dist/command-api-tracing.d.ts.map +1 -0
  9. package/dist/command-api-tracing.js +137 -0
  10. package/dist/commands/act.d.ts.map +1 -1
  11. package/dist/commands/act.js +822 -670
  12. package/dist/commands/act.test-harness.d.ts +6 -0
  13. package/dist/commands/act.test-harness.d.ts.map +1 -1
  14. package/dist/commands/act.test-harness.js +44 -1
  15. package/dist/commands/action-acceptance.d.ts.map +1 -1
  16. package/dist/commands/action-acceptance.js +115 -0
  17. package/dist/commands/captcha-solve.d.ts.map +1 -1
  18. package/dist/commands/captcha-solve.js +83 -16
  19. package/dist/commands/click-action-executor.d.ts +0 -1
  20. package/dist/commands/click-action-executor.d.ts.map +1 -1
  21. package/dist/commands/click-action-executor.js +31 -77
  22. package/dist/commands/close.d.ts +3 -3
  23. package/dist/commands/close.d.ts.map +1 -1
  24. package/dist/commands/close.js +178 -0
  25. package/dist/commands/descriptor-validation.d.ts.map +1 -1
  26. package/dist/commands/descriptor-validation.js +75 -57
  27. package/dist/commands/end-session.d.ts +25 -0
  28. package/dist/commands/end-session.d.ts.map +1 -0
  29. package/dist/commands/end-session.js +161 -0
  30. package/dist/commands/extract-stagehand-executor.js +1 -1
  31. package/dist/commands/extract.d.ts.map +1 -1
  32. package/dist/commands/extract.js +339 -202
  33. package/dist/commands/fill-secret.d.ts +3 -3
  34. package/dist/commands/fill-secret.d.ts.map +1 -1
  35. package/dist/commands/fill-secret.js +419 -234
  36. package/dist/commands/get-secrets-catalog.d.ts.map +1 -1
  37. package/dist/commands/get-secrets-catalog.js +66 -5
  38. package/dist/commands/interaction-kernel.d.ts +46 -0
  39. package/dist/commands/interaction-kernel.d.ts.map +1 -0
  40. package/dist/commands/interaction-kernel.js +215 -0
  41. package/dist/commands/launch.d.ts +0 -2
  42. package/dist/commands/launch.d.ts.map +1 -1
  43. package/dist/commands/launch.js +109 -17
  44. package/dist/commands/navigate.d.ts.map +1 -1
  45. package/dist/commands/navigate.js +188 -45
  46. package/dist/commands/observe-accessibility.d.ts.map +1 -1
  47. package/dist/commands/observe-accessibility.js +50 -39
  48. package/dist/commands/observe-dom-label-contract.d.ts.map +1 -1
  49. package/dist/commands/observe-dom-label-contract.js +5 -0
  50. package/dist/commands/observe-inventory.d.ts +13 -0
  51. package/dist/commands/observe-inventory.d.ts.map +1 -1
  52. package/dist/commands/observe-inventory.js +320 -65
  53. package/dist/commands/observe-persistence.d.ts.map +1 -1
  54. package/dist/commands/observe-persistence.js +3 -0
  55. package/dist/commands/observe-projection.d.ts +1 -0
  56. package/dist/commands/observe-projection.d.ts.map +1 -1
  57. package/dist/commands/observe-projection.js +7 -2
  58. package/dist/commands/observe-protected.d.ts +1 -0
  59. package/dist/commands/observe-protected.d.ts.map +1 -1
  60. package/dist/commands/observe-protected.js +9 -4
  61. package/dist/commands/observe-semantics.d.ts.map +1 -1
  62. package/dist/commands/observe-semantics.js +5 -2
  63. package/dist/commands/observe-stagehand.d.ts +1 -0
  64. package/dist/commands/observe-stagehand.d.ts.map +1 -1
  65. package/dist/commands/observe-stagehand.js +2 -0
  66. package/dist/commands/observe.d.ts +2 -0
  67. package/dist/commands/observe.d.ts.map +1 -1
  68. package/dist/commands/observe.js +387 -203
  69. package/dist/commands/observe.test-harness.d.ts +8 -0
  70. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  71. package/dist/commands/observe.test-harness.js +48 -1
  72. package/dist/commands/poll-secret.d.ts +6 -0
  73. package/dist/commands/poll-secret.d.ts.map +1 -0
  74. package/dist/commands/poll-secret.js +159 -0
  75. package/dist/commands/request-secret.d.ts +6 -0
  76. package/dist/commands/request-secret.d.ts.map +1 -0
  77. package/dist/commands/request-secret.js +284 -0
  78. package/dist/commands/screenshot.d.ts.map +1 -1
  79. package/dist/commands/screenshot.js +172 -7
  80. package/dist/commands/select-action-executor.d.ts.map +1 -1
  81. package/dist/commands/semantic-observe.d.ts +4 -0
  82. package/dist/commands/semantic-observe.d.ts.map +1 -1
  83. package/dist/commands/semantic-observe.js +388 -17
  84. package/dist/commands/start-session.d.ts +31 -0
  85. package/dist/commands/start-session.d.ts.map +1 -0
  86. package/dist/commands/start-session.js +347 -0
  87. package/dist/commands/status.d.ts +2 -1
  88. package/dist/commands/status.d.ts.map +1 -1
  89. package/dist/commands/status.js +166 -144
  90. package/dist/control-semantics.d.ts +1 -0
  91. package/dist/control-semantics.d.ts.map +1 -1
  92. package/dist/control-semantics.js +51 -9
  93. package/dist/index.d.ts.map +1 -1
  94. package/dist/index.js +144 -45
  95. package/dist/otel-exporter.d.ts +58 -0
  96. package/dist/otel-exporter.d.ts.map +1 -0
  97. package/dist/otel-exporter.js +263 -0
  98. package/dist/otel-projector.d.ts +75 -0
  99. package/dist/otel-projector.d.ts.map +1 -0
  100. package/dist/otel-projector.js +409 -0
  101. package/dist/owned-browser.d.ts +1 -1
  102. package/dist/owned-browser.d.ts.map +1 -1
  103. package/dist/owned-browser.js +13 -1
  104. package/dist/owned-process.d.ts +2 -0
  105. package/dist/owned-process.d.ts.map +1 -1
  106. package/dist/owned-process.js +7 -3
  107. package/dist/playwright-runtime.d.ts +1 -1
  108. package/dist/playwright-runtime.d.ts.map +1 -1
  109. package/dist/playwright-runtime.js +8 -8
  110. package/dist/run-observability.d.ts +25 -0
  111. package/dist/run-observability.d.ts.map +1 -0
  112. package/dist/run-observability.js +115 -0
  113. package/dist/run-store.d.ts +274 -0
  114. package/dist/run-store.d.ts.map +1 -0
  115. package/dist/run-store.js +631 -0
  116. package/dist/runtime-metrics.d.ts +27 -0
  117. package/dist/runtime-metrics.d.ts.map +1 -0
  118. package/dist/runtime-metrics.js +66 -0
  119. package/dist/runtime-page-state.d.ts +11 -0
  120. package/dist/runtime-page-state.d.ts.map +1 -0
  121. package/dist/runtime-page-state.js +62 -0
  122. package/dist/runtime-protected-state.d.ts +16 -0
  123. package/dist/runtime-protected-state.d.ts.map +1 -0
  124. package/dist/runtime-protected-state.js +157 -0
  125. package/dist/runtime-state.d.ts +10 -44
  126. package/dist/runtime-state.d.ts.map +1 -1
  127. package/dist/runtime-state.js +57 -222
  128. package/dist/secrets/backend.d.ts +65 -16
  129. package/dist/secrets/backend.d.ts.map +1 -1
  130. package/dist/secrets/backend.js +135 -95
  131. package/dist/secrets/catalog-sync.d.ts.map +1 -1
  132. package/dist/secrets/catalog-sync.js +4 -1
  133. package/dist/secrets/form-matcher.d.ts +5 -5
  134. package/dist/secrets/form-matcher.d.ts.map +1 -1
  135. package/dist/secrets/form-matcher.js +292 -164
  136. package/dist/secrets/intent-output.d.ts +6 -10
  137. package/dist/secrets/intent-output.d.ts.map +1 -1
  138. package/dist/secrets/intent-output.js +4 -58
  139. package/dist/secrets/mock-agentpay-cabinet.d.ts +38 -27
  140. package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -1
  141. package/dist/secrets/mock-agentpay-cabinet.js +177 -111
  142. package/dist/secrets/protected-artifact-guard.d.ts +2 -2
  143. package/dist/secrets/protected-artifact-guard.d.ts.map +1 -1
  144. package/dist/secrets/protected-artifact-guard.js +2 -2
  145. package/dist/secrets/protected-bindings.d.ts +1 -1
  146. package/dist/secrets/protected-bindings.d.ts.map +1 -1
  147. package/dist/secrets/protected-bindings.js +6 -0
  148. package/dist/secrets/protected-field-semantics.d.ts +9 -0
  149. package/dist/secrets/protected-field-semantics.d.ts.map +1 -0
  150. package/dist/secrets/protected-field-semantics.js +154 -0
  151. package/dist/secrets/protected-field-values.d.ts.map +1 -1
  152. package/dist/secrets/protected-field-values.js +3 -3
  153. package/dist/secrets/protected-fill.d.ts +1 -1
  154. package/dist/secrets/protected-fill.d.ts.map +1 -1
  155. package/dist/secrets/protected-fill.js +45 -149
  156. package/dist/secrets/protected-value-adapters.d.ts +2 -1
  157. package/dist/secrets/protected-value-adapters.d.ts.map +1 -1
  158. package/dist/secrets/protected-value-adapters.js +80 -1
  159. package/dist/secrets/request-output.d.ts +11 -0
  160. package/dist/secrets/request-output.d.ts.map +1 -0
  161. package/dist/secrets/request-output.js +75 -0
  162. package/dist/secrets/types.d.ts +15 -9
  163. package/dist/secrets/types.d.ts.map +1 -1
  164. package/dist/secrets/types.js +3 -0
  165. package/dist/session-event-exporter.d.ts +36 -0
  166. package/dist/session-event-exporter.d.ts.map +1 -0
  167. package/dist/session-event-exporter.js +428 -0
  168. package/dist/session.d.ts +16 -7
  169. package/dist/session.d.ts.map +1 -1
  170. package/dist/session.js +150 -23
  171. package/dist/sessions-backend.d.ts +354 -0
  172. package/dist/sessions-backend.d.ts.map +1 -0
  173. package/dist/sessions-backend.js +126 -0
  174. package/dist/solver/browser-launcher.d.ts +1 -1
  175. package/dist/solver/browser-launcher.d.ts.map +1 -1
  176. package/dist/solver/browser-launcher.js +39 -13
  177. package/dist/solver/captcha-solver.d.ts.map +1 -1
  178. package/dist/solver/captcha-solver.js +8 -1
  179. package/dist/solver/types.d.ts +1 -0
  180. package/dist/solver/types.d.ts.map +1 -1
  181. package/dist/workflow-session-completion.d.ts +33 -0
  182. package/dist/workflow-session-completion.d.ts.map +1 -0
  183. package/dist/workflow-session-completion.js +156 -0
  184. package/package.json +9 -1
  185. package/dist/commands/create-intent.d.ts +0 -6
  186. package/dist/commands/create-intent.d.ts.map +0 -1
  187. package/dist/commands/create-intent.js +0 -75
  188. package/dist/commands/poll-intent.d.ts +0 -6
  189. package/dist/commands/poll-intent.d.ts.map +0 -1
  190. package/dist/commands/poll-intent.js +0 -57
@@ -62,7 +62,83 @@ export function inferDirectionalControlFallbackFromEvidence(evidence) {
62
62
  }
63
63
  return undefined;
64
64
  }
65
+ export function inferDisabledStateFromSemanticEvidence(evidence) {
66
+ const normalize = (value) => (value ?? '').replace(/\s+/g, ' ').trim().toLowerCase();
67
+ const tagName = normalize(evidence.tagName);
68
+ const role = normalize(evidence.role);
69
+ const inputType = normalize(evidence.inputType);
70
+ const className = normalize(evidence.className);
71
+ const nonClassBlob = [
72
+ evidence.datasetText,
73
+ evidence.dataState,
74
+ evidence.dataStatus,
75
+ evidence.ariaLabel,
76
+ ]
77
+ .map(normalize)
78
+ .filter(Boolean)
79
+ .join(' ');
80
+ const fullSemanticBlob = [className, nonClassBlob].filter(Boolean).join(' ');
81
+ const disabledLikeRe = /(?:disabled?|disable|inactive|unselectable)\b/;
82
+ // Native fields should trust real DOM/ARIA/data-state signals, not styling classes
83
+ // like Kupibilet's `ym-disable-keys`.
84
+ if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
85
+ return disabledLikeRe.test(nonClassBlob);
86
+ }
87
+ const collectionOrButtonLike = tagName === 'button' ||
88
+ role === 'button' ||
89
+ role === 'option' ||
90
+ role === 'menuitem' ||
91
+ role === 'listitem' ||
92
+ role === 'gridcell' ||
93
+ role === 'tab' ||
94
+ role === 'radio' ||
95
+ inputType === 'button' ||
96
+ inputType === 'submit' ||
97
+ inputType === 'reset';
98
+ return disabledLikeRe.test(collectionOrButtonLike ? fullSemanticBlob : nonClassBlob);
99
+ }
65
100
  const INFER_STRUCTURED_CELL_VARIANT_HELPER_SCRIPT = `const inferStructuredCellVariantFromEvidence = ${inferStructuredCellVariantFromEvidence.toString()};`;
101
+ const INFER_DISABLED_STATE_FROM_SEMANTIC_EVIDENCE_HELPER_SCRIPT = String.raw `
102
+ const inferDisabledStateFromSemanticEvidence = (evidence) => {
103
+ const normalizeDisabledSemanticValue = (value) =>
104
+ (value || '').replace(/\s+/g, ' ').trim().toLowerCase();
105
+
106
+ const tagName = normalizeDisabledSemanticValue(evidence?.tagName);
107
+ const role = normalizeDisabledSemanticValue(evidence?.role);
108
+ const inputType = normalizeDisabledSemanticValue(evidence?.inputType);
109
+ const className = normalizeDisabledSemanticValue(evidence?.className);
110
+ const nonClassBlob = [
111
+ evidence?.datasetText,
112
+ evidence?.dataState,
113
+ evidence?.dataStatus,
114
+ evidence?.ariaLabel,
115
+ ]
116
+ .map(normalizeDisabledSemanticValue)
117
+ .filter(Boolean)
118
+ .join(' ');
119
+ const fullSemanticBlob = [className, nonClassBlob].filter(Boolean).join(' ');
120
+ const disabledLikeRe = /(?:disabled?|disable|inactive|unselectable)\b/;
121
+
122
+ if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
123
+ return disabledLikeRe.test(nonClassBlob);
124
+ }
125
+
126
+ const collectionOrButtonLike =
127
+ tagName === 'button' ||
128
+ role === 'button' ||
129
+ role === 'option' ||
130
+ role === 'menuitem' ||
131
+ role === 'listitem' ||
132
+ role === 'gridcell' ||
133
+ role === 'tab' ||
134
+ role === 'radio' ||
135
+ inputType === 'button' ||
136
+ inputType === 'submit' ||
137
+ inputType === 'reset';
138
+
139
+ return disabledLikeRe.test(collectionOrButtonLike ? fullSemanticBlob : nonClassBlob);
140
+ };
141
+ `;
66
142
  const INFER_DIRECTIONAL_CONTROL_FALLBACK_HELPER_SCRIPT = String.raw `
67
143
  const inferDirectionalControlFallbackFromEvidence = (evidence) => {
68
144
  const normalizeDirectionalControlFallbackValue = (value) => {
@@ -140,6 +216,7 @@ function enrichObservedTargetSemantics(target) {
140
216
  inputName: target.inputName,
141
217
  inputType: target.inputType,
142
218
  autocomplete: target.autocomplete,
219
+ ariaAutocomplete: target.ariaAutocomplete,
143
220
  states: target.states,
144
221
  };
145
222
  const allowedActions = inferAllowedActionsFromFacts(facts);
@@ -166,6 +243,7 @@ function hasStagehandDomFacts(domFacts) {
166
243
  (domFacts.kind ||
167
244
  domFacts.role ||
168
245
  domFacts.placeholder ||
246
+ domFacts.ariaAutocomplete ||
169
247
  domFacts.value ||
170
248
  domFacts.text ||
171
249
  domFacts.currentValue ||
@@ -182,6 +260,9 @@ function scoreStagehandLocatorSnapshot(snapshot) {
182
260
  if (snapshot.domFacts?.placeholder) {
183
261
  score += 1;
184
262
  }
263
+ if (snapshot.domFacts?.ariaAutocomplete) {
264
+ score += 1;
265
+ }
185
266
  if (snapshot.domFacts?.value) {
186
267
  score += 1;
187
268
  }
@@ -282,6 +363,7 @@ const STAGEHAND_DOM_FACTS_SCRIPT = String.raw `
282
363
  inputName: element.getAttribute('name') || undefined,
283
364
  inputType: element.getAttribute('type') || undefined,
284
365
  autocomplete: element.getAttribute('autocomplete') || undefined,
366
+ ariaAutocomplete: element.getAttribute('aria-autocomplete') || undefined,
285
367
  value: directValue || undefined,
286
368
  text: directText || undefined,
287
369
  currentValue: currentValue || undefined,
@@ -421,9 +503,67 @@ async function collectDomTargetsFromDocument(context, options) {
421
503
 
422
504
  return undefined;
423
505
  };
506
+ const hiddenChoiceSiblingControlOf = (element) => {
507
+ if (!isHTMLElementNode(element)) return undefined;
508
+
509
+ const parent = composedParentElement(element);
510
+ if (!isHTMLElementNode(parent)) {
511
+ return undefined;
512
+ }
513
+
514
+ const siblingChoiceControls = Array.from(parent.children).filter((candidate) => {
515
+ if (candidate === element || !isHTMLInputNode(candidate)) {
516
+ return false;
517
+ }
518
+
519
+ const type = (candidate.type || '').toLowerCase();
520
+ if (type !== 'radio' && type !== 'checkbox') {
521
+ return false;
522
+ }
523
+
524
+ const style = window.getComputedStyle(candidate);
525
+ const rect = candidate.getBoundingClientRect();
526
+ return (
527
+ style.display === 'none' ||
528
+ style.visibility === 'hidden' ||
529
+ style.pointerEvents === 'none' ||
530
+ Number(style.opacity || '1') < 0.05 ||
531
+ rect.width < 4 ||
532
+ rect.height < 4
533
+ );
534
+ });
535
+
536
+ if (siblingChoiceControls.length !== 1) {
537
+ return undefined;
538
+ }
539
+
540
+ const visibleNonChoiceSiblings = Array.from(parent.children).filter(
541
+ (candidate) =>
542
+ candidate !== siblingChoiceControls[0] &&
543
+ isHTMLElementNode(candidate) &&
544
+ isVisible(candidate)
545
+ );
546
+
547
+ if (visibleNonChoiceSiblings.length !== 1 || visibleNonChoiceSiblings[0] !== element) {
548
+ return undefined;
549
+ }
550
+
551
+ return siblingChoiceControls[0];
552
+ };
553
+ const associatedChoiceControlOf = (element) => {
554
+ if (isHTMLInputNode(element)) {
555
+ const type = (element.type || '').toLowerCase();
556
+ if (type === 'radio' || type === 'checkbox') {
557
+ return element;
558
+ }
559
+ }
560
+
561
+ return labelBackedChoiceControlOf(element) || hiddenChoiceSiblingControlOf(element);
562
+ };
424
563
  ${TRANSPARENT_ACTIONABLE_CONTROL_HELPER_SCRIPT}
425
564
  ${OBSERVE_DOM_LABEL_CONTRACT_HELPER_SCRIPT}
426
565
  ${INFER_STRUCTURED_CELL_VARIANT_HELPER_SCRIPT}
566
+ ${INFER_DISABLED_STATE_FROM_SEMANTIC_EVIDENCE_HELPER_SCRIPT}
427
567
  ${INFER_DIRECTIONAL_CONTROL_FALLBACK_HELPER_SCRIPT}
428
568
 
429
569
  const normalizeDescriptorText = (value) => observedNormalizeDescriptorText(value);
@@ -602,8 +742,15 @@ async function collectDomTargetsFromDocument(context, options) {
602
742
  }
603
743
 
604
744
  const matches = Array.from(root.querySelectorAll(selector)).concat(
745
+ Array.from(root.querySelectorAll('*')).filter(
746
+ (candidate) =>
747
+ isHTMLElementNode(candidate) &&
748
+ !candidate.matches?.(selector) &&
749
+ !isHTMLLabelNode(candidate) &&
750
+ Boolean(associatedChoiceControlOf(candidate))
751
+ ),
605
752
  Array.from(root.querySelectorAll('label')).filter((candidate) =>
606
- isHTMLElementNode(candidate) && Boolean(labelBackedChoiceControlOf(candidate))
753
+ isHTMLElementNode(candidate) && Boolean(associatedChoiceControlOf(candidate))
607
754
  )
608
755
  );
609
756
  for (const candidate of matches) {
@@ -761,6 +908,8 @@ async function collectDomTargetsFromDocument(context, options) {
761
908
  if (tag === 'input') {
762
909
  const inputType = inputTypeOf(element);
763
910
  if (isButtonLikeInput(element)) return 'Button';
911
+ if (inputType === 'checkbox') return 'Checkbox';
912
+ if (inputType === 'radio') return 'Radio';
764
913
  if (inputType === 'tel') return 'Phone input';
765
914
  if (inputType === 'email') return 'Email input';
766
915
  if (inputType === 'password') return 'Password input';
@@ -783,7 +932,8 @@ async function collectDomTargetsFromDocument(context, options) {
783
932
  return undefined;
784
933
  };
785
934
 
786
- const inferRole = (element) => observedInferRole(element) || undefined;
935
+ const inferRole = (element) =>
936
+ isHTMLElementNode(element) ? observedInferRole(element) || undefined : undefined;
787
937
 
788
938
  const kindOf = (element) => {
789
939
  const tag = element.tagName.toLowerCase();
@@ -1068,7 +1218,7 @@ async function collectDomTargetsFromDocument(context, options) {
1068
1218
  const tag = element.tagName.toLowerCase();
1069
1219
  const role = element.getAttribute('role')?.trim().toLowerCase() || '';
1070
1220
  if (role) return false;
1071
- if (labelBackedChoiceControlOf(element)) return false;
1221
+ if (associatedChoiceControlOf(element)) return false;
1072
1222
  if (
1073
1223
  ['body', 'main', 'form', 'button', 'input', 'textarea', 'select', 'a', 'label'].includes(
1074
1224
  tag
@@ -1112,9 +1262,9 @@ async function collectDomTargetsFromDocument(context, options) {
1112
1262
  if (hasSemanticInteractiveAncestor(element)) return false;
1113
1263
 
1114
1264
  const tag = element.tagName.toLowerCase();
1115
- const labelBackedChoice = labelBackedChoiceControlOf(element);
1265
+ const associatedChoiceControl = associatedChoiceControlOf(element);
1116
1266
  if (['body', 'main', 'form'].includes(tag)) return false;
1117
- if (tag === 'label' && !labelBackedChoice) return false;
1267
+ if (tag === 'label' && !associatedChoiceControl) return false;
1118
1268
 
1119
1269
  const style = window.getComputedStyle(element);
1120
1270
  if (style.pointerEvents === 'none') return false;
@@ -1144,7 +1294,12 @@ async function collectDomTargetsFromDocument(context, options) {
1144
1294
  clickableSemanticBlobOf(element)
1145
1295
  );
1146
1296
 
1147
- if (!structuredLike && !explicitClick && !labelBackedChoice && descriptorText.length < 12) {
1297
+ if (
1298
+ !structuredLike &&
1299
+ !explicitClick &&
1300
+ !associatedChoiceControl &&
1301
+ descriptorText.length < 12
1302
+ ) {
1148
1303
  return false;
1149
1304
  }
1150
1305
 
@@ -1685,7 +1840,9 @@ async function collectDomTargetsFromDocument(context, options) {
1685
1840
 
1686
1841
  const stateOf = (element) => {
1687
1842
  const states = {};
1688
- const labelBackedChoice = labelBackedChoiceControlOf(element);
1843
+ const associatedChoiceControl = associatedChoiceControlOf(element);
1844
+ const role = inferRole(element) || inferRole(associatedChoiceControl);
1845
+ const tag = element.tagName.toLowerCase();
1689
1846
 
1690
1847
  const ariaDisabled = readBooleanState(element, 'aria-disabled');
1691
1848
  if (ariaDisabled !== undefined) states.disabled = ariaDisabled;
@@ -1732,21 +1889,31 @@ async function collectDomTargetsFromDocument(context, options) {
1732
1889
  const dataset = Object.values(element.dataset || {})
1733
1890
  .join(' ')
1734
1891
  .toLowerCase();
1735
- const semanticBlob =
1736
- className +
1737
- ' ' +
1738
- dataset +
1739
- ' ' +
1740
- (element.getAttribute('data-state') || '').toLowerCase() +
1741
- ' ' +
1742
- (element.getAttribute('data-status') || '').toLowerCase() +
1743
- ' ' +
1744
- (element.getAttribute('aria-label') || '').toLowerCase();
1892
+ const dataState = (element.getAttribute('data-state') || '').toLowerCase();
1893
+ const dataStatus = (element.getAttribute('data-status') || '').toLowerCase();
1894
+ const ariaLabel = (element.getAttribute('aria-label') || '').toLowerCase();
1895
+ const semanticBlob = className + ' ' + dataset + ' ' + dataState + ' ' + dataStatus + ' ' + ariaLabel;
1896
+ const inputType = isHTMLInputNode(element) ? (element.type || '').toLowerCase() : undefined;
1745
1897
 
1746
1898
  if (/(?:selected|active|current)\b/.test(semanticBlob)) {
1747
1899
  if (states.selected === undefined) states.selected = true;
1748
1900
  if (states.current === undefined) states.current = true;
1749
1901
  }
1902
+ if (
1903
+ inferDisabledStateFromSemanticEvidence({
1904
+ tagName: tag,
1905
+ role,
1906
+ inputType,
1907
+ className,
1908
+ datasetText: dataset,
1909
+ dataState,
1910
+ dataStatus,
1911
+ ariaLabel,
1912
+ })
1913
+ ) {
1914
+ states.disabled = true;
1915
+ states.selectable = false;
1916
+ }
1750
1917
  if (/(?:occupied|unavailable|sold|taken|reserved|booked)\b/.test(semanticBlob)) {
1751
1918
  states.occupied = true;
1752
1919
  states.selectable = false;
@@ -1756,8 +1923,6 @@ async function collectDomTargetsFromDocument(context, options) {
1756
1923
  states.premium = true;
1757
1924
  }
1758
1925
  if (states.selectable === undefined && states.disabled !== true && states.occupied !== true) {
1759
- const role = inferRole(element);
1760
- const tag = element.tagName.toLowerCase();
1761
1926
  if (role === 'gridcell' || tag === 'button') {
1762
1927
  states.selectable = true;
1763
1928
  }
@@ -1773,15 +1938,17 @@ async function collectDomTargetsFromDocument(context, options) {
1773
1938
  }
1774
1939
  }
1775
1940
 
1776
- if (isHTMLInputNode(labelBackedChoice)) {
1777
- const type = (labelBackedChoice.type || 'text').toLowerCase();
1941
+ if (isHTMLInputNode(associatedChoiceControl)) {
1942
+ const type = (associatedChoiceControl.type || 'text').toLowerCase();
1778
1943
  if (type === 'checkbox' || type === 'radio') {
1779
- states.checked = labelBackedChoice.indeterminate ? 'mixed' : labelBackedChoice.checked;
1944
+ states.checked = associatedChoiceControl.indeterminate
1945
+ ? 'mixed'
1946
+ : associatedChoiceControl.checked;
1780
1947
  }
1781
- if (labelBackedChoice.disabled) {
1948
+ if (associatedChoiceControl.disabled) {
1782
1949
  states.disabled = true;
1783
1950
  }
1784
- if (labelBackedChoice.readOnly) {
1951
+ if (associatedChoiceControl.readOnly) {
1785
1952
  states.readonly = true;
1786
1953
  }
1787
1954
  }
@@ -2264,7 +2431,7 @@ async function collectDomTargetsFromDocument(context, options) {
2264
2431
  );
2265
2432
  };
2266
2433
 
2267
- const isVisualGridSquareElement = (element) => {
2434
+ const isVisualGridTokenElement = (element) => {
2268
2435
  if (!isHTMLElementNode(element) || !isVisible(element)) {
2269
2436
  return false;
2270
2437
  }
@@ -2273,10 +2440,14 @@ async function collectDomTargetsFromDocument(context, options) {
2273
2440
  }
2274
2441
 
2275
2442
  const rect = element.getBoundingClientRect();
2276
- if (rect.width < 24 || rect.width > 52 || rect.height < 24 || rect.height > 52) {
2443
+ if (rect.width < 24 || rect.height < 16 || rect.width > 88 || rect.height > 56) {
2277
2444
  return false;
2278
2445
  }
2279
- if (Math.abs(rect.width - rect.height) > Math.max(8, Math.min(rect.width, rect.height) * 0.35)) {
2446
+ const text = compactText(textOf(element));
2447
+ const axisLabelLike = /^\d{1,3}$/.test(text) || /^[a-z]$/i.test(text);
2448
+ const shorterSide = Math.min(rect.width, rect.height);
2449
+ const longerSide = Math.max(rect.width, rect.height);
2450
+ if (shorterSide <= 0 || longerSide / shorterSide > (axisLabelLike ? 4.5 : 2.6)) {
2280
2451
  return false;
2281
2452
  }
2282
2453
  if (rect.width * rect.height < 576) {
@@ -2308,6 +2479,12 @@ async function collectDomTargetsFromDocument(context, options) {
2308
2479
  'svg, path, use, circle, line, polyline, polygon'
2309
2480
  ).length;
2310
2481
  const states = {};
2482
+ const pointerEventsDisabled = style.pointerEvents === 'none';
2483
+
2484
+ if (pointerEventsDisabled) {
2485
+ states.disabled = true;
2486
+ states.selectable = false;
2487
+ }
2311
2488
 
2312
2489
  if (glyphCount > 0 && !hasFilledBackground) {
2313
2490
  states.occupied = true;
@@ -2316,7 +2493,9 @@ async function collectDomTargetsFromDocument(context, options) {
2316
2493
  return states;
2317
2494
  }
2318
2495
 
2319
- states.selectable = true;
2496
+ if (!pointerEventsDisabled) {
2497
+ states.selectable = true;
2498
+ }
2320
2499
  if (glyphCount > 0 && hasFilledBackground) {
2321
2500
  states.selected = true;
2322
2501
  }
@@ -2382,7 +2561,7 @@ async function collectDomTargetsFromDocument(context, options) {
2382
2561
  };
2383
2562
 
2384
2563
  const isVisualSeatCellElement = (element) => {
2385
- if (!isVisualGridSquareElement(element)) {
2564
+ if (!isVisualGridTokenElement(element)) {
2386
2565
  return false;
2387
2566
  }
2388
2567
  if (hasSemanticInteractiveAncestor(element)) {
@@ -2395,10 +2574,6 @@ async function collectDomTargetsFromDocument(context, options) {
2395
2574
  }
2396
2575
 
2397
2576
  const style = window.getComputedStyle(element);
2398
- if (style.pointerEvents === 'none') {
2399
- return false;
2400
- }
2401
-
2402
2577
  const background = parseColor(style.backgroundColor);
2403
2578
  const border = parseColor(style.borderColor);
2404
2579
  const glyphCount = element.querySelectorAll(
@@ -2486,15 +2661,66 @@ async function collectDomTargetsFromDocument(context, options) {
2486
2661
  return ranked[0]?.header;
2487
2662
  };
2488
2663
 
2664
+ const groupHeadersByBand = (headers, axis) => {
2665
+ const sorted = [...headers].sort((left, right) => {
2666
+ const leftCenter =
2667
+ axis === 'column'
2668
+ ? left.rect.top + left.rect.height / 2
2669
+ : left.rect.left + left.rect.width / 2;
2670
+ const rightCenter =
2671
+ axis === 'column'
2672
+ ? right.rect.top + right.rect.height / 2
2673
+ : right.rect.left + right.rect.width / 2;
2674
+ return leftCenter - rightCenter;
2675
+ });
2676
+ const bands = [];
2677
+
2678
+ for (const header of sorted) {
2679
+ const center =
2680
+ axis === 'column'
2681
+ ? header.rect.top + header.rect.height / 2
2682
+ : header.rect.left + header.rect.width / 2;
2683
+ const tolerance =
2684
+ axis === 'column'
2685
+ ? Math.max(14, header.rect.height)
2686
+ : Math.max(14, header.rect.width);
2687
+ const band = bands.find((candidate) => Math.abs(candidate.center - center) <= tolerance);
2688
+ if (band) {
2689
+ band.headers.push(header);
2690
+ const centers = band.headers.map((entry) =>
2691
+ axis === 'column'
2692
+ ? entry.rect.top + entry.rect.height / 2
2693
+ : entry.rect.left + entry.rect.width / 2
2694
+ );
2695
+ band.center = centers.reduce((sum, value) => sum + value, 0) / centers.length;
2696
+ } else {
2697
+ bands.push({
2698
+ center,
2699
+ headers: [header],
2700
+ });
2701
+ }
2702
+ }
2703
+
2704
+ return bands
2705
+ .map((band) => ({
2706
+ center: band.center,
2707
+ headers:
2708
+ axis === 'column'
2709
+ ? [...band.headers].sort((left, right) => left.rect.left - right.rect.left)
2710
+ : [...band.headers].sort((left, right) => left.rect.top - right.rect.top),
2711
+ }))
2712
+ .sort((left, right) => left.center - right.center);
2713
+ };
2714
+
2489
2715
  const analyzeVisualSeatGridSurface = (surface) => {
2490
2716
  if (!isPotentialVisualGridSurface(surface)) {
2491
2717
  return null;
2492
2718
  }
2493
2719
 
2494
- const squareNodes = Array.from(surface.querySelectorAll('*')).filter((candidate) =>
2495
- isVisualGridSquareElement(candidate)
2720
+ const tokenNodes = Array.from(surface.querySelectorAll('*')).filter((candidate) =>
2721
+ isVisualGridTokenElement(candidate)
2496
2722
  );
2497
- if (squareNodes.length < 16) {
2723
+ if (tokenNodes.length < 16) {
2498
2724
  return null;
2499
2725
  }
2500
2726
 
@@ -2502,7 +2728,7 @@ async function collectDomTargetsFromDocument(context, options) {
2502
2728
  const columnHeaders = [];
2503
2729
  const seatCells = [];
2504
2730
 
2505
- for (const candidate of squareNodes) {
2731
+ for (const candidate of tokenNodes) {
2506
2732
  const rect = candidate.getBoundingClientRect();
2507
2733
  const tokenKind = visualSeatGridTokenKindOf(candidate);
2508
2734
  if (tokenKind === 'row') {
@@ -2533,13 +2759,14 @@ async function collectDomTargetsFromDocument(context, options) {
2533
2759
  return null;
2534
2760
  }
2535
2761
 
2536
- const topMostColumn = Math.min(...columnHeaders.map((header) => header.rect.top));
2537
- const topColumnHeaders = columnHeaders
2538
- .filter((header) => Math.abs(header.rect.top - topMostColumn) <= Math.max(14, header.rect.height))
2539
- .sort((left, right) => left.rect.left - right.rect.left);
2540
- if (topColumnHeaders.length < 4) {
2762
+ const columnBands = groupHeadersByBand(columnHeaders, 'column').filter(
2763
+ (band) => band.headers.length >= 4
2764
+ );
2765
+ if (columnBands.length === 0) {
2541
2766
  return null;
2542
2767
  }
2768
+ const topColumnHeaders = columnBands[0]?.headers ?? [];
2769
+ const bottomColumnHeaders = columnBands[columnBands.length - 1]?.headers ?? [];
2543
2770
 
2544
2771
  const ownerSurface = visualSeatGridOwnerSurfaceOf(surface);
2545
2772
  const descriptors = [];
@@ -2552,7 +2779,9 @@ async function collectDomTargetsFromDocument(context, options) {
2552
2779
  return Math.abs(headerCenterY - seatCenterY) <= Math.max(12, seatCell.rect.height);
2553
2780
  });
2554
2781
  const preferredRowHeaders = rowHeaderCandidates.filter(
2555
- (header) => header.rect.right <= seatCell.rect.left + 4
2782
+ (header) =>
2783
+ header.rect.right <= seatCell.rect.left + 4 ||
2784
+ header.rect.left >= seatCell.rect.right - 4
2556
2785
  );
2557
2786
  const rowHeader =
2558
2787
  chooseNearestHeader(
@@ -2560,21 +2789,38 @@ async function collectDomTargetsFromDocument(context, options) {
2560
2789
  seatCell.rect,
2561
2790
  'row'
2562
2791
  ) || undefined;
2563
- const columnHeaderCandidates = topColumnHeaders.filter(
2792
+ const topColumnHeaderCandidates = topColumnHeaders.filter(
2564
2793
  (header) => header.rect.bottom <= seatCell.rect.top + 12
2565
2794
  );
2566
- const columnHeader =
2567
- explicitSeatIdentity?.column ||
2568
- !topColumnHeaders.length
2569
- ? undefined
2570
- : chooseNearestHeader(
2571
- columnHeaderCandidates.length > 0 ? columnHeaderCandidates : topColumnHeaders,
2795
+ const bottomColumnHeaderCandidates = bottomColumnHeaders.filter(
2796
+ (header) => header.rect.top >= seatCell.rect.bottom - 12
2797
+ );
2798
+ const topColumnHeader =
2799
+ topColumnHeaders.length > 0
2800
+ ? chooseNearestHeader(
2801
+ topColumnHeaderCandidates.length > 0 ? topColumnHeaderCandidates : topColumnHeaders,
2802
+ seatCell.rect,
2803
+ 'column'
2804
+ )
2805
+ : undefined;
2806
+ const bottomColumnHeader =
2807
+ bottomColumnHeaders.length > 0
2808
+ ? chooseNearestHeader(
2809
+ bottomColumnHeaderCandidates.length > 0
2810
+ ? bottomColumnHeaderCandidates
2811
+ : bottomColumnHeaders,
2572
2812
  seatCell.rect,
2573
2813
  'column'
2574
- );
2814
+ )
2815
+ : undefined;
2816
+ const columnHeader =
2817
+ explicitSeatIdentity?.column ||
2818
+ topColumnHeader?.text ||
2819
+ bottomColumnHeader?.text ||
2820
+ undefined;
2575
2821
 
2576
2822
  const row = explicitSeatIdentity?.row || rowHeader?.text;
2577
- const column = explicitSeatIdentity?.column || columnHeader?.text;
2823
+ const column = explicitSeatIdentity?.column || columnHeader;
2578
2824
  if (!row || !column) {
2579
2825
  continue;
2580
2826
  }
@@ -2615,16 +2861,16 @@ async function collectDomTargetsFromDocument(context, options) {
2615
2861
  return acc;
2616
2862
  }
2617
2863
 
2618
- const squareNodes = Array.from(root.querySelectorAll('*')).filter((candidate) =>
2619
- isVisualGridSquareElement(candidate)
2864
+ const tokenNodes = Array.from(root.querySelectorAll('*')).filter((candidate) =>
2865
+ isVisualGridTokenElement(candidate)
2620
2866
  );
2621
- if (squareNodes.length < 16) {
2867
+ if (tokenNodes.length < 16) {
2622
2868
  return acc;
2623
2869
  }
2624
2870
 
2625
2871
  const candidateSurfaces = new Map();
2626
- for (const squareNode of squareNodes) {
2627
- let current = composedParentElement(squareNode);
2872
+ for (const tokenNode of tokenNodes) {
2873
+ let current = composedParentElement(tokenNode);
2628
2874
  let depth = 0;
2629
2875
  while (current && depth < 8) {
2630
2876
  if (isPotentialVisualGridSurface(current)) {
@@ -2748,13 +2994,13 @@ async function collectDomTargetsFromDocument(context, options) {
2748
2994
 
2749
2995
  const targets = elements.map((element, ordinal) => {
2750
2996
  const visualSeatGrid = visualSeatGridMeta.get(element);
2751
- const labelBackedChoice = labelBackedChoiceControlOf(element);
2997
+ const associatedChoiceControl = associatedChoiceControlOf(element);
2752
2998
  const genericClickable = isGenericClickableElement(element);
2753
2999
  const bareFocusableClickTarget = isBareFocusableClickTarget(element);
2754
3000
  const effectiveElement = element;
2755
3001
  const domSignature = domSignatureOf(effectiveElement);
2756
3002
  const genericCardLike =
2757
- !labelBackedChoice &&
3003
+ !associatedChoiceControl &&
2758
3004
  genericClickable &&
2759
3005
  (isStructuredContainer(element) ||
2760
3006
  /\b(card|item|result|fare|flight|ticket|offer|row)\b/.test(
@@ -2762,8 +3008,8 @@ async function collectDomTargetsFromDocument(context, options) {
2762
3008
  ));
2763
3009
  const inferredKind =
2764
3010
  visualSeatGrid?.kind ||
2765
- (labelBackedChoice
2766
- ? (labelBackedChoice.type || '').toLowerCase() === 'checkbox'
3011
+ (associatedChoiceControl
3012
+ ? (associatedChoiceControl.type || '').toLowerCase() === 'checkbox'
2767
3013
  ? 'checkbox'
2768
3014
  : 'radio'
2769
3015
  : genericCardLike
@@ -2777,7 +3023,9 @@ async function collectDomTargetsFromDocument(context, options) {
2777
3023
  const overlaySurface = composedClosest(element, overlaySurfaceSelector);
2778
3024
  const localSurface = localSurfaceCandidateOf(element);
2779
3025
  const selfSurface =
2780
- genericClickable && !labelBackedChoice && isStructuredContainer(element) ? element : undefined;
3026
+ genericClickable && !associatedChoiceControl && isStructuredContainer(element)
3027
+ ? element
3028
+ : undefined;
2781
3029
  const surface =
2782
3030
  visualSeatGrid?.surface ||
2783
3031
  (isHTMLElementNode(overlaySurface) ? overlaySurface : localSurface || selfSurface);
@@ -2790,7 +3038,7 @@ async function collectDomTargetsFromDocument(context, options) {
2790
3038
  );
2791
3039
  const fallbackLabel = directionalFallbackLabel || directFallbackLabel;
2792
3040
  const currentValue = popupCurrentValueOf(element);
2793
- const role = inferRole(element);
3041
+ const role = inferRole(element) || inferRole(associatedChoiceControl);
2794
3042
  const surfaceKind = visualSeatGrid?.surfaceKind || surfaceKindOf(surface);
2795
3043
  const fallbackSurfaceLabel =
2796
3044
  (visualSeatGrid?.hintText ? 'Seat map' : undefined) ||
@@ -2812,9 +3060,16 @@ async function collectDomTargetsFromDocument(context, options) {
2812
3060
  currentValue: currentValue || undefined,
2813
3061
  text: textOf(element),
2814
3062
  placeholder: element.getAttribute('placeholder')?.trim() || undefined,
2815
- inputName: element.getAttribute('name')?.trim() || undefined,
2816
- inputType: element.getAttribute('type')?.trim() || undefined,
3063
+ inputName:
3064
+ element.getAttribute('name')?.trim() ||
3065
+ associatedChoiceControl?.getAttribute('name')?.trim() ||
3066
+ undefined,
3067
+ inputType:
3068
+ element.getAttribute('type')?.trim() ||
3069
+ associatedChoiceControl?.getAttribute('type')?.trim() ||
3070
+ undefined,
2817
3071
  autocomplete: element.getAttribute('autocomplete')?.trim() || undefined,
3072
+ ariaAutocomplete: element.getAttribute('aria-autocomplete')?.trim() || undefined,
2818
3073
  validation: validationEvidenceOf(element),
2819
3074
  title: element.getAttribute('title')?.trim() || undefined,
2820
3075
  testId:
@@ -1 +1 @@
1
- {"version":3,"file":"observe-persistence.d.ts","sourceRoot":"","sources":["../../src/commands/observe-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AASnD,OAAO,KAAK,EAAoB,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAuF/B;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAC5C,OAAO,EAAE,gBAAgB,EAAE,GAC1B,IAAI,CAYN;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACzC,OAAO,CAAC,EAAE;IACR,gBAAgB,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;IACjE,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC1C,GACA;IACD,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,CAkEA;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,GAC5D,IAAI,CAsBN;AAUD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAC5C,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACjD,cAAc,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAChD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,iBAAiB,EAAE,CAyDrB"}
1
+ {"version":3,"file":"observe-persistence.d.ts","sourceRoot":"","sources":["../../src/commands/observe-persistence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AASnD,OAAO,KAAK,EAAoB,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACjG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAQhE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CA0F/B;AAED,wBAAgB,0BAA0B,CACxC,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAC5C,OAAO,EAAE,gBAAgB,EAAE,GAC1B,IAAI,CAYN;AAED,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACzC,OAAO,CAAC,EAAE;IACR,gBAAgB,CAAC,EAAE,aAAa,CAAC,IAAI,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC,CAAC;IACjE,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC1C,GACA;IACD,cAAc,EAAE,iBAAiB,EAAE,CAAC;IACpC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC,CAkEA;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,eAAe,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,GAC5D,IAAI,CAsBN;AAUD,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAC5C,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,CAAC,EACjD,cAAc,EAAE,aAAa,CAAC,iBAAiB,CAAC,EAChD,aAAa,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACzC,iBAAiB,EAAE,CAyDrB"}
@@ -58,6 +58,9 @@ export function toDomDescriptor(pageRef, target, surfaceRefMap) {
58
58
  inputName: target.inputName,
59
59
  inputType: target.inputType,
60
60
  autocomplete: target.autocomplete,
61
+ ariaAutocomplete: target.ariaAutocomplete,
62
+ surfaceKind: target.surfaceKind,
63
+ controlsSurfaceSelector: target.controlsSurfaceSelector,
61
64
  validation: target.validation,
62
65
  locatorCandidates,
63
66
  semantics: target.role || target.label || target.states
@@ -82,6 +82,7 @@ export declare function compactFillableForms(forms: ReadonlyArray<PersistedFilla
82
82
  fillRef: string;
83
83
  scopeRef?: string;
84
84
  purpose: string;
85
+ presence: 'present' | 'unknown';
85
86
  fields: Array<{
86
87
  fieldKey: string;
87
88
  targetRef: string;