@nuanu-ai/agentbrowse 0.2.12 → 0.2.14

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 (69) hide show
  1. package/README.md +5 -0
  2. package/dist/agentpay-stagehand-llm.d.ts +16 -0
  3. package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
  4. package/dist/agentpay-stagehand-llm.js +35 -10
  5. package/dist/commands/act.d.ts.map +1 -1
  6. package/dist/commands/act.js +16 -15
  7. package/dist/commands/action-acceptance.d.ts +1 -0
  8. package/dist/commands/action-acceptance.d.ts.map +1 -1
  9. package/dist/commands/action-acceptance.js +77 -1
  10. package/dist/commands/extract-snapshot-sanitizer.d.ts +2 -0
  11. package/dist/commands/extract-snapshot-sanitizer.d.ts.map +1 -0
  12. package/dist/commands/extract-snapshot-sanitizer.js +65 -0
  13. package/dist/commands/extract-stagehand-executor.d.ts.map +1 -1
  14. package/dist/commands/extract-stagehand-executor.js +33 -3
  15. package/dist/commands/extract.d.ts.map +1 -1
  16. package/dist/commands/extract.js +29 -0
  17. package/dist/commands/launch.js +0 -7
  18. package/dist/commands/observe-inventory.d.ts.map +1 -1
  19. package/dist/commands/observe-inventory.js +43 -0
  20. package/dist/commands/observe-persistence.d.ts +1 -0
  21. package/dist/commands/observe-persistence.d.ts.map +1 -1
  22. package/dist/commands/observe-persistence.js +52 -1
  23. package/dist/commands/observe-projection.d.ts +28 -5
  24. package/dist/commands/observe-projection.d.ts.map +1 -1
  25. package/dist/commands/observe-projection.js +189 -9
  26. package/dist/commands/observe-semantics.d.ts.map +1 -1
  27. package/dist/commands/observe-semantics.js +13 -2
  28. package/dist/commands/observe-surfaces.d.ts +1 -0
  29. package/dist/commands/observe-surfaces.d.ts.map +1 -1
  30. package/dist/commands/observe-surfaces.js +65 -0
  31. package/dist/commands/observe.d.ts.map +1 -1
  32. package/dist/commands/observe.js +49 -19
  33. package/dist/commands/observe.test-harness.d.ts +1 -0
  34. package/dist/commands/observe.test-harness.d.ts.map +1 -1
  35. package/dist/commands/observe.test-harness.js +53 -16
  36. package/dist/commands/semantic-observe.d.ts +2 -0
  37. package/dist/commands/semantic-observe.d.ts.map +1 -1
  38. package/dist/commands/semantic-observe.js +4 -0
  39. package/dist/playwright-runtime.d.ts +3 -1
  40. package/dist/playwright-runtime.d.ts.map +1 -1
  41. package/dist/playwright-runtime.js +42 -2
  42. package/dist/runtime-state.d.ts +3 -0
  43. package/dist/runtime-state.d.ts.map +1 -1
  44. package/dist/runtime-state.js +2 -0
  45. package/dist/secrets/fill-ordering.d.ts +1 -2
  46. package/dist/secrets/fill-ordering.d.ts.map +1 -1
  47. package/dist/secrets/fill-ordering.js +0 -3
  48. package/dist/secrets/form-matcher.d.ts.map +1 -1
  49. package/dist/secrets/form-matcher.js +0 -9
  50. package/dist/secrets/types.d.ts +0 -9
  51. package/dist/secrets/types.d.ts.map +1 -1
  52. package/dist/solver/browser-launcher.d.ts.map +1 -1
  53. package/dist/solver/browser-launcher.js +492 -55
  54. package/dist/solver/captcha-detector.d.ts.map +1 -1
  55. package/dist/solver/captcha-detector.js +187 -12
  56. package/dist/solver/captcha-runtime.d.ts.map +1 -1
  57. package/dist/solver/captcha-runtime.js +8 -0
  58. package/dist/solver/captcha-solver.d.ts +11 -1
  59. package/dist/solver/captcha-solver.d.ts.map +1 -1
  60. package/dist/solver/captcha-solver.js +11 -4
  61. package/dist/solver/turnstile-challenge.d.ts +3 -0
  62. package/dist/solver/turnstile-challenge.d.ts.map +1 -0
  63. package/dist/solver/turnstile-challenge.js +173 -0
  64. package/dist/solver/types.d.ts +10 -8
  65. package/dist/solver/types.d.ts.map +1 -1
  66. package/package.json +1 -1
  67. package/dist/secrets/request-guidance.d.ts +0 -24
  68. package/dist/secrets/request-guidance.d.ts.map +0 -1
  69. package/dist/secrets/request-guidance.js +0 -142
@@ -1,5 +1,5 @@
1
1
  import { ensureRuntimeState, markSurfaceLifecycle, markTargetLifecycle, replaceSurfacesForPage, setSurfaceAvailability, setTargetAvailability, } from '../runtime-state.js';
2
- import { collectSurfaceDescriptors, pushUniqueLocatorCandidate, surfaceReplacementKey } from './observe-surfaces.js';
2
+ import { buildSyntheticFormSurfaceId, collectSurfaceDescriptors, pushUniqueLocatorCandidate, surfaceReplacementKey, } from './observe-surfaces.js';
3
3
  export function toDomDescriptor(pageRef, target, surfaceRefMap) {
4
4
  const locatorCandidates = [];
5
5
  if (target.role && target.label) {
@@ -168,3 +168,54 @@ export function reconcileObservedTargetsForPage(session, pageRef, observedTarget
168
168
  setTargetAvailability(session, target.ref, 'hidden', 'target-not-observed');
169
169
  }
170
170
  }
171
+ function pushUniqueRef(map, key, ref) {
172
+ const refs = map.get(key) ?? [];
173
+ if (!refs.includes(ref)) {
174
+ refs.push(ref);
175
+ map.set(key, refs);
176
+ }
177
+ }
178
+ export function linkObservedSurfaceGraph(session, pageRef, domTargets, persistedTargets, observedScopes, surfaceRefMap) {
179
+ const runtime = ensureRuntimeState(session);
180
+ const activeSurfaceRefs = new Set(observedScopes.map((scope) => scope.ref));
181
+ const targetRefsBySurface = new Map();
182
+ const parentBySurface = new Map();
183
+ const childRefsByParent = new Map();
184
+ for (const [index, persistedTarget] of persistedTargets.entries()) {
185
+ if (persistedTarget.pageRef !== pageRef) {
186
+ continue;
187
+ }
188
+ if (persistedTarget.surfaceRef) {
189
+ pushUniqueRef(targetRefsBySurface, persistedTarget.surfaceRef, persistedTarget.ref);
190
+ }
191
+ const domTarget = domTargets[index];
192
+ if (!domTarget) {
193
+ continue;
194
+ }
195
+ const syntheticFormSurfaceId = buildSyntheticFormSurfaceId(domTarget);
196
+ const formSurfaceRef = syntheticFormSurfaceId
197
+ ? surfaceRefMap.get(syntheticFormSurfaceId)
198
+ : undefined;
199
+ if (!formSurfaceRef || !persistedTarget.surfaceRef || persistedTarget.surfaceRef === formSurfaceRef) {
200
+ continue;
201
+ }
202
+ parentBySurface.set(persistedTarget.surfaceRef, formSurfaceRef);
203
+ pushUniqueRef(childRefsByParent, formSurfaceRef, persistedTarget.surfaceRef);
204
+ }
205
+ for (const surface of Object.values(runtime.surfaces)) {
206
+ if (surface.pageRef !== pageRef) {
207
+ continue;
208
+ }
209
+ runtime.surfaces[surface.ref] = {
210
+ ...surface,
211
+ parentSurfaceRef: activeSurfaceRefs.has(surface.ref)
212
+ ? parentBySurface.get(surface.ref)
213
+ : undefined,
214
+ childSurfaceRefs: activeSurfaceRefs.has(surface.ref)
215
+ ? [...(childRefsByParent.get(surface.ref) ?? [])]
216
+ : [],
217
+ targetRefs: activeSurfaceRefs.has(surface.ref) ? [...(targetRefsBySurface.get(surface.ref) ?? [])] : [],
218
+ };
219
+ }
220
+ return observedScopes.map((scope) => runtime.surfaces[scope.ref] ?? scope);
221
+ }
@@ -1,5 +1,5 @@
1
1
  import type { SurfaceDescriptor, TargetDescriptor, TargetValidationEvidence } from '../runtime-state.js';
2
- import type { FillableFormGuidanceHint, PersistedFillableForm, ProtectedBindingValueHint } from '../secrets/types.js';
2
+ import type { PersistedFillableForm, ProtectedBindingValueHint } from '../secrets/types.js';
3
3
  import type { DomObservedTarget, ObservedPageSignal } from './observe-inventory.js';
4
4
  export type GoalObserveScopeCandidate = {
5
5
  goalInventoryType: 'scope';
@@ -20,7 +20,7 @@ export type GoalObserveTargetCandidate = DomObservedTarget & {
20
20
  goalTargetKey: string;
21
21
  };
22
22
  export type GoalObserveInventoryCandidate = GoalObserveTargetCandidate | GoalObserveScopeCandidate;
23
- export declare function compactTargets(targets: ReadonlyArray<Pick<TargetDescriptor, 'ref' | 'kind' | 'label' | 'displayLabel' | 'placeholder' | 'inputName' | 'inputType' | 'autocomplete' | 'validation' | 'context' | 'semantics' | 'structure' | 'capability' | 'availability'>>): Array<{
23
+ export declare function compactTargets(targets: ReadonlyArray<Pick<TargetDescriptor, 'ref' | 'kind' | 'label' | 'displayLabel' | 'placeholder' | 'inputName' | 'inputType' | 'autocomplete' | 'validation' | 'context' | 'semantics' | 'structure' | 'capability' | 'availability' | 'surfaceRef'>>): Array<{
24
24
  ref: string;
25
25
  kind?: string;
26
26
  label?: string;
@@ -36,23 +36,45 @@ export declare function compactTargets(targets: ReadonlyArray<Pick<TargetDescrip
36
36
  capability?: TargetDescriptor['capability'];
37
37
  availability?: string;
38
38
  availabilityReason?: string;
39
+ surfaceRef?: string;
39
40
  source?: 'dom' | 'stagehand' | 'aria-snapshot' | 'cdp-ax';
40
41
  }>;
41
- export declare function compactScopes(scopes: ReadonlyArray<Pick<SurfaceDescriptor, 'ref' | 'kind' | 'label' | 'availability'>>): Array<{
42
+ export type CompactObservedTarget = ReturnType<typeof compactTargets>[number];
43
+ export declare function compactScopes(scopes: ReadonlyArray<Pick<SurfaceDescriptor, 'ref' | 'kind' | 'label' | 'availability' | 'parentSurfaceRef' | 'childSurfaceRefs' | 'targetRefs'>>): Array<{
42
44
  ref: string;
43
45
  kind?: string;
44
46
  label?: string;
45
47
  capability: 'scope';
46
48
  availability?: string;
47
49
  availabilityReason?: string;
50
+ parentSurfaceRef?: string;
51
+ childSurfaceRefs?: string[];
52
+ targetRefs?: string[];
48
53
  source: 'dom';
49
54
  }>;
55
+ export type CompactObservedScope = {
56
+ ref: string;
57
+ kind?: string;
58
+ label?: string;
59
+ capability: 'scope';
60
+ availability?: string;
61
+ availabilityReason?: string;
62
+ parentSurfaceRef?: string;
63
+ childSurfaceRefs?: string[];
64
+ targets: CompactObservedTarget[];
65
+ source: 'dom' | 'stagehand' | 'aria-snapshot' | 'cdp-ax';
66
+ };
67
+ type BuildGroupedObserveScopesOptions = {
68
+ pageRef: string;
69
+ title?: string;
70
+ scopes: ReadonlyArray<Pick<SurfaceDescriptor, 'ref' | 'kind' | 'label' | 'availability' | 'parentSurfaceRef' | 'childSurfaceRefs'>>;
71
+ targets: ReadonlyArray<Pick<TargetDescriptor, 'ref' | 'kind' | 'label' | 'displayLabel' | 'placeholder' | 'inputName' | 'inputType' | 'autocomplete' | 'validation' | 'context' | 'semantics' | 'structure' | 'capability' | 'availability' | 'surfaceRef'>>;
72
+ };
73
+ export declare function buildGroupedObserveScopes(options: BuildGroupedObserveScopesOptions): CompactObservedScope[];
50
74
  export declare function compactFillableForms(forms: ReadonlyArray<PersistedFillableForm>): Array<{
51
75
  fillRef: string;
52
76
  scopeRef?: string;
53
77
  purpose: string;
54
- recommendedTiming?: 'late';
55
- guidance?: FillableFormGuidanceHint;
56
78
  fields: Array<{
57
79
  fieldKey: string;
58
80
  targetRef: string;
@@ -82,4 +104,5 @@ export declare function selectTargetsForGoalMatches(allTargets: ReadonlyArray<Do
82
104
  };
83
105
  export declare function buildExplicitScopeRefs(selectedSurfaceIds: ReadonlySet<string>, surfaceRefMap: ReadonlyMap<string, string>): Set<string>;
84
106
  export declare function projectPersistedTargetsForGoal(domTargets: ReadonlyArray<DomObservedTarget>, persistedTargets: ReadonlyArray<TargetDescriptor>, selectedTargets: ReadonlyArray<DomObservedTarget>): TargetDescriptor[];
107
+ export {};
85
108
  //# sourceMappingURL=observe-projection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observe-projection.d.ts","sourceRoot":"","sources":["../../src/commands/observe-projection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"observe-projection.d.ts","sourceRoot":"","sources":["../../src/commands/observe-projection.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,98 @@
1
1
  import { observedTargetKey } from './observe-semantics.js';
2
- import { summarizeContext } from './observe-surfaces.js';
2
+ import { buildSyntheticFormSurfaceId, summarizeContext } from './observe-surfaces.js';
3
+ function normalizeClusterText(value) {
4
+ const normalized = value?.replace(/\s+/g, ' ').trim().toLowerCase();
5
+ return normalized ? normalized : undefined;
6
+ }
7
+ function isActionLikeGoalTarget(target) {
8
+ const actions = target.allowedActions ?? [];
9
+ const kind = (target.kind ?? '').trim().toLowerCase();
10
+ const role = (target.role ?? '').trim().toLowerCase();
11
+ const isValueControl = actions.includes('fill') || actions.includes('type') || actions.includes('select');
12
+ if (isValueControl) {
13
+ return false;
14
+ }
15
+ return (actions.includes('click') ||
16
+ actions.includes('press') ||
17
+ kind === 'button' ||
18
+ role === 'button' ||
19
+ kind === 'link' ||
20
+ role === 'link');
21
+ }
22
+ function goalActionClusterKey(target) {
23
+ const itemKey = normalizeClusterText(target.context?.item?.label ?? target.context?.item?.text);
24
+ const groupKey = normalizeClusterText(target.context?.group?.label ?? target.context?.group?.text);
25
+ const containerKey = normalizeClusterText(target.context?.container?.label ?? target.context?.container?.text);
26
+ const parts = [
27
+ target.surfaceRef ? `surface:${target.surfaceRef}` : undefined,
28
+ itemKey ? `item:${itemKey}` : undefined,
29
+ groupKey ? `group:${groupKey}` : undefined,
30
+ containerKey ? `container:${containerKey}` : undefined,
31
+ ].filter((value) => Boolean(value));
32
+ return parts.length > 0 ? parts.join('|') : undefined;
33
+ }
34
+ function escapeRegExp(value) {
35
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
36
+ }
37
+ function stripSiblingLabels(value, siblingLabels) {
38
+ if (!value) {
39
+ return value;
40
+ }
41
+ let sanitized = value;
42
+ for (const label of siblingLabels) {
43
+ if (!label) {
44
+ continue;
45
+ }
46
+ sanitized = sanitized.replace(new RegExp(escapeRegExp(label), 'gi'), ' ');
47
+ }
48
+ const collapsed = sanitized.replace(/\s+[—-]\s+/g, ' ').replace(/\s+/g, ' ').trim();
49
+ return collapsed || undefined;
50
+ }
51
+ function sanitizeGoalTargetContext(target, siblingLabelsByCluster) {
52
+ if (!isActionLikeGoalTarget(target)) {
53
+ return target;
54
+ }
55
+ const clusterKey = goalActionClusterKey(target);
56
+ if (!clusterKey) {
57
+ return target;
58
+ }
59
+ const ownLabel = normalizeClusterText(target.label);
60
+ const siblingLabels = (siblingLabelsByCluster.get(clusterKey) ?? []).filter((label) => label !== ownLabel);
61
+ if (siblingLabels.length === 0 || !target.context) {
62
+ return target;
63
+ }
64
+ return {
65
+ ...target,
66
+ context: {
67
+ ...target.context,
68
+ item: target.context.item
69
+ ? {
70
+ ...target.context.item,
71
+ text: stripSiblingLabels(target.context.item.text, siblingLabels),
72
+ }
73
+ : target.context.item,
74
+ group: target.context.group
75
+ ? {
76
+ ...target.context.group,
77
+ text: stripSiblingLabels(target.context.group.text, siblingLabels),
78
+ }
79
+ : target.context.group,
80
+ container: target.context.container
81
+ ? {
82
+ ...target.context.container,
83
+ text: stripSiblingLabels(target.context.container.text, siblingLabels),
84
+ }
85
+ : target.context.container,
86
+ landmark: target.context.landmark
87
+ ? {
88
+ ...target.context.landmark,
89
+ text: stripSiblingLabels(target.context.landmark.text, siblingLabels),
90
+ }
91
+ : target.context.landmark,
92
+ hintText: stripSiblingLabels(target.context.hintText, siblingLabels),
93
+ },
94
+ };
95
+ }
3
96
  export function compactTargets(targets) {
4
97
  return targets.map((target) => ({
5
98
  ref: target.ref,
@@ -17,6 +110,7 @@ export function compactTargets(targets) {
17
110
  capability: target.capability,
18
111
  availability: target.availability?.state,
19
112
  availabilityReason: target.availability?.reason,
113
+ surfaceRef: target.surfaceRef,
20
114
  source: target.semantics?.source,
21
115
  }));
22
116
  }
@@ -28,16 +122,69 @@ export function compactScopes(scopes) {
28
122
  capability: 'scope',
29
123
  availability: scope.availability?.state,
30
124
  availabilityReason: scope.availability?.reason,
125
+ parentSurfaceRef: scope.parentSurfaceRef,
126
+ childSurfaceRefs: scope.childSurfaceRefs ? [...scope.childSurfaceRefs] : [],
127
+ targetRefs: scope.targetRefs ? [...scope.targetRefs] : [],
31
128
  source: 'dom',
32
129
  }));
33
130
  }
131
+ function compactScopeSource(targets) {
132
+ return targets.find((target) => typeof target.source === 'string')?.source ?? 'dom';
133
+ }
134
+ export function buildGroupedObserveScopes(options) {
135
+ const compactedTargets = compactTargets(options.targets);
136
+ const scopeRefs = new Set(options.scopes.map((scope) => scope.ref));
137
+ const compactedTargetsByScope = new Map();
138
+ const unscopedTargets = [];
139
+ for (const target of compactedTargets) {
140
+ if (target.surfaceRef && scopeRefs.has(target.surfaceRef)) {
141
+ const grouped = compactedTargetsByScope.get(target.surfaceRef) ?? [];
142
+ grouped.push(target);
143
+ compactedTargetsByScope.set(target.surfaceRef, grouped);
144
+ continue;
145
+ }
146
+ unscopedTargets.push(target);
147
+ }
148
+ const groupedScopes = options.scopes.map((scope) => {
149
+ const scopeTargets = compactedTargetsByScope.get(scope.ref) ?? [];
150
+ const visibleChildSurfaceRefs = (scope.childSurfaceRefs ?? []).filter((ref) => scopeRefs.has(ref));
151
+ return {
152
+ ref: scope.ref,
153
+ kind: scope.kind,
154
+ label: scope.label,
155
+ capability: 'scope',
156
+ availability: scope.availability?.state,
157
+ availabilityReason: scope.availability?.reason,
158
+ parentSurfaceRef: scope.parentSurfaceRef && scopeRefs.has(scope.parentSurfaceRef)
159
+ ? scope.parentSurfaceRef
160
+ : undefined,
161
+ childSurfaceRefs: visibleChildSurfaceRefs,
162
+ targets: scopeTargets,
163
+ source: compactScopeSource(scopeTargets),
164
+ };
165
+ });
166
+ if (unscopedTargets.length === 0) {
167
+ return groupedScopes;
168
+ }
169
+ return [
170
+ ...groupedScopes,
171
+ {
172
+ ref: `page:${options.pageRef}`,
173
+ kind: 'page',
174
+ label: options.title ?? 'Page',
175
+ capability: 'scope',
176
+ availability: 'available',
177
+ childSurfaceRefs: [],
178
+ targets: unscopedTargets,
179
+ source: compactScopeSource(unscopedTargets),
180
+ },
181
+ ];
182
+ }
34
183
  export function compactFillableForms(forms) {
35
184
  return forms.map((form) => ({
36
185
  fillRef: form.fillRef,
37
186
  scopeRef: form.scopeRef,
38
187
  purpose: form.purpose,
39
- recommendedTiming: form.recommendedTiming,
40
- guidance: form.guidance,
41
188
  fields: form.fields.map((field) => ({
42
189
  fieldKey: field.fieldKey,
43
190
  targetRef: field.targetRef,
@@ -64,11 +211,42 @@ export function compactSignals(signals) {
64
211
  }));
65
212
  }
66
213
  export function buildGoalObserveInventoryCandidates(targets, surfaces) {
67
- const targetCandidates = targets.map((target) => ({
68
- ...target,
69
- goalInventoryType: 'target',
70
- goalTargetKey: observedTargetKey(target),
71
- }));
214
+ const siblingLabelsByCluster = new Map();
215
+ for (const target of targets) {
216
+ if (!isActionLikeGoalTarget(target)) {
217
+ continue;
218
+ }
219
+ const clusterKey = goalActionClusterKey(target);
220
+ const normalizedLabel = normalizeClusterText(target.label);
221
+ if (!clusterKey || !normalizedLabel) {
222
+ continue;
223
+ }
224
+ const labels = siblingLabelsByCluster.get(clusterKey) ?? [];
225
+ if (!labels.includes(normalizedLabel)) {
226
+ labels.push(normalizedLabel);
227
+ siblingLabelsByCluster.set(clusterKey, labels);
228
+ }
229
+ }
230
+ const targetCandidates = targets.map((target) => {
231
+ const sanitized = sanitizeGoalTargetContext(target, siblingLabelsByCluster);
232
+ const syntheticFormSurfaceId = buildSyntheticFormSurfaceId(sanitized);
233
+ const surfaceRef = sanitized.surfaceRef ?? syntheticFormSurfaceId;
234
+ const surfaceKind = sanitized.surfaceKind ?? (syntheticFormSurfaceId ? 'form' : undefined);
235
+ const surfaceLabel = sanitized.surfaceLabel ??
236
+ (syntheticFormSurfaceId
237
+ ? sanitized.context?.landmark?.label ?? sanitized.context?.group?.label ?? 'Form'
238
+ : undefined);
239
+ const surfacePriority = sanitized.surfacePriority ?? (surfaceKind === 'form' ? 70 : undefined);
240
+ return {
241
+ ...sanitized,
242
+ surfaceRef,
243
+ surfaceKind,
244
+ surfaceLabel,
245
+ surfacePriority,
246
+ goalInventoryType: 'target',
247
+ goalTargetKey: observedTargetKey(target),
248
+ };
249
+ });
72
250
  const scopeCandidates = surfaces.map((surface) => {
73
251
  const linkedTargets = targets.filter((target) => target.surfaceRef === surface.surfaceId);
74
252
  const primaryLinkedTarget = linkedTargets[0];
@@ -134,7 +312,9 @@ export function selectTargetsForGoalMatches(allTargets, rerankedCandidates) {
134
312
  const scopeTargets = allTargets.filter((target) => {
135
313
  const directMatch = typeof target.ordinal === 'number' && directTargetOrdinals.has(target.ordinal);
136
314
  const directKeyMatch = directTargetKeys.has(observedTargetKey(target));
137
- const scopeMatch = target.surfaceRef ? selectedSurfaceIds.has(target.surfaceRef) : false;
315
+ const syntheticFormSurfaceId = buildSyntheticFormSurfaceId(target);
316
+ const scopeMatch = (target.surfaceRef ? selectedSurfaceIds.has(target.surfaceRef) : false) ||
317
+ (syntheticFormSurfaceId ? selectedSurfaceIds.has(syntheticFormSurfaceId) : false);
138
318
  if (directMatch || directKeyMatch) {
139
319
  return false;
140
320
  }
@@ -1 +1 @@
1
- {"version":3,"file":"observe-semantics.d.ts","sourceRoot":"","sources":["../../src/commands/observe-semantics.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAYjF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CA6B7E;AAgBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAQ/E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAMnE;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACzC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAChD,iBAAiB,EAAE,CAyCrB;AAkFD,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAChD,iBAAiB,EAAE,CA6BrB;AAqBD,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GACxC,iBAAiB,EAAE,CAuBrB;AAkGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,EAAE,CAmDjG;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GACxC,iBAAiB,EAAE,CAsFrB"}
1
+ {"version":3,"file":"observe-semantics.d.ts","sourceRoot":"","sources":["../../src/commands/observe-semantics.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAYjF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CA6B7E;AAgBD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAQ/E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAMnE;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACzC,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAChD,iBAAiB,EAAE,CAyCrB;AAkFD,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,eAAe,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAChD,iBAAiB,EAAE,CA6BrB;AAqBD,wBAAgB,oCAAoC,CAClD,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GACxC,iBAAiB,EAAE,CAuBrB;AAkGD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,EAAE,CAiEjG;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,GACxC,iBAAiB,EAAE,CAsFrB"}
@@ -1,5 +1,5 @@
1
1
  import { inferAcceptancePolicyFromFacts, inferAllowedActionsFromFacts, inferAvailabilityFromFacts, inferControlFamilyFromFacts, } from '../control-semantics.js';
2
- import { buildSurfaceRef } from './observe-surfaces.js';
2
+ import { buildSurfaceRef, buildSyntheticFormSurfaceId } from './observe-surfaces.js';
3
3
  export function normalizeSemanticDuplicateLabel(target) {
4
4
  return (target.displayLabel ??
5
5
  target.label ??
@@ -299,9 +299,20 @@ export function annotateDomTargets(targets) {
299
299
  const availability = inferAvailability(target);
300
300
  const capability = inferCapability(target, allowedActions);
301
301
  const acceptancePolicy = inferAcceptancePolicy(target, allowedActions);
302
- const surfaceRef = buildSurfaceRef(target);
302
+ const explicitSurfaceRef = buildSurfaceRef(target);
303
+ const syntheticFormSurfaceRef = explicitSurfaceRef === undefined ? buildSyntheticFormSurfaceId(target) : undefined;
304
+ const surfaceRef = explicitSurfaceRef ?? syntheticFormSurfaceRef;
305
+ const surfaceKind = target.surfaceKind ?? (syntheticFormSurfaceRef ? 'form' : undefined);
306
+ const surfaceLabel = target.surfaceLabel ??
307
+ (syntheticFormSurfaceRef
308
+ ? target.context?.landmark?.label ?? target.context?.group?.label ?? 'Form'
309
+ : undefined);
310
+ const surfacePriority = target.surfacePriority ?? (surfaceKind === 'form' ? 70 : undefined);
303
311
  return {
304
312
  ...target,
313
+ surfaceKind,
314
+ surfaceLabel,
315
+ surfacePriority,
305
316
  capability,
306
317
  availability,
307
318
  allowedActions,
@@ -2,6 +2,7 @@ import type { LocatorCandidate, SurfaceDescriptor, TargetContext, TargetDescript
2
2
  import type { DomObservedTarget } from './observe-inventory.js';
3
3
  export declare function selectScopesForOutput(scopes: ReadonlyArray<SurfaceDescriptor>, targets: ReadonlyArray<Pick<TargetDescriptor, 'surfaceRef' | 'allowedActions' | 'acceptancePolicy'>>, preferredScopeRefs?: ReadonlySet<string>): SurfaceDescriptor[];
4
4
  export declare function buildSurfaceRef(target: DomObservedTarget): string | undefined;
5
+ export declare function buildSyntheticFormSurfaceId(target: Pick<DomObservedTarget, 'pageSignature' | 'framePath' | 'frameUrl' | 'formSelector' | 'context'>): string | undefined;
5
6
  export declare function surfaceReplacementKey(surface: Pick<SurfaceDescriptor, 'pageRef' | 'pageSignature' | 'framePath' | 'kind' | 'label'>): string;
6
7
  export declare function summarizeContext(context: TargetContext | undefined): string | undefined;
7
8
  export declare function pushUniqueLocatorCandidate(acc: LocatorCandidate[], candidate: LocatorCandidate | undefined): void;
@@ -1 +1 @@
1
- {"version":3,"file":"observe-surfaces.d.ts","sourceRoot":"","sources":["../../src/commands/observe-surfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAahE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACxC,OAAO,EAAE,aAAa,CACpB,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,gBAAgB,GAAG,kBAAkB,CAAC,CAC7E,EACD,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACvC,iBAAiB,EAAE,CA+CrB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAa7E;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,eAAe,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC,GAC7F,MAAM,CAMR;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA4CvF;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,gBAAgB,EAAE,EACvB,SAAS,EAAE,gBAAgB,GAAG,SAAS,GACtC,IAAI,CAON;AAwDD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,oCAoC1C"}
1
+ {"version":3,"file":"observe-surfaces.d.ts","sourceRoot":"","sources":["../../src/commands/observe-surfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,gBAAgB,EACjB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAgBhE,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,aAAa,CAAC,iBAAiB,CAAC,EACxC,OAAO,EAAE,aAAa,CACpB,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,gBAAgB,GAAG,kBAAkB,CAAC,CAC7E,EACD,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACvC,iBAAiB,EAAE,CA+CrB;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAa7E;AAyBD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,WAAW,GAAG,UAAU,GAAG,cAAc,GAAG,SAAS,CAAC,GACvG,MAAM,GAAG,SAAS,CAiBpB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,GAAG,eAAe,GAAG,WAAW,GAAG,MAAM,GAAG,OAAO,CAAC,GAC7F,MAAM,CAMR;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CA4CvF;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,gBAAgB,EAAE,EACvB,SAAS,EAAE,gBAAgB,GAAG,SAAS,GACtC,IAAI,CAON;AAwDD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,aAAa,CAAC,iBAAiB,CAAC,oCAoE1C"}
@@ -1,5 +1,6 @@
1
1
  import { locatorCandidateKey } from '../runtime-state.js';
2
2
  const HIGH_SIGNAL_SCOPE_KINDS = new Set([
3
+ 'form',
3
4
  'dialog',
4
5
  'listbox',
5
6
  'menu',
@@ -8,6 +9,8 @@ const HIGH_SIGNAL_SCOPE_KINDS = new Set([
8
9
  'popover',
9
10
  'dropdown',
10
11
  'datepicker',
12
+ 'floating-panel',
13
+ 'sticky-panel',
11
14
  ]);
12
15
  export function selectScopesForOutput(scopes, targets, preferredScopeRefs) {
13
16
  if (scopes.length === 0) {
@@ -63,6 +66,39 @@ export function buildSurfaceRef(target) {
63
66
  target.surfaceLabel ?? '',
64
67
  ].join('|');
65
68
  }
69
+ function normalizeSurfaceText(value) {
70
+ const normalized = value?.replace(/\s+/g, ' ').trim();
71
+ return normalized ? normalized : undefined;
72
+ }
73
+ function semanticFormContextLabel(target) {
74
+ for (const node of [
75
+ target.context?.landmark,
76
+ target.context?.container,
77
+ target.context?.group,
78
+ target.context?.item,
79
+ ]) {
80
+ const kind = (node?.kind ?? '').trim().toLowerCase();
81
+ if (kind !== 'form') {
82
+ continue;
83
+ }
84
+ return normalizeSurfaceText(node?.label ?? node?.text);
85
+ }
86
+ return undefined;
87
+ }
88
+ export function buildSyntheticFormSurfaceId(target) {
89
+ const pageKey = normalizeSurfaceText(target.pageSignature);
90
+ if (!pageKey) {
91
+ return undefined;
92
+ }
93
+ const formKey = normalizeSurfaceText(target.formSelector) ??
94
+ semanticFormContextLabel(target)?.toLowerCase();
95
+ if (!formKey) {
96
+ return undefined;
97
+ }
98
+ const frameKey = target.framePath?.join('>') ??
99
+ (normalizeSurfaceText(target.frameUrl) ? `url:${normalizeSurfaceText(target.frameUrl)}` : 'top');
100
+ return `${pageKey}|${frameKey}|form|${formKey}`;
101
+ }
66
102
  export function surfaceReplacementKey(surface) {
67
103
  const pageKey = surface.pageSignature ?? surface.pageRef;
68
104
  const frameKey = surface.framePath?.join('>') ?? 'top';
@@ -191,5 +227,34 @@ export function collectSurfaceDescriptors(pageRef, targets) {
191
227
  pageSignature: existing?.pageSignature ?? target.pageSignature,
192
228
  });
193
229
  }
230
+ for (const target of targets) {
231
+ const surfaceId = buildSyntheticFormSurfaceId(target);
232
+ if (!surfaceId) {
233
+ continue;
234
+ }
235
+ const existing = descriptors.get(surfaceId);
236
+ const locatorCandidates = existing ? [...existing.locatorCandidates] : [];
237
+ const formSelector = target.formSelector?.trim();
238
+ if (formSelector) {
239
+ pushUniqueLocatorCandidate(locatorCandidates, {
240
+ strategy: formSelector.startsWith('xpath=') ? 'xpath' : 'css',
241
+ value: formSelector,
242
+ scope: 'root',
243
+ });
244
+ }
245
+ descriptors.set(surfaceId, {
246
+ surfaceId,
247
+ pageRef,
248
+ framePath: existing?.framePath ?? target.framePath,
249
+ frameUrl: existing?.frameUrl ?? target.frameUrl,
250
+ kind: 'form',
251
+ label: existing?.label ?? semanticFormContextLabel(target) ?? 'Form',
252
+ lifecycle: 'live',
253
+ availability: { state: 'available' },
254
+ locatorCandidates,
255
+ createdAt: existing?.createdAt ?? Date.now(),
256
+ pageSignature: existing?.pageSignature ?? target.pageSignature,
257
+ });
258
+ }
194
259
  return [...descriptors.values()];
195
260
  }
@@ -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;AAgDnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAU/D,eAAO,MAAM,yBAAyB;;;;iBA6OguF,CAAC;gBAAwB,CAAC;;;;;iBAAq7vE,CAAC;gBAAwB,CAAC;;;CA7O1q1E,CAAC;AACtE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGrC,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsOzF"}
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;AAgDnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAU/D,eAAO,MAAM,yBAAyB;;;;iBAyR+wD,CAAC;gBAAwB,CAAC;;;;;iBAAirzE,CAAC;gBAAwB,CAAC;;;CAzRr92E,CAAC;AACtE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGrC,CAAC;AAEF,wBAAsB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkRzF"}