@eidra-umain/greenlight 0.1.0
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 +391 -0
- package/dist/browser/browser.d.ts +24 -0
- package/dist/browser/browser.d.ts.map +1 -0
- package/dist/browser/browser.js +44 -0
- package/dist/browser/browser.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +140 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/run.d.ts +9 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli/run.js +277 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +107 -0
- package/dist/config.js.map +1 -0
- package/dist/globals.d.ts +21 -0
- package/dist/globals.d.ts.map +1 -0
- package/dist/globals.js +24 -0
- package/dist/globals.js.map +1 -0
- package/dist/parser/loader.d.ts +7 -0
- package/dist/parser/loader.d.ts.map +1 -0
- package/dist/parser/loader.js +43 -0
- package/dist/parser/loader.js.map +1 -0
- package/dist/parser/schema.d.ts +42 -0
- package/dist/parser/schema.d.ts.map +1 -0
- package/dist/parser/schema.js +33 -0
- package/dist/parser/schema.js.map +1 -0
- package/dist/parser/steps.d.ts +13 -0
- package/dist/parser/steps.d.ts.map +1 -0
- package/dist/parser/steps.js +44 -0
- package/dist/parser/steps.js.map +1 -0
- package/dist/parser/variables.d.ts +18 -0
- package/dist/parser/variables.d.ts.map +1 -0
- package/dist/parser/variables.js +44 -0
- package/dist/parser/variables.js.map +1 -0
- package/dist/pilot/a11y-parser.d.ts +26 -0
- package/dist/pilot/a11y-parser.d.ts.map +1 -0
- package/dist/pilot/a11y-parser.js +195 -0
- package/dist/pilot/a11y-parser.js.map +1 -0
- package/dist/pilot/assertions.d.ts +30 -0
- package/dist/pilot/assertions.d.ts.map +1 -0
- package/dist/pilot/assertions.js +219 -0
- package/dist/pilot/assertions.js.map +1 -0
- package/dist/pilot/checkbox.d.ts +12 -0
- package/dist/pilot/checkbox.d.ts.map +1 -0
- package/dist/pilot/checkbox.js +104 -0
- package/dist/pilot/checkbox.js.map +1 -0
- package/dist/pilot/executor.d.ts +17 -0
- package/dist/pilot/executor.d.ts.map +1 -0
- package/dist/pilot/executor.js +462 -0
- package/dist/pilot/executor.js.map +1 -0
- package/dist/pilot/form-fields.d.ts +34 -0
- package/dist/pilot/form-fields.d.ts.map +1 -0
- package/dist/pilot/form-fields.js +139 -0
- package/dist/pilot/form-fields.js.map +1 -0
- package/dist/pilot/llm.d.ts +49 -0
- package/dist/pilot/llm.d.ts.map +1 -0
- package/dist/pilot/llm.js +188 -0
- package/dist/pilot/llm.js.map +1 -0
- package/dist/pilot/locator.d.ts +58 -0
- package/dist/pilot/locator.d.ts.map +1 -0
- package/dist/pilot/locator.js +248 -0
- package/dist/pilot/locator.js.map +1 -0
- package/dist/pilot/message-builder.d.ts +31 -0
- package/dist/pilot/message-builder.d.ts.map +1 -0
- package/dist/pilot/message-builder.js +112 -0
- package/dist/pilot/message-builder.js.map +1 -0
- package/dist/pilot/network.d.ts +23 -0
- package/dist/pilot/network.d.ts.map +1 -0
- package/dist/pilot/network.js +92 -0
- package/dist/pilot/network.js.map +1 -0
- package/dist/pilot/pilot.d.ts +27 -0
- package/dist/pilot/pilot.d.ts.map +1 -0
- package/dist/pilot/pilot.js +249 -0
- package/dist/pilot/pilot.js.map +1 -0
- package/dist/pilot/prompts.d.ts +8 -0
- package/dist/pilot/prompts.d.ts.map +1 -0
- package/dist/pilot/prompts.js +163 -0
- package/dist/pilot/prompts.js.map +1 -0
- package/dist/pilot/providers/anthropic.d.ts +6 -0
- package/dist/pilot/providers/anthropic.d.ts.map +1 -0
- package/dist/pilot/providers/anthropic.js +45 -0
- package/dist/pilot/providers/anthropic.js.map +1 -0
- package/dist/pilot/providers/gemini.d.ts +6 -0
- package/dist/pilot/providers/gemini.d.ts.map +1 -0
- package/dist/pilot/providers/gemini.js +55 -0
- package/dist/pilot/providers/gemini.js.map +1 -0
- package/dist/pilot/providers/index.d.ts +10 -0
- package/dist/pilot/providers/index.d.ts.map +1 -0
- package/dist/pilot/providers/index.js +25 -0
- package/dist/pilot/providers/index.js.map +1 -0
- package/dist/pilot/providers/openai-compatible.d.ts +7 -0
- package/dist/pilot/providers/openai-compatible.d.ts.map +1 -0
- package/dist/pilot/providers/openai-compatible.js +34 -0
- package/dist/pilot/providers/openai-compatible.js.map +1 -0
- package/dist/pilot/providers/types.d.ts +12 -0
- package/dist/pilot/providers/types.d.ts.map +1 -0
- package/dist/pilot/providers/types.js +2 -0
- package/dist/pilot/providers/types.js.map +1 -0
- package/dist/pilot/response-parser.d.ts +31 -0
- package/dist/pilot/response-parser.d.ts.map +1 -0
- package/dist/pilot/response-parser.js +188 -0
- package/dist/pilot/response-parser.js.map +1 -0
- package/dist/pilot/state.d.ts +19 -0
- package/dist/pilot/state.d.ts.map +1 -0
- package/dist/pilot/state.js +67 -0
- package/dist/pilot/state.js.map +1 -0
- package/dist/pilot/trace.d.ts +16 -0
- package/dist/pilot/trace.d.ts.map +1 -0
- package/dist/pilot/trace.js +117 -0
- package/dist/pilot/trace.js.map +1 -0
- package/dist/planner/hasher.d.ts +14 -0
- package/dist/planner/hasher.d.ts.map +1 -0
- package/dist/planner/hasher.js +21 -0
- package/dist/planner/hasher.js.map +1 -0
- package/dist/planner/plan-generator.d.ts +23 -0
- package/dist/planner/plan-generator.d.ts.map +1 -0
- package/dist/planner/plan-generator.js +56 -0
- package/dist/planner/plan-generator.js.map +1 -0
- package/dist/planner/plan-runner.d.ts +16 -0
- package/dist/planner/plan-runner.d.ts.map +1 -0
- package/dist/planner/plan-runner.js +375 -0
- package/dist/planner/plan-runner.js.map +1 -0
- package/dist/planner/plan-store.d.ts +22 -0
- package/dist/planner/plan-store.d.ts.map +1 -0
- package/dist/planner/plan-store.js +71 -0
- package/dist/planner/plan-store.js.map +1 -0
- package/dist/planner/plan-types.d.ts +64 -0
- package/dist/planner/plan-types.d.ts.map +1 -0
- package/dist/planner/plan-types.js +7 -0
- package/dist/planner/plan-types.js.map +1 -0
- package/dist/reporter/types.d.ts +130 -0
- package/dist/reporter/types.d.ts.map +1 -0
- package/dist/reporter/types.js +5 -0
- package/dist/reporter/types.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action executor — translates LLM Action objects into Playwright browser calls.
|
|
3
|
+
*/
|
|
4
|
+
import { globals } from "../globals.js";
|
|
5
|
+
import { resolveLocator, resolveActionTarget, extractSelectorInfo, } from "./locator.js";
|
|
6
|
+
import { checkCheckbox } from "./checkbox.js";
|
|
7
|
+
import { executeAssertion } from "./assertions.js";
|
|
8
|
+
/**
|
|
9
|
+
* Run an action that might trigger navigation.
|
|
10
|
+
* Listens for a 'framenavigated' event during the action — if one fires,
|
|
11
|
+
* waits for the new page to reach domcontentloaded. If no navigation
|
|
12
|
+
* happens, returns immediately with no delay.
|
|
13
|
+
*/
|
|
14
|
+
export async function runWithNavigationHandling(page, action) {
|
|
15
|
+
// Track whether the action triggers a navigation via event callback.
|
|
16
|
+
// The flag is mutated asynchronously by the event handler.
|
|
17
|
+
const state = { navigated: false };
|
|
18
|
+
const onNav = () => {
|
|
19
|
+
state.navigated = true;
|
|
20
|
+
};
|
|
21
|
+
page.on("framenavigated", onNav);
|
|
22
|
+
try {
|
|
23
|
+
await action();
|
|
24
|
+
if (state.navigated) {
|
|
25
|
+
await page.waitForLoadState("domcontentloaded");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
page.off("framenavigated", onNav);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Search the a11y tree for a node whose name contains a number and
|
|
34
|
+
* matches any of the given keywords. Used as a fallback when the LLM
|
|
35
|
+
* returns a remember action without specifying a target element.
|
|
36
|
+
*/
|
|
37
|
+
function findValueInTree(nodes, keywords) {
|
|
38
|
+
const lowerKeywords = keywords.map((k) => k.toLowerCase());
|
|
39
|
+
let bestMatch = "";
|
|
40
|
+
function walk(nodeList) {
|
|
41
|
+
for (const node of nodeList) {
|
|
42
|
+
const name = node.name.toLowerCase();
|
|
43
|
+
// Check if the name contains a number
|
|
44
|
+
if (/\d/.test(name)) {
|
|
45
|
+
// Check if any keyword matches
|
|
46
|
+
const matches = lowerKeywords.some((kw) => name.includes(kw));
|
|
47
|
+
if (matches) {
|
|
48
|
+
// Prefer shorter, more specific matches
|
|
49
|
+
if (!bestMatch || node.name.length < bestMatch.length) {
|
|
50
|
+
bestMatch = node.name;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (node.children)
|
|
55
|
+
walk(node.children);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
walk(nodes);
|
|
59
|
+
return bestMatch;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Execute a single Action against the browser page.
|
|
63
|
+
*/
|
|
64
|
+
export async function executeAction(page, action, a11yTree, _valueStore) {
|
|
65
|
+
const start = performance.now();
|
|
66
|
+
let rememberedValue;
|
|
67
|
+
let resolvedSelector;
|
|
68
|
+
try {
|
|
69
|
+
switch (action.action) {
|
|
70
|
+
case "click": {
|
|
71
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
72
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
73
|
+
await runWithNavigationHandling(page, () => locator.click());
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "check": {
|
|
77
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
78
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
79
|
+
await checkCheckbox(page, locator, true);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
case "uncheck": {
|
|
83
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
84
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
85
|
+
await checkCheckbox(page, locator, false);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
case "type": {
|
|
89
|
+
if (!action.value) {
|
|
90
|
+
throw new Error("type action requires a value");
|
|
91
|
+
}
|
|
92
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
93
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
94
|
+
// Click to focus, clear existing value, then type character by
|
|
95
|
+
// character. pressSequentially dispatches real keydown/keypress/
|
|
96
|
+
// keyup/input events per keystroke, which is required for
|
|
97
|
+
// frameworks that rely on JS input events (React onChange, custom
|
|
98
|
+
// validation, etc.). fill() bypasses these.
|
|
99
|
+
await locator.click();
|
|
100
|
+
await locator.fill("");
|
|
101
|
+
await locator.pressSequentially(action.value, { delay: 30 });
|
|
102
|
+
// Verify the value landed correctly. Async UI (search dropdowns,
|
|
103
|
+
// autocomplete overlays) can steal focus or trigger re-renders
|
|
104
|
+
// that swallow the last keystrokes. If the value drifted, re-focus
|
|
105
|
+
// and type the missing suffix.
|
|
106
|
+
const actual = await locator.inputValue().catch(() => "");
|
|
107
|
+
if (actual !== action.value) {
|
|
108
|
+
if (globals.debug) {
|
|
109
|
+
console.log(` [type] Value drifted: got "${actual}", expected "${action.value}" — correcting`);
|
|
110
|
+
}
|
|
111
|
+
await locator.click();
|
|
112
|
+
if (action.value.startsWith(actual)) {
|
|
113
|
+
// Only the tail is missing — append it
|
|
114
|
+
await locator.pressSequentially(action.value.slice(actual.length), { delay: 30 });
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
// Value is garbled — clear and retype
|
|
118
|
+
await locator.fill("");
|
|
119
|
+
await locator.pressSequentially(action.value, { delay: 30 });
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
break;
|
|
123
|
+
}
|
|
124
|
+
case "select": {
|
|
125
|
+
if (!action.value) {
|
|
126
|
+
throw new Error("select action requires a value");
|
|
127
|
+
}
|
|
128
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
129
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
130
|
+
// Try native <select> first; if the element is a custom dropdown
|
|
131
|
+
// (button/div with aria-haspopup), click to open it then click
|
|
132
|
+
// the option by text.
|
|
133
|
+
const tagName = await locator.evaluate((el) => el.tagName).catch(() => "");
|
|
134
|
+
if (tagName === "SELECT") {
|
|
135
|
+
await locator.selectOption({ label: action.value });
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
if (globals.debug) {
|
|
139
|
+
console.log(` [select] Element is not a <select>, using click-to-open strategy`);
|
|
140
|
+
}
|
|
141
|
+
// Click to open the dropdown
|
|
142
|
+
await locator.click();
|
|
143
|
+
// After clicking the trigger, wait a moment for the popup
|
|
144
|
+
// to render, then find the option.
|
|
145
|
+
await page.waitForTimeout(500);
|
|
146
|
+
if (globals.debug) {
|
|
147
|
+
try {
|
|
148
|
+
const menuId = await locator.evaluate((el) => el.getAttribute("aria-controls") ??
|
|
149
|
+
el.getAttribute("data-controls") ?? "");
|
|
150
|
+
console.log(` [select] Trigger aria-controls="${menuId}"`);
|
|
151
|
+
// Dump all potential popup containers on the page
|
|
152
|
+
const selectors = [
|
|
153
|
+
"[role='menu']", "[role='listbox']",
|
|
154
|
+
"[data-part='content']", "[data-state='open']",
|
|
155
|
+
"[data-scope='menu']", "[aria-haspopup]",
|
|
156
|
+
];
|
|
157
|
+
for (const sel of selectors) {
|
|
158
|
+
const count = await page.locator(sel).count().catch(() => 0);
|
|
159
|
+
if (count > 0) {
|
|
160
|
+
const visible = await page.locator(sel).first().isVisible().catch(() => false);
|
|
161
|
+
console.log(` [select] ${sel}: ${String(count)} found, first visible=${String(visible)}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
catch { /* skip */ }
|
|
166
|
+
}
|
|
167
|
+
// Strategy 1: Find menu container via aria-controls and
|
|
168
|
+
// search within it (safe — scoped to the popup).
|
|
169
|
+
let clicked = false;
|
|
170
|
+
try {
|
|
171
|
+
const menuId = await locator.evaluate((el) => el.getAttribute("aria-controls") ??
|
|
172
|
+
el.getAttribute("data-controls") ?? "");
|
|
173
|
+
if (menuId) {
|
|
174
|
+
const menu = page.locator(`#${CSS.escape(menuId)}`);
|
|
175
|
+
if (await menu.isVisible().catch(() => false)) {
|
|
176
|
+
if (globals.debug) {
|
|
177
|
+
console.log(` [select] Found menu container: #${menuId}`);
|
|
178
|
+
}
|
|
179
|
+
const opt = menu.getByText(action.value, { exact: true });
|
|
180
|
+
if (await opt.first().isVisible().catch(() => false)) {
|
|
181
|
+
await opt.first().click();
|
|
182
|
+
clicked = true;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
// Try loose match within menu
|
|
186
|
+
const loose = menu.getByText(action.value);
|
|
187
|
+
if (await loose.first().isVisible().catch(() => false)) {
|
|
188
|
+
await loose.first().click();
|
|
189
|
+
clicked = true;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
catch { /* try next strategy */ }
|
|
196
|
+
// Strategy 2: Search all visible popup-like containers
|
|
197
|
+
if (!clicked) {
|
|
198
|
+
const popupSelectors = [
|
|
199
|
+
"[role='menu']",
|
|
200
|
+
"[role='listbox']",
|
|
201
|
+
"[data-part='content']",
|
|
202
|
+
"[data-state='open'][data-scope='menu']",
|
|
203
|
+
"[data-radix-popper-content-wrapper]",
|
|
204
|
+
];
|
|
205
|
+
for (const sel of popupSelectors) {
|
|
206
|
+
try {
|
|
207
|
+
const containers = page.locator(sel);
|
|
208
|
+
const count = await containers.count();
|
|
209
|
+
for (let i = 0; i < count && !clicked; i++) {
|
|
210
|
+
const container = containers.nth(i);
|
|
211
|
+
if (!await container.isVisible().catch(() => false))
|
|
212
|
+
continue;
|
|
213
|
+
const opt = container.getByText(action.value, { exact: true });
|
|
214
|
+
if (await opt.first().isVisible().catch(() => false)) {
|
|
215
|
+
if (globals.debug) {
|
|
216
|
+
console.log(` [select] Found option in ${sel} container`);
|
|
217
|
+
}
|
|
218
|
+
await opt.first().click();
|
|
219
|
+
clicked = true;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
catch { /* try next */ }
|
|
224
|
+
if (clicked)
|
|
225
|
+
break;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
// Strategy 3: Role-based page-wide (menuitem/option only)
|
|
229
|
+
if (!clicked) {
|
|
230
|
+
const roleCandidates = [
|
|
231
|
+
page.getByRole("menuitem", { name: action.value }),
|
|
232
|
+
page.getByRole("menuitemradio", { name: action.value }),
|
|
233
|
+
page.getByRole("option", { name: action.value }),
|
|
234
|
+
];
|
|
235
|
+
for (const opt of roleCandidates) {
|
|
236
|
+
try {
|
|
237
|
+
if (await opt.first().isVisible().catch(() => false)) {
|
|
238
|
+
if (globals.debug) {
|
|
239
|
+
console.log(` [select] Found option via page-wide role search`);
|
|
240
|
+
}
|
|
241
|
+
await opt.first().click();
|
|
242
|
+
clicked = true;
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
catch { /* try next */ }
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (!clicked) {
|
|
250
|
+
throw new Error(`Could not find option "${action.value}" in custom dropdown`);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
case "autocomplete": {
|
|
256
|
+
if (!action.value) {
|
|
257
|
+
throw new Error("autocomplete action requires a value");
|
|
258
|
+
}
|
|
259
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
260
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
261
|
+
if (globals.debug) {
|
|
262
|
+
console.log(` [autocomplete] Typing "${action.value}" into field (target: ${action.ref ?? action.text ?? "unknown"})`);
|
|
263
|
+
if (action.option) {
|
|
264
|
+
console.log(` [autocomplete] Will select specific option: "${action.option}"`);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
console.log(` [autocomplete] Will select first suggestion`);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Click to focus, then type character by character to trigger autocomplete
|
|
271
|
+
await locator.click();
|
|
272
|
+
await locator.fill("");
|
|
273
|
+
await locator.pressSequentially(action.value, { delay: 50 });
|
|
274
|
+
if (globals.debug) {
|
|
275
|
+
console.log(` [autocomplete] Typed "${action.value}", waiting for suggestions...`);
|
|
276
|
+
}
|
|
277
|
+
// Wait for autocomplete suggestions to appear.
|
|
278
|
+
// Try multiple common patterns: role=option, role=listbox children,
|
|
279
|
+
// generic dropdown/suggestion containers.
|
|
280
|
+
const suggestionPatterns = [
|
|
281
|
+
{ name: "role=option", locator: page.locator("[role='option']") },
|
|
282
|
+
{ name: "role=listbox children", locator: page.locator("[role='listbox'] > *") },
|
|
283
|
+
{ name: "CSS class patterns", locator: page.locator(".autocomplete-results > *, .suggestions > *, .dropdown-menu > *") },
|
|
284
|
+
];
|
|
285
|
+
let suggestions;
|
|
286
|
+
let matchedPattern;
|
|
287
|
+
for (const pattern of suggestionPatterns) {
|
|
288
|
+
try {
|
|
289
|
+
await pattern.locator.first().waitFor({ state: "visible", timeout: 5000 });
|
|
290
|
+
suggestions = pattern.locator;
|
|
291
|
+
matchedPattern = pattern.name;
|
|
292
|
+
break;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
if (globals.debug) {
|
|
296
|
+
console.log(` [autocomplete] Pattern "${pattern.name}" — no match`);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if (!suggestions) {
|
|
301
|
+
throw new Error("Autocomplete suggestions did not appear after typing");
|
|
302
|
+
}
|
|
303
|
+
const suggestionCount = await suggestions.count();
|
|
304
|
+
if (globals.debug) {
|
|
305
|
+
console.log(` [autocomplete] Found ${String(suggestionCount)} suggestions via "${matchedPattern ?? "unknown"}"`);
|
|
306
|
+
// Log first few suggestion texts
|
|
307
|
+
const previewCount = Math.min(suggestionCount, 5);
|
|
308
|
+
for (let i = 0; i < previewCount; i++) {
|
|
309
|
+
try {
|
|
310
|
+
const text = await suggestions.nth(i).textContent();
|
|
311
|
+
console.log(` [autocomplete] ${String(i + 1)}. ${text?.trim() ?? "(empty)"}`);
|
|
312
|
+
}
|
|
313
|
+
catch { /* skip */ }
|
|
314
|
+
}
|
|
315
|
+
if (suggestionCount > 5) {
|
|
316
|
+
console.log(` [autocomplete] ... and ${String(suggestionCount - 5)} more`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
// Select the target option
|
|
320
|
+
if (action.option) {
|
|
321
|
+
// Find by matching text
|
|
322
|
+
const optionCandidates = [
|
|
323
|
+
{ name: "filter by hasText", locator: suggestions.filter({ hasText: action.option }).first() },
|
|
324
|
+
{ name: "getByRole option", locator: page.getByRole("option", { name: action.option }) },
|
|
325
|
+
{ name: "getByText exact", locator: page.getByText(action.option, { exact: true }) },
|
|
326
|
+
{ name: "getByText loose", locator: page.getByText(action.option) },
|
|
327
|
+
];
|
|
328
|
+
let clicked = false;
|
|
329
|
+
for (const candidate of optionCandidates) {
|
|
330
|
+
try {
|
|
331
|
+
if (await candidate.locator.isVisible()) {
|
|
332
|
+
if (globals.debug) {
|
|
333
|
+
console.log(` [autocomplete] Clicking option "${action.option}" via ${candidate.name}`);
|
|
334
|
+
}
|
|
335
|
+
await candidate.locator.click();
|
|
336
|
+
clicked = true;
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch {
|
|
341
|
+
if (globals.debug) {
|
|
342
|
+
console.log(` [autocomplete] Option strategy "${candidate.name}" — no match`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (!clicked) {
|
|
347
|
+
throw new Error(`Autocomplete option "${action.option}" not found in suggestions`);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else {
|
|
351
|
+
// Click the first visible suggestion
|
|
352
|
+
if (globals.debug) {
|
|
353
|
+
const firstText = await suggestions.first().textContent();
|
|
354
|
+
console.log(` [autocomplete] Clicking first suggestion: "${firstText?.trim() ?? "(empty)"}"`);
|
|
355
|
+
}
|
|
356
|
+
await suggestions.first().click();
|
|
357
|
+
}
|
|
358
|
+
if (globals.debug) {
|
|
359
|
+
console.log(` [autocomplete] Done`);
|
|
360
|
+
}
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
case "scroll": {
|
|
364
|
+
if (action.ref) {
|
|
365
|
+
const locator = await resolveLocator(page, a11yTree, action.ref);
|
|
366
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
367
|
+
await locator.scrollIntoViewIfNeeded();
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
const delta = action.value === "up" ? -500 : 500;
|
|
371
|
+
await page.mouse.wheel(0, delta);
|
|
372
|
+
}
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
case "press": {
|
|
376
|
+
if (!action.value) {
|
|
377
|
+
throw new Error("press action requires a value");
|
|
378
|
+
}
|
|
379
|
+
const key = action.value;
|
|
380
|
+
await runWithNavigationHandling(page, () => page.keyboard.press(key));
|
|
381
|
+
break;
|
|
382
|
+
}
|
|
383
|
+
case "navigate": {
|
|
384
|
+
if (!action.value) {
|
|
385
|
+
throw new Error("navigate action requires a value");
|
|
386
|
+
}
|
|
387
|
+
const url = action.value.startsWith("/")
|
|
388
|
+
? new URL(action.value, page.url()).href
|
|
389
|
+
: action.value;
|
|
390
|
+
await page.goto(url, { waitUntil: "domcontentloaded" });
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
case "wait": {
|
|
394
|
+
if (!action.value) {
|
|
395
|
+
throw new Error("wait action requires a value");
|
|
396
|
+
}
|
|
397
|
+
// Wait for text to appear on the page
|
|
398
|
+
await page.getByText(action.value).waitFor({ state: "visible" });
|
|
399
|
+
break;
|
|
400
|
+
}
|
|
401
|
+
case "remember": {
|
|
402
|
+
let capturedText;
|
|
403
|
+
if (action.ref || action.text) {
|
|
404
|
+
const locator = await resolveActionTarget(page, action, a11yTree);
|
|
405
|
+
resolvedSelector = await extractSelectorInfo(page, action, a11yTree, locator);
|
|
406
|
+
capturedText = (await locator.textContent() ?? "").trim();
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
// LLM didn't specify a target element. Search the a11y tree
|
|
410
|
+
// for nodes whose text contains a number and matches keywords
|
|
411
|
+
// from the step description (the variable name or step text).
|
|
412
|
+
if (globals.debug) {
|
|
413
|
+
console.log(` [remember] No ref/text target, searching a11y tree for matching value`);
|
|
414
|
+
}
|
|
415
|
+
const keywords = (action.rememberAs ?? "")
|
|
416
|
+
.replace(/_/g, " ")
|
|
417
|
+
.split(" ")
|
|
418
|
+
.filter((w) => w.length > 2);
|
|
419
|
+
capturedText = findValueInTree(a11yTree, keywords);
|
|
420
|
+
if (!capturedText) {
|
|
421
|
+
throw new Error(`remember action: LLM returned no element target and could not find a matching value in the page`);
|
|
422
|
+
}
|
|
423
|
+
if (globals.debug) {
|
|
424
|
+
console.log(` [remember] Found by keyword search: "${capturedText}"`);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (globals.debug) {
|
|
428
|
+
const preview = capturedText.length > 80
|
|
429
|
+
? capturedText.slice(0, 80) + "..."
|
|
430
|
+
: capturedText;
|
|
431
|
+
console.log(` [remember] Captured "${preview}" as "${action.rememberAs ?? ""}"`);
|
|
432
|
+
}
|
|
433
|
+
rememberedValue = capturedText;
|
|
434
|
+
break;
|
|
435
|
+
}
|
|
436
|
+
case "assert": {
|
|
437
|
+
if (!action.assertion) {
|
|
438
|
+
throw new Error("assert action requires an assertion");
|
|
439
|
+
}
|
|
440
|
+
await executeAssertion(page, action, a11yTree);
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
default:
|
|
444
|
+
throw new Error(`Unknown action: ${action.action}`);
|
|
445
|
+
}
|
|
446
|
+
return {
|
|
447
|
+
success: true,
|
|
448
|
+
duration: performance.now() - start,
|
|
449
|
+
resolvedSelector,
|
|
450
|
+
rememberedValue,
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
catch (err) {
|
|
454
|
+
return {
|
|
455
|
+
success: false,
|
|
456
|
+
duration: performance.now() - start,
|
|
457
|
+
error: err instanceof Error ? err.message : String(err),
|
|
458
|
+
resolvedSelector,
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
//# sourceMappingURL=executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../../src/pilot/executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Form field capture and formatting for Playwright pages.
|
|
3
|
+
*/
|
|
4
|
+
import type { Page } from "playwright";
|
|
5
|
+
/** Metadata about a single form field, extracted from the DOM. */
|
|
6
|
+
export interface FormFieldInfo {
|
|
7
|
+
/** The element ref from the a11y tree, if matched. */
|
|
8
|
+
ref?: string;
|
|
9
|
+
/** The <label> text associated with this field. */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** The placeholder attribute value. */
|
|
12
|
+
placeholder?: string;
|
|
13
|
+
/** The input type (text, email, tel, number, url, etc.). */
|
|
14
|
+
inputType: string;
|
|
15
|
+
/** The tag name (input, textarea, select). */
|
|
16
|
+
tag: string;
|
|
17
|
+
/** Whether the field is required. */
|
|
18
|
+
required: boolean;
|
|
19
|
+
/** For select elements: the available option labels. */
|
|
20
|
+
options?: string[];
|
|
21
|
+
/** Whether this field is an autocomplete/typeahead/combobox that shows suggestions as you type. */
|
|
22
|
+
autocomplete?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Capture metadata about all visible form fields on the page.
|
|
26
|
+
* Extracts label, placeholder, input type, required status, and select options
|
|
27
|
+
* directly from the DOM — information not available in the a11y tree.
|
|
28
|
+
*/
|
|
29
|
+
export declare function captureFormFields(page: Page): Promise<FormFieldInfo[]>;
|
|
30
|
+
/**
|
|
31
|
+
* Format form field metadata as readable text for LLM consumption.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatFormFields(fields: FormFieldInfo[]): string;
|
|
34
|
+
//# sourceMappingURL=form-fields.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form-fields.d.ts","sourceRoot":"","sources":["../../src/pilot/form-fields.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEtC,kEAAkE;AAClE,MAAM,WAAW,aAAa;IAC7B,sDAAsD;IACtD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,4DAA4D;IAC5D,SAAS,EAAE,MAAM,CAAA;IACjB,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAA;IACX,qCAAqC;IACrC,QAAQ,EAAE,OAAO,CAAA;IACjB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;IAClB,mGAAmG;IACnG,YAAY,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAuH5E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,CAiBhE"}
|