@nuanu-ai/agentbrowse 0.2.19 → 0.2.20

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.
@@ -1 +1 @@
1
- {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/commands/act.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoCnD,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAqHxF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,CAAC;AAoV7B,wBAAsB,GAAG,CACvB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAioBf"}
1
+ {"version":3,"file":"act.d.ts","sourceRoot":"","sources":["../../src/commands/act.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoCnD,OAAO,EAAE,cAAc,EAAE,KAAK,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAqHxF,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,CAAC;AAoV7B,wBAAsB,GAAG,CACvB,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,YAAY,EACpB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAmqBf"}
@@ -531,6 +531,38 @@ export async function act(session, targetRef, action, value) {
531
531
  }
532
532
  }
533
533
  let acceptanceProbe = null;
534
+ const tryRecoverActionErrorAcceptance = async () => {
535
+ if (!acceptanceProbe) {
536
+ return false;
537
+ }
538
+ const acceptance = await waitForAcceptanceProbe(acceptanceProbe).catch(() => null);
539
+ if (acceptance?.polls && acceptance.polls > 1) {
540
+ attempts.push(`acceptance.polled:${acceptance.polls}`);
541
+ }
542
+ if (!acceptance?.accepted) {
543
+ return false;
544
+ }
545
+ if (acceptanceProbe.policy === 'submit') {
546
+ const submitResolution = await resolveSubmitResult(acceptanceProbe, acceptance.afterPageObservation);
547
+ if (!submitResolution.acceptAsProgress) {
548
+ return false;
549
+ }
550
+ attempts.push(`submit-resolution:${submitResolution.finalVerdict}`);
551
+ if (submitResolution.claims.some((claim) => claim.kind === 'soft_result_candidate')) {
552
+ attempts.push('submit-resolution:soft-result-candidate');
553
+ }
554
+ }
555
+ attempts.push(`acceptance.recovered:${acceptanceProbe.policy}`);
556
+ incrementMetric(session, 'fallbackActions');
557
+ resolvedBy = 'playwright-locator';
558
+ locatorStrategy = strategy;
559
+ progressProbe = null;
560
+ lastError = null;
561
+ recoveredAfterError = true;
562
+ recoveredAcceptancePolicy = acceptanceProbe.policy;
563
+ setTargetAvailability(session, targetRef, 'available');
564
+ return true;
565
+ };
534
566
  try {
535
567
  const valueProjection = await projectActionValue({
536
568
  target,
@@ -573,31 +605,26 @@ export async function act(session, targetRef, action, value) {
573
605
  (acceptanceProbe.policy === 'value-change' ||
574
606
  acceptanceProbe.policy === 'selection' ||
575
607
  acceptanceProbe.policy === 'date-selection' ||
576
- ((acceptanceProbe.policy === 'navigation' || acceptanceProbe.policy === 'submit') &&
577
- staleReason !== null &&
578
- staleReason !== 'page-signature-mismatch'));
579
- if (acceptanceProbe !== null && shouldAttemptAcceptanceRecovery) {
580
- const acceptance = await waitForAcceptanceProbe(acceptanceProbe).catch(() => null);
581
- if (acceptance?.polls && acceptance.polls > 1) {
582
- attempts.push(`acceptance.polled:${acceptance.polls}`);
583
- }
584
- if (acceptance?.accepted) {
585
- attempts.push(`acceptance.recovered:${acceptanceProbe.policy}`);
586
- incrementMetric(session, 'fallbackActions');
587
- resolvedBy = 'playwright-locator';
588
- locatorStrategy = strategy;
589
- progressProbe = null;
590
- lastError = null;
591
- recoveredAfterError = true;
592
- recoveredAcceptancePolicy = acceptanceProbe.policy;
593
- setTargetAvailability(session, targetRef, 'available');
594
- return true;
595
- }
608
+ acceptanceProbe.policy === 'navigation' ||
609
+ acceptanceProbe.policy === 'submit');
610
+ if (shouldAttemptAcceptanceRecovery && (await tryRecoverActionErrorAcceptance())) {
611
+ return true;
596
612
  }
597
613
  if (staleReason) {
598
614
  throw lastError;
599
615
  }
600
- await assertResolvedTargetStillValid(resolvedLocator, `after-error:${strategy}`);
616
+ try {
617
+ await assertResolvedTargetStillValid(resolvedLocator, `after-error:${strategy}`);
618
+ }
619
+ catch (validationError) {
620
+ if ((acceptanceProbe?.policy === 'navigation' || acceptanceProbe?.policy === 'submit') &&
621
+ validationError instanceof Error &&
622
+ validationError.message === 'stale_target_page_signature_changed' &&
623
+ (await tryRecoverActionErrorAcceptance())) {
624
+ return true;
625
+ }
626
+ throw validationError;
627
+ }
601
628
  return false;
602
629
  }
603
630
  };
@@ -1 +1 @@
1
- {"version":3,"file":"action-executor-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/action-executor-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAerD,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAC9C,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAkB7C,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWpE;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,CAAC,CAOjB;AA+FD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/E;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC;IACT,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC,CAgBD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GAAG,IAAI,EACjC,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAkBR;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAarF"}
1
+ {"version":3,"file":"action-executor-helpers.d.ts","sourceRoot":"","sources":["../../src/commands/action-executor-helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAerD,eAAO,MAAM,wBAAwB,OAAQ,CAAC;AAC9C,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAkB7C,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAWpE;AAED,wBAAsB,sBAAsB,CAC1C,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,OAAO,CAAC,CAqBlB;AAED,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAsCf;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,MAAM,CAAC,CAOjB;AA+FD,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/E;AAED,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC;IACT,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC;CACxB,CAAC,CAgBD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,aAAa,EAAE,MAAM,EACrB,kBAAkB,EAAE,MAAM,GAAG,IAAI,EACjC,QAAQ,EAAE,MAAM,EAAE,GACjB,MAAM,CAkBR;AAED,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAAE,GACjB,OAAO,CAAC,IAAI,CAAC,CAYf;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAarF"}
@@ -33,9 +33,14 @@ export async function dismissBlockingOverlay(page, attempts) {
33
33
  continue;
34
34
  }
35
35
  attempts.push(`overlay.dismiss:${selector}`);
36
- await candidate.click({ timeout: LOCATOR_CLICK_TIMEOUT_MS });
37
- attempts.push('overlay.dismissed');
38
- return true;
36
+ try {
37
+ await candidate.click({ timeout: LOCATOR_CLICK_TIMEOUT_MS });
38
+ attempts.push('overlay.dismissed');
39
+ return true;
40
+ }
41
+ catch {
42
+ continue;
43
+ }
39
44
  }
40
45
  return false;
41
46
  }
@@ -0,0 +1,3 @@
1
+ import type { Page } from 'playwright-core';
2
+ export declare function readScopedDialogText(page: Page, selector: string): Promise<string | null>;
3
+ //# sourceMappingURL=extract-scoped-dialog-text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extract-scoped-dialog-text.d.ts","sourceRoot":"","sources":["../../src/commands/extract-scoped-dialog-text.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAuM5C,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAyB/F"}
@@ -0,0 +1,213 @@
1
+ const BLOCK_MARKER = '[block]';
2
+ const ANCHOR_SELECTOR = [
3
+ 'button',
4
+ 'a[href]',
5
+ '[role="button"]',
6
+ '[role="link"]',
7
+ 'input[type="button"]',
8
+ 'input[type="submit"]',
9
+ 'input[type="reset"]',
10
+ ].join(', ');
11
+ // Build the browser callback from plain JS source so Playwright serializes
12
+ // stable code instead of tsx-transformed output.
13
+ const readScopedDialogTextInBrowser = Function(`return (${String.raw `(root, payload) => {
14
+ const marker = payload.marker;
15
+ const anchorSelector = payload.anchorSelector;
16
+ const minBlockTextLength = payload.minBlockTextLength;
17
+ const maxAnchorCountPerBlock = payload.maxAnchorCountPerBlock;
18
+
19
+ function normalizeOutputText(text) {
20
+ return text
21
+ .replace(/\r/g, '')
22
+ .split('\n')
23
+ .map((line) => line.trim())
24
+ .join('\n')
25
+ .replace(/\n{3,}/g, '\n\n')
26
+ .trim();
27
+ }
28
+
29
+ function normalizeBlockText(text) {
30
+ return normalizeOutputText(text).replace(/\n{2,}/g, '\n');
31
+ }
32
+
33
+ function isVisibleElement(element) {
34
+ if (!(element instanceof HTMLElement)) {
35
+ return false;
36
+ }
37
+
38
+ if (element.hidden || element.getAttribute('aria-hidden') === 'true') {
39
+ return false;
40
+ }
41
+
42
+ const style = window.getComputedStyle(element);
43
+ return style.display !== 'none' && style.visibility !== 'hidden';
44
+ }
45
+
46
+ function visibleChildren(element) {
47
+ return Array.from(element.children).filter((child) => isVisibleElement(child));
48
+ }
49
+
50
+ function collectVisibleAnchors(rootElement) {
51
+ return Array.from(rootElement.querySelectorAll(anchorSelector)).filter((anchor) =>
52
+ isVisibleElement(anchor)
53
+ );
54
+ }
55
+
56
+ function countAnchorsWithin(element, anchors) {
57
+ let count = 0;
58
+ for (const anchor of anchors) {
59
+ if (element.contains(anchor)) {
60
+ count += 1;
61
+ }
62
+ }
63
+ return count;
64
+ }
65
+
66
+ function pathFromRoot(rootElement, node) {
67
+ const path = [];
68
+ let current = node;
69
+
70
+ while (current && current !== rootElement) {
71
+ const parent = current.parentElement;
72
+ if (!(parent instanceof HTMLElement)) {
73
+ return null;
74
+ }
75
+
76
+ const index = Array.from(parent.children).indexOf(current);
77
+ if (index < 0) {
78
+ return null;
79
+ }
80
+
81
+ path.unshift(index);
82
+ current = parent;
83
+ }
84
+
85
+ return current === rootElement ? path : null;
86
+ }
87
+
88
+ function max(values) {
89
+ return values.reduce((current, value) => Math.max(current, value), 0);
90
+ }
91
+
92
+ function sum(values) {
93
+ return values.reduce((current, value) => current + value, 0);
94
+ }
95
+
96
+ if (!(root instanceof HTMLElement)) {
97
+ return null;
98
+ }
99
+
100
+ const rawText = normalizeOutputText(root.innerText);
101
+ if (!rawText) {
102
+ return null;
103
+ }
104
+
105
+ const anchors = collectVisibleAnchors(root);
106
+ if (anchors.length < 2) {
107
+ return rawText;
108
+ }
109
+
110
+ const candidates = [root, ...Array.from(root.querySelectorAll('*')).filter((element) => isVisibleElement(element))]
111
+ .map((element) => {
112
+ const children = visibleChildren(element);
113
+ if (children.length < 2) {
114
+ return null;
115
+ }
116
+
117
+ const tagName = children[0] && children[0].tagName;
118
+ if (!tagName || children.some((child) => child.tagName !== tagName)) {
119
+ return null;
120
+ }
121
+
122
+ const childSummaries = children.map((child) => {
123
+ const text = normalizeBlockText(child.innerText);
124
+ const anchorCount = countAnchorsWithin(child, anchors);
125
+ return {
126
+ text,
127
+ textLength: text.length,
128
+ anchorCount,
129
+ };
130
+ });
131
+
132
+ if (
133
+ childSummaries.some(
134
+ (summary) => summary.anchorCount < 1 || summary.anchorCount > maxAnchorCountPerBlock
135
+ )
136
+ ) {
137
+ return null;
138
+ }
139
+
140
+ const anchorCounts = childSummaries.map((summary) => summary.anchorCount);
141
+ if (max(anchorCounts) - Math.min(...anchorCounts) > 1) {
142
+ return null;
143
+ }
144
+
145
+ const textLengths = childSummaries.map((summary) => summary.textLength);
146
+ if (textLengths.some((length) => length < minBlockTextLength)) {
147
+ return null;
148
+ }
149
+
150
+ const parentPath = pathFromRoot(root, element);
151
+ if (!parentPath) {
152
+ return null;
153
+ }
154
+
155
+ return {
156
+ parentPath,
157
+ blockTexts: childSummaries.map((summary) => summary.text).filter(Boolean),
158
+ childCount: childSummaries.length,
159
+ totalTextLength: sum(textLengths),
160
+ depth: parentPath.length,
161
+ maxAnchorCount: max(anchorCounts),
162
+ };
163
+ })
164
+ .filter(Boolean);
165
+
166
+ const bestCandidate = candidates.sort((left, right) => {
167
+ if (right.childCount !== left.childCount) {
168
+ return right.childCount - left.childCount;
169
+ }
170
+ if (right.totalTextLength !== left.totalTextLength) {
171
+ return right.totalTextLength - left.totalTextLength;
172
+ }
173
+ if (right.maxAnchorCount !== left.maxAnchorCount) {
174
+ return right.maxAnchorCount - left.maxAnchorCount;
175
+ }
176
+ return right.depth - left.depth;
177
+ })[0];
178
+
179
+ if (!bestCandidate || bestCandidate.blockTexts.length < 2) {
180
+ return rawText;
181
+ }
182
+
183
+ return normalizeOutputText(
184
+ bestCandidate.blockTexts.map((text) => marker + '\n' + text).join('\n\n')
185
+ );
186
+ }`});`)();
187
+ export async function readScopedDialogText(page, selector) {
188
+ let rawText = null;
189
+ try {
190
+ rawText = (await page.locator(selector).first().innerText()).replace(/\r/g, '');
191
+ if (!rawText.trim()) {
192
+ return null;
193
+ }
194
+ }
195
+ catch {
196
+ return null;
197
+ }
198
+ try {
199
+ const result = await page
200
+ .locator(selector)
201
+ .first()
202
+ .evaluate(readScopedDialogTextInBrowser, {
203
+ marker: BLOCK_MARKER,
204
+ anchorSelector: ANCHOR_SELECTOR,
205
+ minBlockTextLength: 20,
206
+ maxAnchorCountPerBlock: 4,
207
+ });
208
+ return typeof result === 'string' && result.trim().length > 0 ? result : rawText;
209
+ }
210
+ catch {
211
+ return rawText;
212
+ }
213
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAyKnD,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAgLf"}
1
+ {"version":3,"file":"extract.d.ts","sourceRoot":"","sources":["../../src/commands/extract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AA8KnD,wBAAsB,OAAO,CAC3B,OAAO,EAAE,aAAa,EACtB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CAkMf"}
@@ -8,6 +8,7 @@ import { getSurface, getTarget, markSurfaceLifecycle, markTargetLifecycle, setCu
8
8
  import { outputContractFailure, outputJSON } from '../output.js';
9
9
  import { connectPlaywright, disconnectPlaywright, resolvePageByRef as resolvePlaywrightPageByRef, syncSessionPage, } from '../playwright-runtime.js';
10
10
  import { normalizePageSignature } from './descriptor-validation.js';
11
+ import { readScopedDialogText } from './extract-scoped-dialog-text.js';
11
12
  import { resolveScopedExtractContext } from './extract-scope-resolution.js';
12
13
  import { executeStagehandExtract } from './extract-stagehand-executor.js';
13
14
  function buildSchemaValue(descriptor) {
@@ -133,6 +134,9 @@ function buildTruncationReason(error) {
133
134
  ? `Structured output was truncated by the LLM provider (${details.join(', ')}).`
134
135
  : 'Structured output was truncated by the LLM provider.';
135
136
  }
137
+ function schemaRequestsScopedDialogText(schemaDescriptor) {
138
+ return schemaDescriptor.dialog_text === 'string';
139
+ }
136
140
  export async function extract(session, schemaJson, scopeRef) {
137
141
  let schemaDescriptor;
138
142
  try {
@@ -239,10 +243,26 @@ export async function extract(session, schemaJson, scopeRef) {
239
243
  ? scopedResolution.degradationReason
240
244
  : undefined,
241
245
  });
246
+ let data = execution.data;
247
+ if (scopeTarget &&
248
+ effectiveSelector &&
249
+ schemaRequestsScopedDialogText(schemaDescriptor) &&
250
+ data &&
251
+ typeof data === 'object' &&
252
+ !Array.isArray(data)) {
253
+ const dialogText = await readScopedDialogText(page, effectiveSelector);
254
+ if (typeof dialogText === 'string' && dialogText.trim().length > 0) {
255
+ data = {
256
+ ...data,
257
+ dialog_text: dialogText,
258
+ };
259
+ }
260
+ }
242
261
  saveSession(session);
243
262
  outputJSON({
244
263
  success: true,
245
264
  ...execution,
265
+ data,
246
266
  pageRef,
247
267
  scopeRef,
248
268
  metrics: session.runtime?.metrics,
@@ -1 +1 @@
1
- {"version":3,"file":"observe-inventory.d.ts","sourceRoot":"","sources":["../../src/commands/observe-inventory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observe-inventory.d.ts","sourceRoot":"","sources":["../../src/commands/observe-inventory.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { inferAcceptancePolicyFromFacts, inferAllowedActionsFromFacts, inferAvailabilityFromFacts, inferControlFamilyFromFacts, } from '../control-semantics.js';
2
2
  import { LOCATOR_DOM_SIGNATURE_SCRIPT, normalizePageSignature, readLocatorDomSignature, } from './descriptor-validation.js';
3
3
  import { TRANSPARENT_ACTIONABLE_CONTROL_HELPER_SCRIPT } from './user-actionable.js';
4
- const DOM_TARGET_COLLECTION_LIMIT = 320;
4
+ const DOM_TARGET_COLLECTION_LIMIT = 640;
5
+ const DOM_TARGET_OUTPUT_LIMIT = 480;
5
6
  const DOM_SIGNAL_COLLECTION_LIMIT = 24;
6
7
  export function inferStructuredCellVariantFromEvidence(evidence) {
7
8
  const role = (evidence.role ?? '').toLowerCase();
@@ -325,7 +326,7 @@ async function collectDomTargetsFromDocument(context, options) {
325
326
  'li, tr, td, article, [role="option"], [role="listitem"], [role="row"], [role="gridcell"], [role="tab"], [role="menuitem"], [role="radio"]';
326
327
  const headingSelector = 'h1, h2, h3, h4, h5, h6, [role="heading"], legend';
327
328
  const collectorElementLimit = ${DOM_TARGET_COLLECTION_LIMIT};
328
- const collectorOutputLimit = 180;
329
+ const collectorOutputLimit = ${DOM_TARGET_OUTPUT_LIMIT};
329
330
 
330
331
  const cssEscape = (value) =>
331
332
  typeof CSS !== 'undefined' && typeof CSS.escape === 'function'
@@ -405,6 +406,174 @@ async function collectDomTargetsFromDocument(context, options) {
405
406
 
406
407
  return undefined;
407
408
  };
409
+ ${TRANSPARENT_ACTIONABLE_CONTROL_HELPER_SCRIPT}
410
+ ${INFER_STRUCTURED_CELL_VARIANT_HELPER_SCRIPT}
411
+
412
+ const normalizeDescriptorText = (value) => (value || '').replace(/\s+/g, ' ').trim();
413
+
414
+ const isVisible = (element) => {
415
+ const style = window.getComputedStyle(element);
416
+ if (
417
+ style.display === 'none' ||
418
+ style.visibility === 'hidden' ||
419
+ style.visibility === 'collapse'
420
+ ) {
421
+ return false;
422
+ }
423
+ const rect = element.getBoundingClientRect();
424
+ if (rect.width <= 0 || rect.height <= 0) {
425
+ return false;
426
+ }
427
+ if (style.opacity === '0') {
428
+ return isTransparentActionableControl(element);
429
+ }
430
+ return true;
431
+ };
432
+
433
+ const compactDateCellLabelRe =
434
+ /^(?:\d{1,2}|january|february|march|april|may|june|july|august|september|october|november|december|январ|феврал|март|апрел|ма[йя]|июн|июл|август|сентябр|октябр|ноябр|декабр)$/i;
435
+
436
+ const rawDescriptorLabelOf = (element) => {
437
+ if (!isHTMLElementNode(element)) {
438
+ return '';
439
+ }
440
+
441
+ return normalizeDescriptorText(
442
+ element.getAttribute('aria-label') ||
443
+ element.getAttribute('title') ||
444
+ element.innerText ||
445
+ element.textContent ||
446
+ ''
447
+ );
448
+ };
449
+
450
+ const compactDateTokenOf = (element) => {
451
+ if (!isHTMLElementNode(element)) {
452
+ return '';
453
+ }
454
+
455
+ const descriptorValues = [rawDescriptorLabelOf(element)].concat(
456
+ Array.from(element.querySelectorAll('[aria-label]'))
457
+ .slice(0, 6)
458
+ .map((candidate) => normalizeDescriptorText(candidate.getAttribute('aria-label')))
459
+ );
460
+
461
+ for (const descriptorValue of descriptorValues) {
462
+ if (!descriptorValue) {
463
+ continue;
464
+ }
465
+
466
+ const monthMatch = descriptorValue.match(
467
+ /\b(january|february|march|april|may|june|july|august|september|october|november|december)\b/i
468
+ );
469
+ if (monthMatch) {
470
+ return monthMatch[1].toLowerCase();
471
+ }
472
+
473
+ const dayMatch = descriptorValue.match(/\b(\d{1,2})\b/);
474
+ if (dayMatch) {
475
+ return dayMatch[1];
476
+ }
477
+ }
478
+
479
+ return '';
480
+ };
481
+
482
+ const isDatepickerLikeContext = (parentGridCell, element) => {
483
+ const contextNodes = [
484
+ parentGridCell,
485
+ element,
486
+ composedClosest(parentGridCell, '[role="dialog"]'),
487
+ composedClosest(parentGridCell, '[role="grid"]'),
488
+ ];
489
+
490
+ return contextNodes.some((candidate) => {
491
+ if (!isHTMLElementNode(candidate)) {
492
+ return false;
493
+ }
494
+
495
+ if (
496
+ candidate.hasAttribute('data-day') ||
497
+ candidate.hasAttribute('data-date') ||
498
+ candidate.hasAttribute('data-iso')
499
+ ) {
500
+ return true;
501
+ }
502
+
503
+ const semanticBlob = normalizeDescriptorText(
504
+ [
505
+ candidate.getAttribute('role'),
506
+ candidate.getAttribute('aria-label'),
507
+ candidate.getAttribute('aria-roledescription'),
508
+ candidate.getAttribute('data-testid'),
509
+ candidate.getAttribute('id'),
510
+ candidate.getAttribute('class'),
511
+ candidate.getAttribute('data-iso'),
512
+ ]
513
+ .filter(Boolean)
514
+ .join(' ')
515
+ ).toLowerCase();
516
+
517
+ if (
518
+ /\b(date|calendar|month|departure|return|departing|arriving|outbound|inbound)\b/.test(
519
+ semanticBlob
520
+ ) ||
521
+ /\b(january|february|march|april|may|june|july|august|september|october|november|december)\b/.test(
522
+ semanticBlob
523
+ ) ||
524
+ /\b\d{4}-\d{2}-\d{2}\b/.test(semanticBlob)
525
+ ) {
526
+ return true;
527
+ }
528
+
529
+ const descendantAria = normalizeDescriptorText(
530
+ Array.from(candidate.querySelectorAll('[aria-label]'))
531
+ .slice(0, 6)
532
+ .map((child) => child.getAttribute('aria-label') || '')
533
+ .join(' ')
534
+ ).toLowerCase();
535
+
536
+ return (
537
+ /\b(date|calendar|month|departure|return|departing|arriving|outbound|inbound)\b/.test(
538
+ descendantAria
539
+ ) ||
540
+ /\b(january|february|march|april|may|june|july|august|september|october|november|december)\b/.test(
541
+ descendantAria
542
+ )
543
+ );
544
+ });
545
+ };
546
+
547
+ const isDuplicateDatepickerButtonCandidate = (element) => {
548
+ if (!isHTMLElementNode(element)) {
549
+ return false;
550
+ }
551
+
552
+ if ((element.getAttribute('role') || '').toLowerCase() !== 'button') {
553
+ return false;
554
+ }
555
+
556
+ const parentGridCell = composedParentElement(element);
557
+ if (
558
+ !isHTMLElementNode(parentGridCell) ||
559
+ (parentGridCell.getAttribute('role') || '').toLowerCase() !== 'gridcell'
560
+ ) {
561
+ return false;
562
+ }
563
+
564
+ const elementDateToken = compactDateTokenOf(element);
565
+ const parentDateToken = compactDateTokenOf(parentGridCell);
566
+ if (!elementDateToken || elementDateToken !== parentDateToken) {
567
+ return false;
568
+ }
569
+
570
+ if (!compactDateCellLabelRe.test(elementDateToken)) {
571
+ return false;
572
+ }
573
+
574
+ return isDatepickerLikeContext(parentGridCell, element);
575
+ };
576
+
408
577
  const collectInteractiveElements = (
409
578
  root,
410
579
  limit = collectorElementLimit,
@@ -423,6 +592,8 @@ async function collectDomTargetsFromDocument(context, options) {
423
592
  for (const candidate of matches) {
424
593
  if (acc.length >= limit) break;
425
594
  if (!isHTMLElementNode(candidate) || seen.has(candidate)) continue;
595
+ if (!isVisible(candidate)) continue;
596
+ if (isDuplicateDatepickerButtonCandidate(candidate)) continue;
426
597
  seen.add(candidate);
427
598
  acc.push(candidate);
428
599
  }
@@ -437,30 +608,6 @@ async function collectDomTargetsFromDocument(context, options) {
437
608
  return acc;
438
609
  };
439
610
 
440
- ${TRANSPARENT_ACTIONABLE_CONTROL_HELPER_SCRIPT}
441
- ${INFER_STRUCTURED_CELL_VARIANT_HELPER_SCRIPT}
442
-
443
- const isVisible = (element) => {
444
- const style = window.getComputedStyle(element);
445
- if (
446
- style.display === 'none' ||
447
- style.visibility === 'hidden' ||
448
- style.visibility === 'collapse'
449
- ) {
450
- return false;
451
- }
452
- const rect = element.getBoundingClientRect();
453
- if (rect.width <= 0 || rect.height <= 0) {
454
- return false;
455
- }
456
- if (style.opacity === '0') {
457
- return isTransparentActionableControl(element);
458
- }
459
- return true;
460
- };
461
-
462
- const normalizeDescriptorText = (value) => (value || '').replace(/\s+/g, ' ').trim();
463
-
464
611
  const imageAltTextOf = (element) => {
465
612
  if (!isHTMLElementNode(element)) return undefined;
466
613
 
@@ -489,7 +636,69 @@ async function collectDomTargetsFromDocument(context, options) {
489
636
  return values.length > 0 ? values.join(' ') : undefined;
490
637
  };
491
638
 
492
- const textOf = (element) => {
639
+ const MACHINE_DESCRIPTOR_TEXT_RE =
640
+ /(?:window\.[a-z0-9_$]+|apiary(?:sleepingqueue|markerportal)|document\.getelementbyid\(|addeventlistener\(|push\(\[|["']widgets["']\s*:|["']meta["']\s*:)/i;
641
+
642
+ const looksLikeMachineDescriptorText = (value) => {
643
+ const normalized = normalizeDescriptorText(value || '');
644
+ if (!normalized) {
645
+ return false;
646
+ }
647
+
648
+ if (MACHINE_DESCRIPTOR_TEXT_RE.test(normalized)) {
649
+ return true;
650
+ }
651
+
652
+ if (normalized.length < 160) {
653
+ return false;
654
+ }
655
+
656
+ const syntaxCount =
657
+ (normalized.match(/[{}[\]();=]/g) || []).length +
658
+ (normalized.match(/["']/g) || []).length;
659
+ return syntaxCount >= 24 && syntaxCount / normalized.length >= 0.08;
660
+ };
661
+
662
+ const safeVisibleDescriptorTextOf = (element) => {
663
+ const text = normalizeDescriptorText(element?.innerText || '');
664
+ if (!text || looksLikeMachineDescriptorText(text)) {
665
+ return undefined;
666
+ }
667
+ return text;
668
+ };
669
+
670
+ const directVisibleChildDescriptorTextOf = (element) => {
671
+ if (!isHTMLElementNode(element)) {
672
+ return undefined;
673
+ }
674
+
675
+ const values = [];
676
+ const seen = new Set();
677
+ const pushValue = (value) => {
678
+ const normalized = normalizeDescriptorText(value || '');
679
+ if (!normalized || looksLikeMachineDescriptorText(normalized) || seen.has(normalized)) {
680
+ return;
681
+ }
682
+ seen.add(normalized);
683
+ values.push(normalized);
684
+ };
685
+
686
+ for (const child of Array.from(element.children).slice(0, 6)) {
687
+ if (!isHTMLElementNode(child) || !isVisible(child)) {
688
+ continue;
689
+ }
690
+ pushValue(child.innerText || '');
691
+ pushValue(imageAltTextOf(child));
692
+ if (values.join(' ').length >= 160) {
693
+ break;
694
+ }
695
+ }
696
+
697
+ return values.length > 0 ? values.join(' ') : undefined;
698
+ };
699
+
700
+ const textOf = (element, options = {}) => {
701
+ const container = options?.container === true;
493
702
  const tag = element?.tagName?.toLowerCase?.();
494
703
  if (tag && ['script', 'style', 'noscript', 'template'].includes(tag)) {
495
704
  return undefined;
@@ -502,8 +711,20 @@ async function collectDomTargetsFromDocument(context, options) {
502
711
  if (buttonLikeText) {
503
712
  return buttonLikeText;
504
713
  }
505
- const textValue = normalizeDescriptorText(element?.innerText || element?.textContent || '');
506
714
  const altValue = imageAltTextOf(element);
715
+ const visibleText = safeVisibleDescriptorTextOf(element);
716
+ const childText = container ? directVisibleChildDescriptorTextOf(element) : undefined;
717
+ const rawTextContent = normalizeDescriptorText(element?.textContent || '');
718
+ const textContentFallback =
719
+ !container &&
720
+ rawTextContent &&
721
+ rawTextContent !== visibleText &&
722
+ rawTextContent !== childText &&
723
+ !looksLikeMachineDescriptorText(rawTextContent)
724
+ ? rawTextContent
725
+ : undefined;
726
+ const textValue = visibleText || childText || textContentFallback;
727
+
507
728
  if (!textValue && !altValue) {
508
729
  return undefined;
509
730
  }
@@ -1088,7 +1309,7 @@ async function collectDomTargetsFromDocument(context, options) {
1088
1309
  const headingText = textOf(heading);
1089
1310
  if (headingText) return headingText;
1090
1311
 
1091
- const text = textOf(container);
1312
+ const text = textOf(container, { container: true });
1092
1313
  if (text && text.length <= 140) return text;
1093
1314
  if (text) return text.slice(0, 140);
1094
1315
  return undefined;
@@ -1106,7 +1327,7 @@ async function collectDomTargetsFromDocument(context, options) {
1106
1327
  return true;
1107
1328
  }
1108
1329
 
1109
- const text = textOf(element);
1330
+ const text = textOf(element, { container: true });
1110
1331
  if (!text) return false;
1111
1332
 
1112
1333
  const interactiveCount = element.querySelectorAll(selector).length;
@@ -1238,7 +1459,7 @@ async function collectDomTargetsFromDocument(context, options) {
1238
1459
  };
1239
1460
 
1240
1461
  const containerTextOf = (container) => {
1241
- const text = textOf(container);
1462
+ const text = textOf(container, { container: true });
1242
1463
  if (!text) return undefined;
1243
1464
  return text.length <= 240 ? text : text.slice(0, 240);
1244
1465
  };
@@ -1257,7 +1478,7 @@ async function collectDomTargetsFromDocument(context, options) {
1257
1478
  let depth = 0;
1258
1479
 
1259
1480
  while (current && depth < 5) {
1260
- const currentText = textOf(current);
1481
+ const currentText = textOf(current, { container: true });
1261
1482
  if (currentText && currentText !== selfText) {
1262
1483
  const interactiveCount = current.querySelectorAll(selector).length;
1263
1484
  const hasSiblingText = Array.from(current.children).some((child) => {
@@ -1290,10 +1511,10 @@ async function collectDomTargetsFromDocument(context, options) {
1290
1511
  }
1291
1512
 
1292
1513
  if (element.matches?.(itemSelector)) {
1293
- const ancestorItem = composedClosest(composedParentElement(element), itemSelector);
1514
+ const ancestorItem = composedClosest(composedParentElement(element), itemSelector);
1294
1515
  if (ancestorItem) {
1295
1516
  const selfText = textOf(element);
1296
- const ancestorText = textOf(ancestorItem);
1517
+ const ancestorText = textOf(ancestorItem, { container: true });
1297
1518
  if (
1298
1519
  ancestorText &&
1299
1520
  ancestorText !== selfText &&
@@ -1347,7 +1568,7 @@ async function collectDomTargetsFromDocument(context, options) {
1347
1568
  }
1348
1569
 
1349
1570
  pushCandidate(candidates, landmarkLabelOf(node));
1350
- pushCandidate(candidates, textOf(node));
1571
+ pushCandidate(candidates, textOf(node, { container: true }));
1351
1572
  };
1352
1573
 
1353
1574
  const anchors = [
@@ -1424,7 +1645,7 @@ async function collectDomTargetsFromDocument(context, options) {
1424
1645
  if (candidate.querySelector(validationFieldSelectors)) {
1425
1646
  continue;
1426
1647
  }
1427
- pushMessage(candidate.textContent);
1648
+ pushMessage(textOf(candidate, { container: true }));
1428
1649
  }
1429
1650
  }
1430
1651
 
@@ -1 +1 @@
1
- {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/commands/observe.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoDnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAU/D,eAAO,MAAM,yBAAyB;;;;iBA+R4zG,CAAC;gBAAwB,CAAC;;;;;iBAAw24E,CAAC;gBAAwB,CAAC;;;;CA/Rzr/E,CAAC;AACtE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGrC,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwRzF"}
1
+ {"version":3,"file":"observe.d.ts","sourceRoot":"","sources":["../../src/commands/observe.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAoDnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAU/D,eAAO,MAAM,yBAAyB;;;;iBA+Ri2G,CAAC;gBAAwB,CAAC;;;;;iBAAg1mF,CAAC;gBAAwB,CAAC;;;;CA/RtstF,CAAC;AACtE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGrC,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwRzF"}
@@ -1 +1 @@
1
- {"version":3,"file":"observe.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/observe.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AA0EvC,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,2BAA2B,EAAE,MAA0C,CAAC;AACrF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,EAAE,OAAO,EAAgC,CAAC;AA+B5E,eAAO,MAAQ,OAAO,yCAAE,yBAAyB;;;;iBAqEqiT,CAAC;gBAAwB,CAAC;;;;;iBAAw24E,CAAC;gBAAwB,CAAC;;;;GArE/7rF,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAE3E,CAAC;AACF,eAAO,MAAQ,0BAA0B;;;;;CAA+C,CAAC;AAMzF,wBAAgB,WAAW,IAAI,aAAa,CAW3C;AAYD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,IAAI,EAAE,CAAC,EACP,YAAY,SAAkC,GAC7C,CAAC,GAAG;IAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;CAAE,CAM3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAyB9C"}
1
+ {"version":3,"file":"observe.test-harness.d.ts","sourceRoot":"","sources":["../../src/commands/observe.test-harness.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,EAAE,EAAE,MAAM,QAAQ,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAGnD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;AA0EvC,eAAO,MAAM,kBAAkB,EAAE,MAAiC,CAAC;AACnE,eAAO,MAAM,oBAAoB,EAAE,MAAmC,CAAC;AACvE,eAAO,MAAM,yBAAyB,EAAE,MAAwC,CAAC;AACjF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,iBAAiB,EAAE,MAAgC,CAAC;AACjE,eAAO,MAAM,cAAc,EAAE,MAA6B,CAAC;AAC3D,eAAO,MAAM,2BAA2B,EAAE,MAA0C,CAAC;AACrF,eAAO,MAAM,eAAe,EAAE,MAA8B,CAAC;AAC7D,eAAO,MAAM,qBAAqB,EAAE,OAAO,EAAgC,CAAC;AA+B5E,eAAO,MAAQ,OAAO,yCAAE,yBAAyB;;;;iBAqE0kT,CAAC;gBAAwB,CAAC;;;;;iBAAg1mF,CAAC;gBAAwB,CAAC;;;;GArE585F,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAE3E,CAAC;AACF,eAAO,MAAQ,0BAA0B;;;;;CAA+C,CAAC;AAMzF,wBAAgB,WAAW,IAAI,aAAa,CAW3C;AAYD,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACpE,IAAI,EAAE,CAAC,EACP,YAAY,SAAkC,GAC7C,CAAC,GAAG;IAAE,OAAO,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAA;CAAE,CAM3C;AAED,wBAAgB,uBAAuB,IAAI,IAAI,CAyB9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"control-semantics.d.ts","sourceRoot":"","sources":["../src/control-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAyCtF,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,oBAAoB,GAC1B,mBAAmB,GAAG,SAAS,CA2CjC;AAsCD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAYxE;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,oBAAoB,GAC1B,mBAAmB,EAAE,CAiFvB;AAED,wBAAgB,0BAA0B,CACxC,MAAM,CAAC,EAAE,gBAAgB,EACzB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B,GACL,uBAAuB,CAyBzB;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,mBAAmB,GAAG,SAAS,CA0EjC;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,sBAAsB,GAAG,SAAS,CAqDpC"}
1
+ {"version":3,"file":"control-semantics.d.ts","sourceRoot":"","sources":["../src/control-semantics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,sBAAsB,EACtB,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EAChB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;AAyCtF,wBAAgB,iCAAiC,CAC/C,KAAK,EAAE,oBAAoB,GAC1B,mBAAmB,GAAG,SAAS,CA2CjC;AAsCD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAYxE;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,oBAAoB,GAC1B,mBAAmB,EAAE,CA6FvB;AAED,wBAAgB,0BAA0B,CACxC,MAAM,CAAC,EAAE,gBAAgB,EACzB,WAAW,CAAC,EAAE,MAAM,EACpB,OAAO,GAAE;IACP,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC1B,GACL,uBAAuB,CAyBzB;AAED,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,mBAAmB,GAAG,SAAS,CA0EjC;AAED,wBAAgB,8BAA8B,CAC5C,KAAK,EAAE,oBAAoB,EAC3B,cAAc,EAAE,aAAa,CAAC,mBAAmB,CAAC,GACjD,sBAAsB,GAAG,SAAS,CAqDpC"}
@@ -105,6 +105,12 @@ export function inferAllowedActionsFromFacts(facts) {
105
105
  const legacyMethod = normalizeText(facts.legacyMethod);
106
106
  const selectLikePopupOwner = isSelectLikePopupOwner(facts);
107
107
  const buttonLikeInput = isButtonLikeInputFacts(facts);
108
+ const checkedToggle = facts.states?.checked !== undefined ||
109
+ kind === 'checkbox' ||
110
+ kind === 'radio' ||
111
+ role === 'checkbox' ||
112
+ role === 'radio' ||
113
+ role === 'switch';
108
114
  const actions = new Set();
109
115
  if (selectLikePopupOwner) {
110
116
  actions.add('click');
@@ -136,6 +142,10 @@ export function inferAllowedActionsFromFacts(facts) {
136
142
  if (kind === 'option' || role === 'option' || role === 'menuitem') {
137
143
  actions.add('click');
138
144
  }
145
+ if (checkedToggle) {
146
+ actions.add('click');
147
+ actions.add('press');
148
+ }
139
149
  if (role === 'gridcell' || facts.structure?.family === 'structured-grid') {
140
150
  actions.add('click');
141
151
  actions.add('press');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuanu-ai/agentbrowse",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
4
4
  "type": "module",
5
5
  "description": "Browser automation CLI for AI agents: control a CDP browser, observe UI surfaces, act on refs, extract data, and solve captchas",
6
6
  "keywords": [