zan-browser 1.3.37 → 2.0.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/dist/ai.d.ts +3 -16
- package/dist/ai.d.ts.map +1 -1
- package/dist/ai.js +101 -208
- package/dist/ai.js.map +1 -1
- package/dist/blacklist.d.ts +2 -0
- package/dist/blacklist.d.ts.map +1 -0
- package/dist/blacklist.js +115 -0
- package/dist/blacklist.js.map +1 -0
- package/dist/browser-provider.d.ts +81 -0
- package/dist/browser-provider.d.ts.map +1 -0
- package/dist/browser-provider.js +6 -0
- package/dist/browser-provider.js.map +1 -0
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +51 -60
- package/dist/browser.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptor.d.ts +3 -3
- package/dist/interceptor.d.ts.map +1 -1
- package/dist/interceptor.js +45 -19
- package/dist/interceptor.js.map +1 -1
- package/dist/navigator.d.ts +40 -0
- package/dist/navigator.d.ts.map +1 -0
- package/dist/navigator.js +507 -0
- package/dist/navigator.js.map +1 -0
- package/dist/observer.d.ts +23 -3
- package/dist/observer.d.ts.map +1 -1
- package/dist/observer.js +310 -270
- package/dist/observer.js.map +1 -1
- package/dist/perception.d.ts +42 -0
- package/dist/perception.d.ts.map +1 -0
- package/dist/perception.js +140 -0
- package/dist/perception.js.map +1 -0
- package/dist/providers/browserbase.d.ts +12 -0
- package/dist/providers/browserbase.d.ts.map +1 -0
- package/dist/providers/browserbase.js +226 -0
- package/dist/providers/browserbase.js.map +1 -0
- package/dist/providers/puppeteer-local.d.ts +5 -0
- package/dist/providers/puppeteer-local.d.ts.map +1 -0
- package/dist/providers/puppeteer-local.js +218 -0
- package/dist/providers/puppeteer-local.js.map +1 -0
- package/dist/session.d.ts +17 -23
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +112 -401
- package/dist/session.js.map +1 -1
- package/dist/types.d.ts +1 -32
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── Smart Navigator ──────────────────────────────────────────────────────────
|
|
3
|
+
// Replaces the dumb "goto → wait → check → give up" with intelligent navigation.
|
|
4
|
+
// Adopts patterns from: Notte (one action per step, re-observe), test-api (multi-value retry,
|
|
5
|
+
// autocomplete handling), and Anything API (cumulative context, early termination).
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.SmartNavigator = void 0;
|
|
8
|
+
const perception_1 = require("./perception");
|
|
9
|
+
// ─── Autocomplete selectors (from test-api) ──────────────────────────────────
|
|
10
|
+
const AUTOCOMPLETE_SELECTORS = [
|
|
11
|
+
'[class*="autocomplete"] li',
|
|
12
|
+
'[class*="autocomplete"] a',
|
|
13
|
+
'[class*="suggestion"] li',
|
|
14
|
+
'[class*="suggestion"] a',
|
|
15
|
+
'[class*="dropdown"] li a',
|
|
16
|
+
'[class*="search-result"] a',
|
|
17
|
+
'[class*="search-result"] li',
|
|
18
|
+
'[role="listbox"] [role="option"]',
|
|
19
|
+
'[role="listbox"] li',
|
|
20
|
+
'ul[class*="result"] li',
|
|
21
|
+
'ul[class*="result"] a',
|
|
22
|
+
".autocomplete-results a",
|
|
23
|
+
".tt-suggestion",
|
|
24
|
+
".ui-autocomplete li",
|
|
25
|
+
".search-suggestions a",
|
|
26
|
+
".pac-item",
|
|
27
|
+
];
|
|
28
|
+
// ─── SmartNavigator ───────────────────────────────────────────────────────────
|
|
29
|
+
class SmartNavigator {
|
|
30
|
+
page;
|
|
31
|
+
observer;
|
|
32
|
+
interceptor;
|
|
33
|
+
ai;
|
|
34
|
+
constructor(page, observer, interceptor, ai) {
|
|
35
|
+
this.page = page;
|
|
36
|
+
this.observer = observer;
|
|
37
|
+
this.interceptor = interceptor;
|
|
38
|
+
this.ai = ai;
|
|
39
|
+
}
|
|
40
|
+
// ─── Main entry point ─────────────────────────────────────────────────────────
|
|
41
|
+
async navigate(config) {
|
|
42
|
+
const strategy = config.strategy === "auto"
|
|
43
|
+
? this.inferStrategy(config)
|
|
44
|
+
: config.strategy;
|
|
45
|
+
const progress = config.onProgress ?? (() => { });
|
|
46
|
+
progress(`Strategy: ${strategy}`);
|
|
47
|
+
switch (strategy) {
|
|
48
|
+
case "load-capture":
|
|
49
|
+
return this.strategyLoadAndCapture(config);
|
|
50
|
+
case "search":
|
|
51
|
+
return this.strategySearchInteraction(config);
|
|
52
|
+
case "multi-step":
|
|
53
|
+
return this.strategyMultiStep(config);
|
|
54
|
+
default:
|
|
55
|
+
return this.strategySearchInteraction(config); // safe default
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// ─── Strategy: Load & Capture ─────────────────────────────────────────────────
|
|
59
|
+
// For sites that fire XHR on page load (price pages, dashboards, data portals)
|
|
60
|
+
async strategyLoadAndCapture(config) {
|
|
61
|
+
const steps = [];
|
|
62
|
+
// Page should already be loaded by Session.goto() before navigator is called.
|
|
63
|
+
// Wait for any additional lazy-loaded requests.
|
|
64
|
+
await this.waitForNetworkSettle("initial");
|
|
65
|
+
const seedStrings = config.seedValues.map((s) => String(s.exampleValue));
|
|
66
|
+
// Check if we got what we need
|
|
67
|
+
if (this.interceptor.hasSeedValueInResponses(seedStrings)) {
|
|
68
|
+
return {
|
|
69
|
+
success: true,
|
|
70
|
+
requests: this.interceptor.getUseful(5),
|
|
71
|
+
steps,
|
|
72
|
+
finalUrl: this.page.url(),
|
|
73
|
+
reason: "Data captured on page load",
|
|
74
|
+
earlyTerminated: true,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const useful = this.interceptor.getUseful(8);
|
|
78
|
+
if (useful.length >= 3) {
|
|
79
|
+
return {
|
|
80
|
+
success: true,
|
|
81
|
+
requests: this.interceptor.getUseful(5),
|
|
82
|
+
steps,
|
|
83
|
+
finalUrl: this.page.url(),
|
|
84
|
+
reason: `${useful.length} useful requests captured on load`,
|
|
85
|
+
earlyTerminated: false,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Load didn't capture enough — fall through to search interaction
|
|
89
|
+
config.onProgress?.("Load-capture insufficient, trying search interaction...");
|
|
90
|
+
return this.strategySearchInteraction(config);
|
|
91
|
+
}
|
|
92
|
+
// ─── Strategy: Search Interaction ─────────────────────────────────────────────
|
|
93
|
+
// For sites with a search box: fill input → handle autocomplete → submit → capture
|
|
94
|
+
async strategySearchInteraction(config) {
|
|
95
|
+
const steps = [];
|
|
96
|
+
const seedStrings = config.seedValues.map((s) => String(s.exampleValue));
|
|
97
|
+
// Detect forms on page
|
|
98
|
+
const forms = await this.observer.detectForms();
|
|
99
|
+
const mainForm = forms[0];
|
|
100
|
+
if (!mainForm || !mainForm.mainInput) {
|
|
101
|
+
// No form found — fall through to multi-step AI navigation
|
|
102
|
+
config.onProgress?.("No search form detected, falling back to AI navigation...");
|
|
103
|
+
return this.strategyMultiStep(config);
|
|
104
|
+
}
|
|
105
|
+
// Try each seed value (multi-value retry from test-api)
|
|
106
|
+
for (let i = 0; i < Math.min(config.seedValues.length, 4); i++) {
|
|
107
|
+
const seedValue = config.seedValues[i];
|
|
108
|
+
const exampleValue = String(seedValue.exampleValue);
|
|
109
|
+
config.onProgress?.(`Trying value ${i + 1}: "${exampleValue}"`);
|
|
110
|
+
// If retrying, navigate back to the original URL
|
|
111
|
+
if (i > 0) {
|
|
112
|
+
await this.page.goto(config.url, { waitUntil: "domcontentloaded", timeout: 12_000 });
|
|
113
|
+
await this.waitForNetworkSettle("initial");
|
|
114
|
+
// Re-detect forms (page may have changed)
|
|
115
|
+
const retryForms = await this.observer.detectForms();
|
|
116
|
+
const retryForm = retryForms[0];
|
|
117
|
+
if (!retryForm?.mainInput)
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const currentForm = i === 0 ? mainForm : (await this.observer.detectForms())[0];
|
|
121
|
+
if (!currentForm?.mainInput)
|
|
122
|
+
continue;
|
|
123
|
+
const requestsBefore = this.interceptor.getAll().length;
|
|
124
|
+
// Step 1: Fill the main input
|
|
125
|
+
try {
|
|
126
|
+
this.interceptor.markActionTimestamp();
|
|
127
|
+
const selector = this.observer.getSelector(currentForm.mainInput);
|
|
128
|
+
if (selector) {
|
|
129
|
+
await this.page.click(selector, { clickCount: 3 });
|
|
130
|
+
await this.page.keyboard.press("Backspace");
|
|
131
|
+
await this.page.type(selector, exampleValue, { delay: 80 });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Fallback to generic selectors (from test-api)
|
|
135
|
+
const fallbackSelectors = [
|
|
136
|
+
'input[type="search"]',
|
|
137
|
+
'input[placeholder*="search" i]',
|
|
138
|
+
'input[placeholder*="buscar" i]',
|
|
139
|
+
'input[name*="search" i]',
|
|
140
|
+
'input[name*="query" i]',
|
|
141
|
+
"#search", ".search-input", ".search-box",
|
|
142
|
+
];
|
|
143
|
+
let filled = false;
|
|
144
|
+
for (const sel of fallbackSelectors) {
|
|
145
|
+
try {
|
|
146
|
+
await this.page.waitForSelector(sel, { timeout: 1500 });
|
|
147
|
+
await this.page.click(sel, { clickCount: 3 });
|
|
148
|
+
await this.page.keyboard.press("Backspace");
|
|
149
|
+
await this.page.type(sel, exampleValue, { delay: 80 });
|
|
150
|
+
filled = true;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (!filled)
|
|
158
|
+
continue; // skip this seed value
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
steps.push({
|
|
163
|
+
step: steps.length + 1,
|
|
164
|
+
action: "fill",
|
|
165
|
+
elementId: currentForm.mainInput,
|
|
166
|
+
value: exampleValue,
|
|
167
|
+
result: "error",
|
|
168
|
+
newRequestCount: 0,
|
|
169
|
+
errorMessages: ["Failed to fill input"],
|
|
170
|
+
});
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
steps.push({
|
|
174
|
+
step: steps.length + 1,
|
|
175
|
+
action: "fill",
|
|
176
|
+
elementId: currentForm.mainInput,
|
|
177
|
+
value: exampleValue,
|
|
178
|
+
result: "success",
|
|
179
|
+
newRequestCount: 0,
|
|
180
|
+
errorMessages: [],
|
|
181
|
+
});
|
|
182
|
+
// Step 2: Wait for autocomplete (1.5s from test-api)
|
|
183
|
+
await this.page.waitForTimeout(1500);
|
|
184
|
+
// Step 3: Check for autocomplete dropdown
|
|
185
|
+
const autocompleteClicked = await this.tryClickAutocomplete();
|
|
186
|
+
if (autocompleteClicked) {
|
|
187
|
+
steps.push({
|
|
188
|
+
step: steps.length + 1,
|
|
189
|
+
action: "selectAutocomplete",
|
|
190
|
+
result: "success",
|
|
191
|
+
newRequestCount: 0,
|
|
192
|
+
errorMessages: [],
|
|
193
|
+
});
|
|
194
|
+
// Wait for data to load after clicking autocomplete
|
|
195
|
+
await this.waitForNetworkSettle("interaction");
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// No autocomplete — try submit button or Enter
|
|
199
|
+
if (currentForm.submitButton) {
|
|
200
|
+
try {
|
|
201
|
+
this.interceptor.markActionTimestamp();
|
|
202
|
+
const submitSel = this.observer.getSelector(currentForm.submitButton);
|
|
203
|
+
if (submitSel) {
|
|
204
|
+
await this.page.click(submitSel);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
await this.page.keyboard.press("Enter");
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
await this.page.keyboard.press("Enter");
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else {
|
|
215
|
+
this.interceptor.markActionTimestamp();
|
|
216
|
+
await this.page.keyboard.press("Enter");
|
|
217
|
+
}
|
|
218
|
+
steps.push({
|
|
219
|
+
step: steps.length + 1,
|
|
220
|
+
action: "pressEnter",
|
|
221
|
+
result: "success",
|
|
222
|
+
newRequestCount: 0,
|
|
223
|
+
errorMessages: [],
|
|
224
|
+
});
|
|
225
|
+
// Wait for results to load (3s like test-api)
|
|
226
|
+
await this.waitForNetworkSettle("interaction");
|
|
227
|
+
}
|
|
228
|
+
// Step 4: Check if we captured useful data
|
|
229
|
+
const requestsAfter = this.interceptor.getAll().length;
|
|
230
|
+
const newRequestCount = requestsAfter - requestsBefore;
|
|
231
|
+
// Update last step with request count
|
|
232
|
+
if (steps.length > 0) {
|
|
233
|
+
steps[steps.length - 1].newRequestCount = newRequestCount;
|
|
234
|
+
}
|
|
235
|
+
// Early termination: seed value found in responses
|
|
236
|
+
if (this.interceptor.hasSeedValueInResponses(seedStrings)) {
|
|
237
|
+
config.onProgress?.(`Data captured with value "${exampleValue}"`);
|
|
238
|
+
return {
|
|
239
|
+
success: true,
|
|
240
|
+
requests: this.interceptor.getUseful(3),
|
|
241
|
+
steps,
|
|
242
|
+
finalUrl: this.page.url(),
|
|
243
|
+
reason: `Seed value "${exampleValue}" found in API responses`,
|
|
244
|
+
earlyTerminated: true,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
// Check for useful requests even without seed value match
|
|
248
|
+
const useful = this.interceptor.getUseful(8);
|
|
249
|
+
if (useful.length >= 3 && newRequestCount > 0) {
|
|
250
|
+
config.onProgress?.(`${useful.length} useful requests captured`);
|
|
251
|
+
return {
|
|
252
|
+
success: true,
|
|
253
|
+
requests: this.interceptor.getUseful(3),
|
|
254
|
+
steps,
|
|
255
|
+
finalUrl: this.page.url(),
|
|
256
|
+
reason: `${useful.length} API requests captured after search`,
|
|
257
|
+
earlyTerminated: false,
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
// Check for error messages on page (no results)
|
|
261
|
+
const errors = await this.observer.detectErrors();
|
|
262
|
+
if (errors.length > 0) {
|
|
263
|
+
steps.push({
|
|
264
|
+
step: steps.length + 1,
|
|
265
|
+
action: "detectErrors",
|
|
266
|
+
result: "error",
|
|
267
|
+
newRequestCount: 0,
|
|
268
|
+
errorMessages: errors,
|
|
269
|
+
});
|
|
270
|
+
config.onProgress?.(`No results with "${exampleValue}", trying next value...`);
|
|
271
|
+
// Continue to next seed value
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
// All seed values exhausted — return what we have
|
|
275
|
+
const allUseful = this.interceptor.getUseful(3);
|
|
276
|
+
if (allUseful.length > 0) {
|
|
277
|
+
return {
|
|
278
|
+
success: true,
|
|
279
|
+
requests: allUseful,
|
|
280
|
+
steps,
|
|
281
|
+
finalUrl: this.page.url(),
|
|
282
|
+
reason: "Partial results after trying all seed values",
|
|
283
|
+
earlyTerminated: false,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
// Nothing found via search — try multi-step as last resort
|
|
287
|
+
config.onProgress?.("Search interaction failed, trying AI navigation...");
|
|
288
|
+
return this.strategyMultiStep(config);
|
|
289
|
+
}
|
|
290
|
+
// ─── Strategy: Multi-step AI Navigation ───────────────────────────────────────
|
|
291
|
+
// For complex sites: AI observes → decides → acts → re-observes.
|
|
292
|
+
// One action per step with full re-observation (Notte pattern).
|
|
293
|
+
async strategyMultiStep(config) {
|
|
294
|
+
const steps = [];
|
|
295
|
+
const seedStrings = config.seedValues.map((s) => String(s.exampleValue));
|
|
296
|
+
const context = {
|
|
297
|
+
stepNumber: 0,
|
|
298
|
+
history: steps,
|
|
299
|
+
hypothesis: config.hypothesis,
|
|
300
|
+
seedValues: seedStrings,
|
|
301
|
+
};
|
|
302
|
+
for (let i = 0; i < config.maxSteps; i++) {
|
|
303
|
+
context.stepNumber = i + 1;
|
|
304
|
+
// Re-observe after every action (Notte pattern)
|
|
305
|
+
const observation = await this.observer.observe();
|
|
306
|
+
const forms = await this.observer.detectForms();
|
|
307
|
+
const autocompleteItems = await this.observer.detectAutocomplete();
|
|
308
|
+
const errorMessages = await this.observer.detectErrors();
|
|
309
|
+
// Build structured perception
|
|
310
|
+
const perception = (0, perception_1.buildPerception)(observation, forms, autocompleteItems, errorMessages, this.interceptor.getAll(), seedStrings);
|
|
311
|
+
// Early termination check
|
|
312
|
+
if (perception.networkSummary.hasSeedValueInResponses) {
|
|
313
|
+
config.onProgress?.("Seed value found in responses — stopping");
|
|
314
|
+
return {
|
|
315
|
+
success: true,
|
|
316
|
+
requests: this.interceptor.getUseful(3),
|
|
317
|
+
steps,
|
|
318
|
+
finalUrl: this.page.url(),
|
|
319
|
+
reason: "Seed value found in captured API responses",
|
|
320
|
+
earlyTerminated: true,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
// Format perception for LLM
|
|
324
|
+
const perceptionText = (0, perception_1.formatPerceptionForLLM)(perception, context);
|
|
325
|
+
// Ask AI what to do
|
|
326
|
+
let action;
|
|
327
|
+
let usedScreenshot = false;
|
|
328
|
+
if (observation.elements.filter((e) => e.visible).length > 0) {
|
|
329
|
+
action = await this.ai.decideFromObservation(config.navigationGoal, { ...observation, text: perceptionText }, // override text with structured perception
|
|
330
|
+
steps.map((s) => `Step ${s.step}: ${s.action} → ${s.result}`), config.seedValues);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Fallback to screenshot
|
|
334
|
+
const screenshot = await this.page.screenshot({ type: "jpeg", quality: 80, encoding: "base64" });
|
|
335
|
+
const base64 = typeof screenshot === "string" ? screenshot : screenshot.toString("base64");
|
|
336
|
+
action = await this.ai.decideFromScreenshot(config.navigationGoal, base64, steps.map((s) => `Step ${s.step}: ${s.action} → ${s.result}`), config.seedValues);
|
|
337
|
+
usedScreenshot = true;
|
|
338
|
+
}
|
|
339
|
+
// Terminal states
|
|
340
|
+
if (action.type === "done") {
|
|
341
|
+
return {
|
|
342
|
+
success: true,
|
|
343
|
+
requests: this.interceptor.getUseful(3),
|
|
344
|
+
steps,
|
|
345
|
+
finalUrl: this.page.url(),
|
|
346
|
+
reason: action.reason,
|
|
347
|
+
earlyTerminated: false,
|
|
348
|
+
};
|
|
349
|
+
}
|
|
350
|
+
if (action.type === "impossible") {
|
|
351
|
+
return {
|
|
352
|
+
success: false,
|
|
353
|
+
requests: this.interceptor.getUseful(3),
|
|
354
|
+
steps,
|
|
355
|
+
finalUrl: this.page.url(),
|
|
356
|
+
reason: action.reason,
|
|
357
|
+
earlyTerminated: false,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
// Execute action
|
|
361
|
+
const requestsBefore = this.interceptor.getAll().length;
|
|
362
|
+
await this.executeAction(action);
|
|
363
|
+
// Wait after interaction (2s — shorter than initial)
|
|
364
|
+
await this.waitForNetworkSettle("interaction");
|
|
365
|
+
const requestsAfter = this.interceptor.getAll().length;
|
|
366
|
+
const postErrors = await this.observer.detectErrors();
|
|
367
|
+
steps.push({
|
|
368
|
+
step: i + 1,
|
|
369
|
+
action: action.type,
|
|
370
|
+
elementId: "elementId" in action ? action.elementId : undefined,
|
|
371
|
+
value: "value" in action ? action.value : undefined,
|
|
372
|
+
result: requestsAfter > requestsBefore ? "new-requests" : postErrors.length > 0 ? "error" : "no-change",
|
|
373
|
+
newRequestCount: requestsAfter - requestsBefore,
|
|
374
|
+
errorMessages: postErrors,
|
|
375
|
+
});
|
|
376
|
+
config.onProgress?.(`Step ${i + 1}: ${action.type} → ${requestsAfter - requestsBefore} new requests`);
|
|
377
|
+
}
|
|
378
|
+
// Max steps reached
|
|
379
|
+
return {
|
|
380
|
+
success: this.interceptor.getUseful(5).length > 0,
|
|
381
|
+
requests: this.interceptor.getUseful(3),
|
|
382
|
+
steps,
|
|
383
|
+
finalUrl: this.page.url(),
|
|
384
|
+
reason: `Completed ${config.maxSteps} steps`,
|
|
385
|
+
earlyTerminated: false,
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
// ─── Execute a single action ────────────────────────────────────────────────
|
|
389
|
+
async executeAction(action) {
|
|
390
|
+
try {
|
|
391
|
+
switch (action.type) {
|
|
392
|
+
case "click": {
|
|
393
|
+
this.interceptor.markActionTimestamp();
|
|
394
|
+
const selector = this.observer.getSelector(action.elementId);
|
|
395
|
+
if (selector) {
|
|
396
|
+
await this.page.click(selector);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
// Resolve by coords
|
|
400
|
+
const coords = await this.observer.resolveElementId(action.elementId);
|
|
401
|
+
if (coords) {
|
|
402
|
+
await this.page.mouse.click(coords.x, coords.y);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
break;
|
|
406
|
+
}
|
|
407
|
+
case "fill": {
|
|
408
|
+
this.interceptor.markActionTimestamp();
|
|
409
|
+
const selector = this.observer.getSelector(action.elementId);
|
|
410
|
+
if (selector) {
|
|
411
|
+
await this.page.click(selector, { clickCount: 3 });
|
|
412
|
+
await this.page.keyboard.press("Backspace");
|
|
413
|
+
await this.page.type(selector, action.value, { delay: 80 });
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
const coords = await this.observer.resolveElementId(action.elementId);
|
|
417
|
+
if (coords) {
|
|
418
|
+
await this.page.mouse.click(coords.x, coords.y);
|
|
419
|
+
await this.page.keyboard.press("Control+a");
|
|
420
|
+
await this.page.keyboard.type(action.value, { delay: 80 });
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
case "scroll":
|
|
426
|
+
this.interceptor.markActionTimestamp();
|
|
427
|
+
await this.page.evaluate(({ direction, amount }) => {
|
|
428
|
+
window.scrollBy(0, direction === "down" ? amount : -amount);
|
|
429
|
+
}, { direction: action.direction, amount: action.amount ?? 300 }).catch(() => { });
|
|
430
|
+
break;
|
|
431
|
+
case "navigate":
|
|
432
|
+
this.interceptor.markActionTimestamp();
|
|
433
|
+
await this.page.goto(action.url, { waitUntil: "domcontentloaded", timeout: 15_000 });
|
|
434
|
+
break;
|
|
435
|
+
case "wait":
|
|
436
|
+
await this.page.waitForTimeout(action.ms);
|
|
437
|
+
break;
|
|
438
|
+
default:
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
catch (err) {
|
|
443
|
+
console.warn(`[Navigator] Action ${action.type} failed:`, err.message);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// ─── Autocomplete handling (from test-api) ──────────────────────────────────
|
|
447
|
+
async tryClickAutocomplete() {
|
|
448
|
+
for (const sel of AUTOCOMPLETE_SELECTORS) {
|
|
449
|
+
try {
|
|
450
|
+
const items = await this.page.$$(sel);
|
|
451
|
+
if (items.length > 0) {
|
|
452
|
+
this.interceptor.markActionTimestamp();
|
|
453
|
+
await items[0].click();
|
|
454
|
+
return true;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
continue;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
// ─── Wait strategies ────────────────────────────────────────────────────────
|
|
464
|
+
async waitForNetworkSettle(mode) {
|
|
465
|
+
if (mode === "initial") {
|
|
466
|
+
// Long wait: up to 8s for network idle
|
|
467
|
+
try {
|
|
468
|
+
await this.page.waitForNetworkIdle({ timeout: 8_000, idleTime: 500 });
|
|
469
|
+
}
|
|
470
|
+
catch {
|
|
471
|
+
// non-fatal
|
|
472
|
+
}
|
|
473
|
+
await this.page.waitForTimeout(800);
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
// Short wait: 2s after interactions (from Notte dual-wait pattern)
|
|
477
|
+
await this.page.waitForTimeout(2000);
|
|
478
|
+
// Quick check for additional requests
|
|
479
|
+
try {
|
|
480
|
+
await this.page.waitForNetworkIdle({ timeout: 2_000, idleTime: 300 });
|
|
481
|
+
}
|
|
482
|
+
catch {
|
|
483
|
+
// non-fatal
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
// ─── Strategy inference ─────────────────────────────────────────────────────
|
|
488
|
+
inferStrategy(config) {
|
|
489
|
+
// If no seed values, we can only load and capture
|
|
490
|
+
if (config.seedValues.length === 0)
|
|
491
|
+
return "load-capture";
|
|
492
|
+
// If hypothesis suggests API-direct or page-load-only
|
|
493
|
+
if (config.hypothesis) {
|
|
494
|
+
const h = config.hypothesis.toLowerCase();
|
|
495
|
+
if (h.includes("page-load") || h.includes("dashboard") || h.includes("data-portal"))
|
|
496
|
+
return "load-capture";
|
|
497
|
+
if (h.includes("search") || h.includes("input"))
|
|
498
|
+
return "search";
|
|
499
|
+
if (h.includes("multi-step") || h.includes("navigation"))
|
|
500
|
+
return "multi-step";
|
|
501
|
+
}
|
|
502
|
+
// Default to search (most common case with seed values)
|
|
503
|
+
return "search";
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
exports.SmartNavigator = SmartNavigator;
|
|
507
|
+
//# sourceMappingURL=navigator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigator.js","sourceRoot":"","sources":["../src/navigator.ts"],"names":[],"mappings":"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"}
|
package/dist/observer.d.ts
CHANGED
|
@@ -1,14 +1,34 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { PageHandle } from "./browser-provider";
|
|
2
2
|
import type { ObserveResult } from "./types";
|
|
3
|
+
export interface DetectedForm {
|
|
4
|
+
mainInput: string | null;
|
|
5
|
+
submitButton: string | null;
|
|
6
|
+
fields: Array<{
|
|
7
|
+
elementId: string;
|
|
8
|
+
name: string;
|
|
9
|
+
type: string;
|
|
10
|
+
isMain: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
formType: "search" | "multi-field" | "login" | "unknown";
|
|
13
|
+
}
|
|
14
|
+
export interface AutocompleteItem {
|
|
15
|
+
text: string;
|
|
16
|
+
selector: string;
|
|
17
|
+
}
|
|
3
18
|
export declare class Observer {
|
|
4
19
|
private page;
|
|
5
|
-
|
|
20
|
+
private elementSelectors;
|
|
21
|
+
constructor(page: PageHandle);
|
|
6
22
|
observe(): Promise<ObserveResult>;
|
|
7
23
|
resolveElementId(id: string): Promise<{
|
|
8
24
|
x: number;
|
|
9
25
|
y: number;
|
|
10
26
|
} | null>;
|
|
27
|
+
getSelector(id: string): string | undefined;
|
|
28
|
+
detectForms(): Promise<DetectedForm[]>;
|
|
29
|
+
detectAutocomplete(): Promise<AutocompleteItem[]>;
|
|
30
|
+
detectErrors(): Promise<string[]>;
|
|
11
31
|
private resolveType;
|
|
12
|
-
private
|
|
32
|
+
private buildTextRepresentation;
|
|
13
33
|
}
|
|
14
34
|
//# sourceMappingURL=observer.d.ts.map
|
package/dist/observer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../src/observer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAmB,aAAa,EAAe,MAAM,SAAS,CAAC;AAgB3E,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,EAAE,KAAK,CAAC;QACZ,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,OAAO,CAAC;KACjB,CAAC,CAAC;IACH,QAAQ,EAAE,QAAQ,GAAG,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;CAC1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,qBAAa,QAAQ;IACnB,OAAO,CAAC,IAAI,CAAa;IAEzB,OAAO,CAAC,gBAAgB,CAAkC;gBAE9C,IAAI,EAAE,UAAU;IAKtB,OAAO,IAAI,OAAO,CAAC,aAAa,CAAC;IA4OjC,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAmC5E,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAMrC,WAAW,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IA8CtC,kBAAkB,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAwCjD,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAoCvC,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,uBAAuB;CAkChC"}
|