@nuanu-ai/agentbrowse 0.2.7 → 0.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -8
- package/dist/agentpay-stagehand-llm.d.ts.map +1 -1
- package/dist/agentpay-stagehand-llm.js +5 -1
- package/dist/commands/act.d.ts +6 -2
- package/dist/commands/act.d.ts.map +1 -1
- package/dist/commands/act.js +840 -55
- package/dist/commands/act.test-harness.d.ts +19 -0
- package/dist/commands/act.test-harness.d.ts.map +1 -0
- package/dist/commands/act.test-harness.js +245 -0
- package/dist/commands/action-acceptance.d.ts +90 -0
- package/dist/commands/action-acceptance.d.ts.map +1 -0
- package/dist/commands/action-acceptance.js +1411 -0
- package/dist/commands/action-artifacts.d.ts +33 -0
- package/dist/commands/action-artifacts.d.ts.map +1 -0
- package/dist/commands/action-artifacts.js +104 -0
- package/dist/commands/action-execution-guards.d.ts +5 -0
- package/dist/commands/action-execution-guards.d.ts.map +1 -0
- package/dist/commands/action-execution-guards.js +3 -0
- package/dist/commands/action-executor-helpers.d.ts +21 -0
- package/dist/commands/action-executor-helpers.d.ts.map +1 -0
- package/dist/commands/action-executor-helpers.js +242 -0
- package/dist/commands/action-executor.d.ts +12 -0
- package/dist/commands/action-executor.d.ts.map +1 -0
- package/dist/commands/action-executor.js +45 -0
- package/dist/commands/action-fallbacks.d.ts +6 -0
- package/dist/commands/action-fallbacks.d.ts.map +1 -0
- package/dist/commands/action-fallbacks.js +43 -0
- package/dist/commands/action-value-projection.d.ts +32 -0
- package/dist/commands/action-value-projection.d.ts.map +1 -0
- package/dist/commands/action-value-projection.js +151 -0
- package/dist/commands/browse-actions.d.ts +4 -0
- package/dist/commands/browse-actions.d.ts.map +1 -0
- package/dist/commands/browse-actions.js +4 -0
- package/dist/commands/captcha-solve.d.ts.map +1 -1
- package/dist/commands/captcha-solve.js +13 -3
- package/dist/commands/click-action-executor.d.ts +10 -0
- package/dist/commands/click-action-executor.d.ts.map +1 -0
- package/dist/commands/click-action-executor.js +68 -0
- package/dist/commands/create-intent.d.ts +6 -0
- package/dist/commands/create-intent.d.ts.map +1 -0
- package/dist/commands/create-intent.js +75 -0
- package/dist/commands/datepicker-action-executor.d.ts +12 -0
- package/dist/commands/datepicker-action-executor.d.ts.map +1 -0
- package/dist/commands/datepicker-action-executor.js +218 -0
- package/dist/commands/descriptor-validation.d.ts +27 -0
- package/dist/commands/descriptor-validation.d.ts.map +1 -0
- package/dist/commands/descriptor-validation.js +333 -0
- package/dist/commands/extract-scope-resolution.d.ts +20 -0
- package/dist/commands/extract-scope-resolution.d.ts.map +1 -0
- package/dist/commands/extract-scope-resolution.js +100 -0
- package/dist/commands/extract-stagehand-executor.d.ts +17 -0
- package/dist/commands/extract-stagehand-executor.d.ts.map +1 -0
- package/dist/commands/extract-stagehand-executor.js +18 -0
- package/dist/commands/extract.d.ts +3 -2
- package/dist/commands/extract.d.ts.map +1 -1
- package/dist/commands/extract.js +256 -39
- package/dist/commands/fill-secret.d.ts +7 -0
- package/dist/commands/fill-secret.d.ts.map +1 -0
- package/dist/commands/fill-secret.js +371 -0
- package/dist/commands/get-secrets-catalog.d.ts +6 -0
- package/dist/commands/get-secrets-catalog.d.ts.map +1 -0
- package/dist/commands/get-secrets-catalog.js +23 -0
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +41 -7
- package/dist/commands/navigate.d.ts +2 -1
- package/dist/commands/navigate.d.ts.map +1 -1
- package/dist/commands/navigate.js +49 -12
- package/dist/commands/observe-inventory.d.ts +109 -0
- package/dist/commands/observe-inventory.d.ts.map +1 -0
- package/dist/commands/observe-inventory.js +2837 -0
- package/dist/commands/observe-persistence.d.ts +14 -0
- package/dist/commands/observe-persistence.d.ts.map +1 -0
- package/dist/commands/observe-persistence.js +170 -0
- package/dist/commands/observe-projection.d.ts +84 -0
- package/dist/commands/observe-projection.d.ts.map +1 -0
- package/dist/commands/observe-projection.js +140 -0
- package/dist/commands/observe-protected.d.ts +5 -0
- package/dist/commands/observe-protected.d.ts.map +1 -0
- package/dist/commands/observe-protected.js +18 -0
- package/dist/commands/observe-semantics.d.ts +10 -0
- package/dist/commands/observe-semantics.d.ts.map +1 -0
- package/dist/commands/observe-semantics.js +338 -0
- package/dist/commands/observe-stagehand.d.ts +48 -0
- package/dist/commands/observe-stagehand.d.ts.map +1 -0
- package/dist/commands/observe-stagehand.js +105 -0
- package/dist/commands/observe-surfaces.d.ts +9 -0
- package/dist/commands/observe-surfaces.d.ts.map +1 -0
- package/dist/commands/observe-surfaces.js +195 -0
- package/dist/commands/observe.d.ts +47 -1
- package/dist/commands/observe.d.ts.map +1 -1
- package/dist/commands/observe.js +173 -20
- package/dist/commands/observe.test-harness.d.ts +67 -0
- package/dist/commands/observe.test-harness.d.ts.map +1 -0
- package/dist/commands/observe.test-harness.js +107 -0
- package/dist/commands/poll-intent.d.ts +6 -0
- package/dist/commands/poll-intent.d.ts.map +1 -0
- package/dist/commands/poll-intent.js +57 -0
- package/dist/commands/screenshot.d.ts +2 -1
- package/dist/commands/screenshot.d.ts.map +1 -1
- package/dist/commands/screenshot.js +44 -12
- package/dist/commands/select-action-executor.d.ts +10 -0
- package/dist/commands/select-action-executor.d.ts.map +1 -0
- package/dist/commands/select-action-executor.js +91 -0
- package/dist/commands/semantic-observe.d.ts +24 -0
- package/dist/commands/semantic-observe.d.ts.map +1 -0
- package/dist/commands/semantic-observe.js +344 -0
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +75 -2
- package/dist/commands/structured-grid-action-executor.d.ts +3 -0
- package/dist/commands/structured-grid-action-executor.d.ts.map +1 -0
- package/dist/commands/structured-grid-action-executor.js +4 -0
- package/dist/commands/target-resolution.d.ts +4 -0
- package/dist/commands/target-resolution.d.ts.map +1 -0
- package/dist/commands/target-resolution.js +33 -0
- package/dist/commands/text-input-action-executor.d.ts +5 -0
- package/dist/commands/text-input-action-executor.d.ts.map +1 -0
- package/dist/commands/text-input-action-executor.js +116 -0
- package/dist/commands/user-actionable.d.ts +4 -0
- package/dist/commands/user-actionable.d.ts.map +1 -0
- package/dist/commands/user-actionable.js +95 -0
- package/dist/control-semantics.d.ts +29 -0
- package/dist/control-semantics.d.ts.map +1 -0
- package/dist/control-semantics.js +299 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +95 -32
- package/dist/output.d.ts +14 -2
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +17 -29
- package/dist/playwright-runtime.d.ts +35 -0
- package/dist/playwright-runtime.d.ts.map +1 -0
- package/dist/playwright-runtime.js +224 -0
- package/dist/runtime-resolution.d.ts +9 -0
- package/dist/runtime-resolution.d.ts.map +1 -0
- package/dist/runtime-resolution.js +19 -0
- package/dist/runtime-state.d.ts +217 -0
- package/dist/runtime-state.d.ts.map +1 -0
- package/dist/runtime-state.js +629 -0
- package/dist/secrets/backend.d.ts +32 -0
- package/dist/secrets/backend.d.ts.map +1 -0
- package/dist/secrets/backend.js +169 -0
- package/dist/secrets/catalog-applicability.d.ts +5 -0
- package/dist/secrets/catalog-applicability.d.ts.map +1 -0
- package/dist/secrets/catalog-applicability.js +59 -0
- package/dist/secrets/catalog-sync.d.ts +14 -0
- package/dist/secrets/catalog-sync.d.ts.map +1 -0
- package/dist/secrets/catalog-sync.js +35 -0
- package/dist/secrets/field-policy.d.ts +3 -0
- package/dist/secrets/field-policy.d.ts.map +1 -0
- package/dist/secrets/field-policy.js +3 -0
- package/dist/secrets/fill-ordering.d.ts +11 -0
- package/dist/secrets/fill-ordering.d.ts.map +1 -0
- package/dist/secrets/fill-ordering.js +44 -0
- package/dist/secrets/form-matcher.d.ts +60 -0
- package/dist/secrets/form-matcher.d.ts.map +1 -0
- package/dist/secrets/form-matcher.js +596 -0
- package/dist/secrets/intent-output.d.ts +11 -0
- package/dist/secrets/intent-output.d.ts.map +1 -0
- package/dist/secrets/intent-output.js +64 -0
- package/dist/secrets/mock-agentpay-backend.d.ts +13 -0
- package/dist/secrets/mock-agentpay-backend.d.ts.map +1 -0
- package/dist/secrets/mock-agentpay-backend.js +87 -0
- package/dist/secrets/mock-agentpay-cabinet.d.ts +43 -0
- package/dist/secrets/mock-agentpay-cabinet.d.ts.map +1 -0
- package/dist/secrets/mock-agentpay-cabinet.js +195 -0
- package/dist/secrets/protected-artifact-guard.d.ts +25 -0
- package/dist/secrets/protected-artifact-guard.d.ts.map +1 -0
- package/dist/secrets/protected-artifact-guard.js +26 -0
- package/dist/secrets/protected-bindings.d.ts +10 -0
- package/dist/secrets/protected-bindings.d.ts.map +1 -0
- package/dist/secrets/protected-bindings.js +17 -0
- package/dist/secrets/protected-field-values.d.ts +13 -0
- package/dist/secrets/protected-field-values.d.ts.map +1 -0
- package/dist/secrets/protected-field-values.js +100 -0
- package/dist/secrets/protected-fill.d.ts +47 -0
- package/dist/secrets/protected-fill.d.ts.map +1 -0
- package/dist/secrets/protected-fill.js +512 -0
- package/dist/secrets/types.d.ts +84 -0
- package/dist/secrets/types.d.ts.map +1 -0
- package/dist/secrets/types.js +27 -0
- package/dist/session.d.ts +22 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +74 -2
- package/dist/solver/browser-launcher.d.ts.map +1 -1
- package/dist/solver/browser-launcher.js +6 -3
- package/dist/stagehand-runtime.d.ts +4 -0
- package/dist/stagehand-runtime.d.ts.map +1 -0
- package/dist/stagehand-runtime.js +10 -0
- package/dist/stagehand.d.ts +0 -5
- package/dist/stagehand.d.ts.map +1 -1
- package/dist/stagehand.js +0 -6
- package/package.json +5 -2
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import { inferAcceptancePolicyFromFacts, inferAllowedActionsFromFacts, inferAvailabilityFromFacts, inferControlFamilyFromFacts, } from '../control-semantics.js';
|
|
2
|
+
import { buildSurfaceRef } from './observe-surfaces.js';
|
|
3
|
+
export function normalizeSemanticDuplicateLabel(target) {
|
|
4
|
+
return (target.displayLabel ??
|
|
5
|
+
target.label ??
|
|
6
|
+
target.text ??
|
|
7
|
+
target.placeholder ??
|
|
8
|
+
target.title ??
|
|
9
|
+
'')
|
|
10
|
+
.replace(/\s+/g, ' ')
|
|
11
|
+
.trim()
|
|
12
|
+
.toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
export function isPrimaryFormControlTarget(target) {
|
|
15
|
+
const kind = (target.kind ?? '').trim().toLowerCase();
|
|
16
|
+
const role = (target.role ?? '').trim().toLowerCase();
|
|
17
|
+
const acceptancePolicy = (target.acceptancePolicy ?? '').trim().toLowerCase();
|
|
18
|
+
if (target.allowedActions?.includes('fill') || target.allowedActions?.includes('type')) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (target.allowedActions?.includes('select')) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
if (acceptancePolicy === 'submit' || acceptancePolicy === 'date-selection') {
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (acceptancePolicy === 'disclosure' &&
|
|
28
|
+
Boolean(formGroupingKeyOf(target)) &&
|
|
29
|
+
(kind === 'button' || role === 'button')) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
return (kind === 'input' ||
|
|
33
|
+
kind === 'textarea' ||
|
|
34
|
+
kind === 'select' ||
|
|
35
|
+
role === 'textbox' ||
|
|
36
|
+
role === 'combobox');
|
|
37
|
+
}
|
|
38
|
+
function semanticFormContextKey(context) {
|
|
39
|
+
for (const node of [context?.landmark, context?.container, context?.group, context?.item]) {
|
|
40
|
+
const kind = (node?.kind ?? '').trim().toLowerCase();
|
|
41
|
+
if (kind !== 'form') {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const label = (node?.label ?? node?.text ?? '').replace(/\s+/g, ' ').trim().toLowerCase();
|
|
45
|
+
return `${kind}|${label}`;
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
export function formGroupingKeyOf(target) {
|
|
50
|
+
const formSelector = target.formSelector?.trim();
|
|
51
|
+
if (formSelector) {
|
|
52
|
+
return `selector:${formSelector}`;
|
|
53
|
+
}
|
|
54
|
+
const contextKey = semanticFormContextKey(target.context);
|
|
55
|
+
return contextKey ? `context:${contextKey}` : undefined;
|
|
56
|
+
}
|
|
57
|
+
export function observedTargetKey(target) {
|
|
58
|
+
return (target.selector ??
|
|
59
|
+
target.domSignature ??
|
|
60
|
+
`${target.formSelector ?? 'no-form'}|${target.ordinal ?? 'no-ordinal'}|${target.label ?? ''}`);
|
|
61
|
+
}
|
|
62
|
+
export function expandRerankedFormTargets(targets, selectedTargets) {
|
|
63
|
+
const selectedFormControlCounts = new Map();
|
|
64
|
+
for (const target of selectedTargets) {
|
|
65
|
+
const formKey = formGroupingKeyOf(target);
|
|
66
|
+
if (!formKey || !isPrimaryFormControlTarget(target)) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
selectedFormControlCounts.set(formKey, (selectedFormControlCounts.get(formKey) ?? 0) + 1);
|
|
70
|
+
}
|
|
71
|
+
const expandableFormKeys = new Set([...selectedFormControlCounts.entries()]
|
|
72
|
+
.filter(([, count]) => count >= 2)
|
|
73
|
+
.map(([formKey]) => formKey));
|
|
74
|
+
if (expandableFormKeys.size === 0) {
|
|
75
|
+
return [...selectedTargets];
|
|
76
|
+
}
|
|
77
|
+
const expanded = new Map();
|
|
78
|
+
for (const target of selectedTargets) {
|
|
79
|
+
expanded.set(observedTargetKey(target), target);
|
|
80
|
+
}
|
|
81
|
+
for (const target of targets) {
|
|
82
|
+
const formKey = formGroupingKeyOf(target);
|
|
83
|
+
if (!formKey || !expandableFormKeys.has(formKey) || !isPrimaryFormControlTarget(target)) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
expanded.set(observedTargetKey(target), target);
|
|
87
|
+
}
|
|
88
|
+
return [...expanded.values()].sort((left, right) => {
|
|
89
|
+
const leftOrdinal = left.ordinal ?? Number.MAX_SAFE_INTEGER;
|
|
90
|
+
const rightOrdinal = right.ordinal ?? Number.MAX_SAFE_INTEGER;
|
|
91
|
+
if (leftOrdinal !== rightOrdinal) {
|
|
92
|
+
return leftOrdinal - rightOrdinal;
|
|
93
|
+
}
|
|
94
|
+
return (left.label ?? '').localeCompare(right.label ?? '');
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
function semanticCompressionKey(target) {
|
|
98
|
+
const band = target.context?.layout?.band;
|
|
99
|
+
if (band !== 'bottom') {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
const kind = (target.kind ?? '').trim().toLowerCase();
|
|
103
|
+
if (kind !== 'link' && kind !== 'button') {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const label = normalizeSemanticDuplicateLabel(target);
|
|
107
|
+
if (!label) {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
return `${kind}|${label}`;
|
|
111
|
+
}
|
|
112
|
+
export function compressSemanticallyDuplicateTargets(targets) {
|
|
113
|
+
const repeatedKeys = new Map();
|
|
114
|
+
for (const target of targets) {
|
|
115
|
+
const key = semanticCompressionKey(target);
|
|
116
|
+
if (!key) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
repeatedKeys.set(key, (repeatedKeys.get(key) || 0) + 1);
|
|
120
|
+
}
|
|
121
|
+
const seen = new Set();
|
|
122
|
+
return targets.filter((target) => {
|
|
123
|
+
const key = semanticCompressionKey(target);
|
|
124
|
+
if (!key || (repeatedKeys.get(key) || 0) <= 1) {
|
|
125
|
+
return true;
|
|
126
|
+
}
|
|
127
|
+
if (seen.has(key)) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
seen.add(key);
|
|
131
|
+
return true;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function inferAllowedActions(target) {
|
|
135
|
+
return inferAllowedActionsFromFacts({
|
|
136
|
+
kind: target.kind,
|
|
137
|
+
role: target.role,
|
|
138
|
+
label: target.label,
|
|
139
|
+
displayLabel: target.displayLabel,
|
|
140
|
+
interactionHint: target.interactionHint,
|
|
141
|
+
text: target.text,
|
|
142
|
+
placeholder: target.placeholder,
|
|
143
|
+
inputName: target.inputName,
|
|
144
|
+
inputType: target.inputType,
|
|
145
|
+
autocomplete: target.autocomplete,
|
|
146
|
+
surfaceKind: target.surfaceKind,
|
|
147
|
+
controlsSurfaceSelector: target.controlsSurfaceSelector,
|
|
148
|
+
states: target.states,
|
|
149
|
+
structure: target.structure,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function inferAvailability(target) {
|
|
153
|
+
const allowedActions = inferAllowedActions(target);
|
|
154
|
+
const controlFamily = inferControlFamilyFromFacts({
|
|
155
|
+
kind: target.kind,
|
|
156
|
+
role: target.role,
|
|
157
|
+
label: target.label,
|
|
158
|
+
displayLabel: target.displayLabel,
|
|
159
|
+
interactionHint: target.interactionHint,
|
|
160
|
+
text: target.text,
|
|
161
|
+
placeholder: target.placeholder,
|
|
162
|
+
inputName: target.inputName,
|
|
163
|
+
inputType: target.inputType,
|
|
164
|
+
autocomplete: target.autocomplete,
|
|
165
|
+
surfaceKind: target.surfaceKind,
|
|
166
|
+
controlsSurfaceSelector: target.controlsSurfaceSelector,
|
|
167
|
+
states: target.states,
|
|
168
|
+
structure: target.structure,
|
|
169
|
+
}, allowedActions);
|
|
170
|
+
const acceptancePolicy = inferAcceptancePolicy(target, allowedActions);
|
|
171
|
+
return inferAvailabilityFromFacts(target.states, target.context?.hintText, {
|
|
172
|
+
readonlyInteractive: controlFamily === 'select' ||
|
|
173
|
+
controlFamily === 'datepicker' ||
|
|
174
|
+
acceptancePolicy === 'selection' ||
|
|
175
|
+
acceptancePolicy === 'date-selection',
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
function inferAcceptancePolicy(target, allowedActions) {
|
|
179
|
+
return inferAcceptancePolicyFromFacts({
|
|
180
|
+
kind: target.kind,
|
|
181
|
+
role: target.role,
|
|
182
|
+
label: target.label,
|
|
183
|
+
displayLabel: target.displayLabel,
|
|
184
|
+
interactionHint: target.interactionHint,
|
|
185
|
+
text: target.text,
|
|
186
|
+
placeholder: target.placeholder,
|
|
187
|
+
inputName: target.inputName,
|
|
188
|
+
inputType: target.inputType,
|
|
189
|
+
autocomplete: target.autocomplete,
|
|
190
|
+
surfaceKind: target.surfaceKind,
|
|
191
|
+
controlsSurfaceSelector: target.controlsSurfaceSelector,
|
|
192
|
+
states: target.states,
|
|
193
|
+
structure: target.structure,
|
|
194
|
+
}, allowedActions);
|
|
195
|
+
}
|
|
196
|
+
function inferCapability(target, allowedActions) {
|
|
197
|
+
const hasExecutionPath = allowedActions.length > 0;
|
|
198
|
+
if (!hasExecutionPath) {
|
|
199
|
+
return 'informational';
|
|
200
|
+
}
|
|
201
|
+
const label = target.label ?? target.displayLabel ?? target.text ?? '';
|
|
202
|
+
const descendantInteractiveCount = target.descendantInteractiveCount ?? 0;
|
|
203
|
+
const giantContainerLike = label.length > 180 && descendantInteractiveCount >= 4 && allowedActions.includes('click');
|
|
204
|
+
if (giantContainerLike) {
|
|
205
|
+
return 'scope';
|
|
206
|
+
}
|
|
207
|
+
return 'actionable';
|
|
208
|
+
}
|
|
209
|
+
export function annotateDomTargets(targets) {
|
|
210
|
+
const annotated = targets.map((target) => {
|
|
211
|
+
const allowedActions = inferAllowedActions(target);
|
|
212
|
+
const availability = inferAvailability(target);
|
|
213
|
+
const capability = inferCapability(target, allowedActions);
|
|
214
|
+
const acceptancePolicy = inferAcceptancePolicy(target, allowedActions);
|
|
215
|
+
const surfaceRef = buildSurfaceRef(target);
|
|
216
|
+
return {
|
|
217
|
+
...target,
|
|
218
|
+
capability,
|
|
219
|
+
availability,
|
|
220
|
+
allowedActions,
|
|
221
|
+
acceptancePolicy,
|
|
222
|
+
surfaceRef,
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
return annotated.map((target, index, current) => {
|
|
226
|
+
if (!target.surfaceRef ||
|
|
227
|
+
!target.acceptancePolicy ||
|
|
228
|
+
!(target.acceptancePolicy === 'selection' || target.acceptancePolicy === 'date-selection')) {
|
|
229
|
+
return target;
|
|
230
|
+
}
|
|
231
|
+
const ownerIndex = current.findIndex((candidate, candidateIndex) => {
|
|
232
|
+
if (candidateIndex === index)
|
|
233
|
+
return false;
|
|
234
|
+
const explicitController = [
|
|
235
|
+
target.controlsSurfaceSelector,
|
|
236
|
+
target.surfaceSelector,
|
|
237
|
+
...(target.surfaceSelectors ?? []),
|
|
238
|
+
candidate.surfaceSelector,
|
|
239
|
+
]
|
|
240
|
+
.filter((value) => typeof value === 'string' && value.length > 0)
|
|
241
|
+
.some((selector) => candidate.controlsSurfaceSelector === selector);
|
|
242
|
+
const sameSurface = candidate.surfaceRef === target.surfaceRef;
|
|
243
|
+
if (!explicitController && !sameSurface)
|
|
244
|
+
return false;
|
|
245
|
+
if (candidate.allowedActions?.includes('fill'))
|
|
246
|
+
return true;
|
|
247
|
+
if (candidate.allowedActions?.includes('select'))
|
|
248
|
+
return true;
|
|
249
|
+
if (candidate.structure?.family === 'structured-grid')
|
|
250
|
+
return false;
|
|
251
|
+
if (candidate.capability === 'informational' && !explicitController)
|
|
252
|
+
return false;
|
|
253
|
+
return (candidate.allowedActions?.includes('click') &&
|
|
254
|
+
['input', 'select', 'button', 'combobox'].includes((candidate.kind || '').toLowerCase()));
|
|
255
|
+
});
|
|
256
|
+
return ownerIndex >= 0 ? { ...target, ownerIndex } : target;
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
export function orderBySurfaceCompetition(targets) {
|
|
260
|
+
const iframeFieldLike = (target) => {
|
|
261
|
+
const kind = (target.kind ?? '').toLowerCase();
|
|
262
|
+
const role = (target.role ?? '').toLowerCase();
|
|
263
|
+
return (Boolean(target.framePath?.length) &&
|
|
264
|
+
(target.allowedActions?.includes('fill') ||
|
|
265
|
+
target.allowedActions?.includes('type') ||
|
|
266
|
+
target.allowedActions?.includes('select') ||
|
|
267
|
+
['input', 'textarea', 'select', 'combobox'].includes(kind) ||
|
|
268
|
+
['textbox', 'combobox'].includes(role)));
|
|
269
|
+
};
|
|
270
|
+
return [...targets].sort((left, right) => {
|
|
271
|
+
const leftPriority = left.surfacePriority ?? 0;
|
|
272
|
+
const rightPriority = right.surfacePriority ?? 0;
|
|
273
|
+
let leftScore = leftPriority * 10;
|
|
274
|
+
let rightScore = rightPriority * 10;
|
|
275
|
+
if (leftPriority >= 80) {
|
|
276
|
+
leftScore += 3_000;
|
|
277
|
+
}
|
|
278
|
+
else if (leftPriority >= 50) {
|
|
279
|
+
leftScore += 2_000;
|
|
280
|
+
}
|
|
281
|
+
else if (left.surfaceRef) {
|
|
282
|
+
leftScore += 1_000;
|
|
283
|
+
}
|
|
284
|
+
if (rightPriority >= 80) {
|
|
285
|
+
rightScore += 3_000;
|
|
286
|
+
}
|
|
287
|
+
else if (rightPriority >= 50) {
|
|
288
|
+
rightScore += 2_000;
|
|
289
|
+
}
|
|
290
|
+
else if (right.surfaceRef) {
|
|
291
|
+
rightScore += 1_000;
|
|
292
|
+
}
|
|
293
|
+
if (left.capability === 'actionable') {
|
|
294
|
+
leftScore += 150;
|
|
295
|
+
}
|
|
296
|
+
else if (left.capability === 'scope') {
|
|
297
|
+
leftScore += 75;
|
|
298
|
+
}
|
|
299
|
+
if (right.capability === 'actionable') {
|
|
300
|
+
rightScore += 150;
|
|
301
|
+
}
|
|
302
|
+
else if (right.capability === 'scope') {
|
|
303
|
+
rightScore += 75;
|
|
304
|
+
}
|
|
305
|
+
if (left.allowedActions?.includes('fill') || left.allowedActions?.includes('select')) {
|
|
306
|
+
leftScore += 40;
|
|
307
|
+
}
|
|
308
|
+
if (right.allowedActions?.includes('fill') || right.allowedActions?.includes('select')) {
|
|
309
|
+
rightScore += 40;
|
|
310
|
+
}
|
|
311
|
+
if (isPrimaryFormControlTarget(left) && formGroupingKeyOf(left)) {
|
|
312
|
+
leftScore += 900;
|
|
313
|
+
}
|
|
314
|
+
if (isPrimaryFormControlTarget(right) && formGroupingKeyOf(right)) {
|
|
315
|
+
rightScore += 900;
|
|
316
|
+
}
|
|
317
|
+
if (iframeFieldLike(left)) {
|
|
318
|
+
leftScore += 1_200;
|
|
319
|
+
}
|
|
320
|
+
if (iframeFieldLike(right)) {
|
|
321
|
+
rightScore += 1_200;
|
|
322
|
+
}
|
|
323
|
+
if (left.ownerIndex !== undefined) {
|
|
324
|
+
leftScore -= 5;
|
|
325
|
+
}
|
|
326
|
+
if (right.ownerIndex !== undefined) {
|
|
327
|
+
rightScore -= 5;
|
|
328
|
+
}
|
|
329
|
+
const scoreDelta = rightScore - leftScore;
|
|
330
|
+
if (scoreDelta !== 0) {
|
|
331
|
+
return scoreDelta;
|
|
332
|
+
}
|
|
333
|
+
if (leftPriority !== rightPriority) {
|
|
334
|
+
return rightPriority - leftPriority;
|
|
335
|
+
}
|
|
336
|
+
return (left.ordinal ?? 0) - (right.ordinal ?? 0);
|
|
337
|
+
});
|
|
338
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Page } from 'playwright-core';
|
|
2
|
+
import { normalizeStagehandSelector, readStagehandLocatorSnapshot } from './observe-inventory.js';
|
|
3
|
+
type StagehandObserveAction = {
|
|
4
|
+
description?: string;
|
|
5
|
+
selector?: string;
|
|
6
|
+
method?: string;
|
|
7
|
+
arguments?: unknown[];
|
|
8
|
+
};
|
|
9
|
+
export declare function toStagehandDescriptor(pageRef: string, action: StagehandObserveAction, page: Page, pageSignature?: string): Promise<{
|
|
10
|
+
pageRef: string;
|
|
11
|
+
kind: string | undefined;
|
|
12
|
+
label: string;
|
|
13
|
+
displayLabel: string | undefined;
|
|
14
|
+
placeholder: string | undefined;
|
|
15
|
+
inputName: string | undefined;
|
|
16
|
+
inputType: string | undefined;
|
|
17
|
+
autocomplete: string | undefined;
|
|
18
|
+
validation: undefined;
|
|
19
|
+
capability: "actionable" | "informational";
|
|
20
|
+
lifecycle: "live";
|
|
21
|
+
availability: import("../runtime-state.js").TargetAvailabilityState;
|
|
22
|
+
allowedActions: import("../runtime-state.js").TargetAllowedAction[];
|
|
23
|
+
controlFamily: import("../runtime-state.js").TargetControlFamily | undefined;
|
|
24
|
+
acceptancePolicy: import("../runtime-state.js").TargetAcceptancePolicy | undefined;
|
|
25
|
+
framePath: string[] | undefined;
|
|
26
|
+
semantics: {
|
|
27
|
+
name: string;
|
|
28
|
+
role: string | undefined;
|
|
29
|
+
states: Record<string, string | number | boolean> | undefined;
|
|
30
|
+
source: "stagehand";
|
|
31
|
+
};
|
|
32
|
+
locatorCandidates: {
|
|
33
|
+
strategy: "css" | "xpath";
|
|
34
|
+
value: string;
|
|
35
|
+
scope: "root";
|
|
36
|
+
}[];
|
|
37
|
+
stagehandAction: StagehandObserveAction;
|
|
38
|
+
createdAt: number;
|
|
39
|
+
pageSignature: string | undefined;
|
|
40
|
+
domSignature: string | undefined;
|
|
41
|
+
}>;
|
|
42
|
+
export declare const __testStagehandDescriptor: {
|
|
43
|
+
toStagehandDescriptor: typeof toStagehandDescriptor;
|
|
44
|
+
normalizeStagehandSelector: typeof normalizeStagehandSelector;
|
|
45
|
+
readStagehandLocatorSnapshot: typeof readStagehandLocatorSnapshot;
|
|
46
|
+
};
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=observe-stagehand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"observe-stagehand.d.ts","sourceRoot":"","sources":["../../src/commands/observe-stagehand.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAQ5C,OAAO,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAElG,KAAK,sBAAsB,GAAG;IAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB,CAAC;AAgBF,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,IAAI,EACV,aAAa,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8FvB;AAED,eAAO,MAAM,yBAAyB;;;;CAIrC,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { inferAcceptancePolicyFromFacts, inferAllowedActionsFromFacts, inferAvailabilityFromFacts, inferControlFamilyFromFacts, } from '../control-semantics.js';
|
|
2
|
+
import { buildLocator, resolveLocatorRoot } from './action-fallbacks.js';
|
|
3
|
+
import { normalizeStagehandSelector, readStagehandLocatorSnapshot } from './observe-inventory.js';
|
|
4
|
+
function normalizeStagehandLiveValue(value) {
|
|
5
|
+
const normalized = value?.replace(/\s+/g, ' ').trim();
|
|
6
|
+
if (!normalized || normalized.length > 80) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return normalized;
|
|
10
|
+
}
|
|
11
|
+
function stagehandLabelIncludesValue(label, value) {
|
|
12
|
+
const normalizedLabel = label.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
13
|
+
const normalizedValue = value.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
14
|
+
return Boolean(normalizedValue) && normalizedLabel.includes(normalizedValue);
|
|
15
|
+
}
|
|
16
|
+
export async function toStagehandDescriptor(pageRef, action, page, pageSignature) {
|
|
17
|
+
const normalizedSelector = normalizeStagehandSelector(typeof action.selector === 'string' ? action.selector.trim() : '');
|
|
18
|
+
const selector = normalizedSelector.selector;
|
|
19
|
+
const locatorCandidates = selector
|
|
20
|
+
? [
|
|
21
|
+
{
|
|
22
|
+
strategy: selector.startsWith('xpath=') ? 'xpath' : 'css',
|
|
23
|
+
value: selector,
|
|
24
|
+
scope: 'root',
|
|
25
|
+
},
|
|
26
|
+
]
|
|
27
|
+
: [];
|
|
28
|
+
const stagehandLocator = selector
|
|
29
|
+
? buildLocator(resolveLocatorRoot(page, normalizedSelector.framePath), locatorCandidates[0])
|
|
30
|
+
: null;
|
|
31
|
+
const { domSignature, domFacts } = stagehandLocator
|
|
32
|
+
? await readStagehandLocatorSnapshot(stagehandLocator).catch(() => ({
|
|
33
|
+
domSignature: null,
|
|
34
|
+
domFacts: null,
|
|
35
|
+
}))
|
|
36
|
+
: {
|
|
37
|
+
domSignature: null,
|
|
38
|
+
domFacts: null,
|
|
39
|
+
};
|
|
40
|
+
const method = (action.method ?? '').trim().toLowerCase();
|
|
41
|
+
const shadowOrUnsupported = method === 'not-supported' || /shadow dom|inside a shadow/i.test(action.description ?? '');
|
|
42
|
+
const facts = {
|
|
43
|
+
kind: domFacts?.kind ?? action.method,
|
|
44
|
+
role: domFacts?.role,
|
|
45
|
+
label: action.description ?? action.method,
|
|
46
|
+
placeholder: domFacts?.placeholder,
|
|
47
|
+
inputName: domFacts?.inputName,
|
|
48
|
+
inputType: domFacts?.inputType,
|
|
49
|
+
autocomplete: domFacts?.autocomplete,
|
|
50
|
+
text: action.description ?? action.method,
|
|
51
|
+
states: domFacts?.states,
|
|
52
|
+
legacyMethod: method,
|
|
53
|
+
};
|
|
54
|
+
const allowedActions = inferAllowedActionsFromFacts(facts);
|
|
55
|
+
const acceptancePolicy = inferAcceptancePolicyFromFacts(facts, allowedActions);
|
|
56
|
+
const controlFamily = inferControlFamilyFromFacts(facts, allowedActions);
|
|
57
|
+
const liveValue = normalizeStagehandLiveValue(domFacts?.currentValue) ??
|
|
58
|
+
normalizeStagehandLiveValue(domFacts?.value) ??
|
|
59
|
+
normalizeStagehandLiveValue(domFacts?.text);
|
|
60
|
+
const baseLabel = action.description ?? action.method ?? 'observed target';
|
|
61
|
+
const displayLabel = liveValue && !stagehandLabelIncludesValue(baseLabel, liveValue)
|
|
62
|
+
? `${baseLabel} — ${liveValue}`
|
|
63
|
+
: undefined;
|
|
64
|
+
const actionable = !shadowOrUnsupported && locatorCandidates.length > 0 && allowedActions.length > 0;
|
|
65
|
+
const availability = inferAvailabilityFromFacts(domFacts?.states, undefined, {
|
|
66
|
+
readonlyInteractive: controlFamily === 'select' ||
|
|
67
|
+
controlFamily === 'datepicker' ||
|
|
68
|
+
acceptancePolicy === 'selection' ||
|
|
69
|
+
acceptancePolicy === 'date-selection',
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
pageRef,
|
|
73
|
+
kind: domFacts?.kind ?? action.method,
|
|
74
|
+
label: baseLabel,
|
|
75
|
+
displayLabel,
|
|
76
|
+
placeholder: domFacts?.placeholder,
|
|
77
|
+
inputName: domFacts?.inputName,
|
|
78
|
+
inputType: domFacts?.inputType,
|
|
79
|
+
autocomplete: domFacts?.autocomplete,
|
|
80
|
+
validation: undefined,
|
|
81
|
+
capability: actionable ? 'actionable' : 'informational',
|
|
82
|
+
lifecycle: 'live',
|
|
83
|
+
availability,
|
|
84
|
+
allowedActions,
|
|
85
|
+
controlFamily,
|
|
86
|
+
acceptancePolicy,
|
|
87
|
+
framePath: normalizedSelector.framePath,
|
|
88
|
+
semantics: {
|
|
89
|
+
name: action.description ?? action.method ?? 'observed target',
|
|
90
|
+
role: domFacts?.role,
|
|
91
|
+
states: domFacts?.states,
|
|
92
|
+
source: 'stagehand',
|
|
93
|
+
},
|
|
94
|
+
locatorCandidates,
|
|
95
|
+
stagehandAction: action,
|
|
96
|
+
createdAt: Date.now(),
|
|
97
|
+
pageSignature,
|
|
98
|
+
domSignature: domSignature ?? undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
export const __testStagehandDescriptor = {
|
|
102
|
+
toStagehandDescriptor,
|
|
103
|
+
normalizeStagehandSelector,
|
|
104
|
+
readStagehandLocatorSnapshot,
|
|
105
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LocatorCandidate, SurfaceDescriptor, TargetContext, TargetDescriptor } from '../runtime-state.js';
|
|
2
|
+
import type { DomObservedTarget } from './observe-inventory.js';
|
|
3
|
+
export declare function selectScopesForOutput(scopes: ReadonlyArray<SurfaceDescriptor>, targets: ReadonlyArray<Pick<TargetDescriptor, 'surfaceRef' | 'allowedActions' | 'acceptancePolicy'>>, preferredScopeRefs?: ReadonlySet<string>): SurfaceDescriptor[];
|
|
4
|
+
export declare function buildSurfaceRef(target: DomObservedTarget): string | undefined;
|
|
5
|
+
export declare function surfaceReplacementKey(surface: Pick<SurfaceDescriptor, 'pageRef' | 'pageSignature' | 'framePath' | 'kind' | 'label'>): string;
|
|
6
|
+
export declare function summarizeContext(context: TargetContext | undefined): string | undefined;
|
|
7
|
+
export declare function pushUniqueLocatorCandidate(acc: LocatorCandidate[], candidate: LocatorCandidate | undefined): void;
|
|
8
|
+
export declare function collectSurfaceDescriptors(pageRef: string, targets: ReadonlyArray<DomObservedTarget>): Omit<SurfaceDescriptor, "ref">[];
|
|
9
|
+
//# sourceMappingURL=observe-surfaces.d.ts.map
|
|
@@ -0,0 +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"}
|