aurix-ai 2.5.7 → 2.5.9
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/bin/aurix.js +31 -0
- package/dist/agent/AgentLoop.d.ts.map +1 -1
- package/dist/agent/AgentLoop.js +17 -0
- package/dist/agent/AgentLoop.js.map +1 -1
- package/dist/agent/Context.d.ts.map +1 -1
- package/dist/agent/Context.js +31 -70
- package/dist/agent/Context.js.map +1 -1
- package/dist/gateway/Gateway.d.ts.map +1 -1
- package/dist/gateway/Gateway.js +2 -1
- package/dist/gateway/Gateway.js.map +1 -1
- package/dist/tools/Browser.d.ts.map +1 -1
- package/dist/tools/Browser.js +198 -112
- package/dist/tools/Browser.js.map +1 -1
- package/dist/tools/CodeExec.d.ts.map +1 -1
- package/dist/tools/CodeExec.js +19 -4
- package/dist/tools/CodeExec.js.map +1 -1
- package/dist/tools/Terminal.d.ts.map +1 -1
- package/dist/tools/Terminal.js +2 -1
- package/dist/tools/Terminal.js.map +1 -1
- package/package.json +2 -3
package/dist/tools/Browser.js
CHANGED
|
@@ -1019,44 +1019,47 @@ async function analyzeImageChallenge(page, frame, provider) {
|
|
|
1019
1019
|
}
|
|
1020
1020
|
export const browserTool = {
|
|
1021
1021
|
name: 'browser',
|
|
1022
|
-
description: `
|
|
1022
|
+
description: `Persistent Chromium browser. Profile: ~/.aurix-browser-profile.
|
|
1023
1023
|
|
|
1024
|
-
|
|
1024
|
+
# HARD RULES — VIOLATE THESE AND YOU FAIL
|
|
1025
|
+
1. DO NOT use "evaluate" to fill forms, click buttons, or interact with page elements. Use fill, click, type, signup-assist, signin-assist instead. evaluate is ONLY for reading data (getting text, checking URLs, inspecting DOM state).
|
|
1026
|
+
2. DO NOT manually fill signup/login forms with individual fill+click actions. ALWAYS use signup-assist or signin-assist — one call does everything.
|
|
1027
|
+
3. DO NOT take 4+ screenshots in a row without fill/click/type in between. Screenshot → act → screenshot to verify is fine. Screenshot → screenshot → screenshot is a loop.
|
|
1028
|
+
4. If an action fails TWICE, STOP and try a COMPLETELY DIFFERENT approach. Never repeat the same failing action.
|
|
1029
|
+
5. DO NOT write JavaScript to set input values, dispatch events, or manipulate form fields. Playwright fill/click handles React, Angular, Vue forms natively.
|
|
1025
1030
|
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
signup-assist
|
|
1031
|
+
# WORKFLOW: Sign Up / Register
|
|
1032
|
+
Step 1: navigate to the signup page
|
|
1033
|
+
Step 2: signup-assist with user data — ONE call fills ALL fields, clicks checkboxes, submits:
|
|
1029
1034
|
action="signup-assist" value='{"email":"user@mail.com","password":"Pass123!","firstName":"John","lastName":"Doe"}'
|
|
1030
|
-
|
|
1035
|
+
Step 3: If multi-step form, run signup-assist again on the next page
|
|
1036
|
+
Step 4: If captcha appears → use solve-captcha → then continue
|
|
1031
1037
|
|
|
1032
|
-
|
|
1038
|
+
# WORKFLOW: Log In
|
|
1039
|
+
Step 1: navigate to the login page
|
|
1040
|
+
Step 2: signin-assist — ONE call:
|
|
1033
1041
|
action="signin-assist" value='{"email":"user@mail.com","password":"Pass123!"}'
|
|
1034
|
-
Also detects OTP code input fields and extra form elements automatically.
|
|
1035
|
-
|
|
1036
|
-
Image-selection grid workflow (when a form asks the user to pick specific images):
|
|
1037
|
-
1. "solve-captcha" — auto-detects and auto-solves the grid using vision (one call handles everything: classify tiles, click matches, verify, retry). If auto-solve fails, falls back to manual:
|
|
1038
|
-
2. "captcha-grid" — screenshots the grid and each tile individually for manual analysis
|
|
1039
|
-
3. "click-tile" with comma-separated indices (e.g. value="0,3,5") to batch-click matching tiles. Replacement tiles are auto-evaluated.
|
|
1040
|
-
4. "captcha-verify" to submit — auto-retries up to 3 times if verification fails
|
|
1041
1042
|
|
|
1042
|
-
|
|
1043
|
-
1
|
|
1044
|
-
2
|
|
1045
|
-
3
|
|
1046
|
-
4
|
|
1047
|
-
5. For image match: "click" on matching elements
|
|
1048
|
-
6. Use "hold-click" for press-and-hold elements (target=element, value=duration in ms)
|
|
1043
|
+
# WORKFLOW: Individual Field Fill (only if signup-assist didn't cover it)
|
|
1044
|
+
Step 1: fill target="selector" value="text" — Playwright handles React/Angular/Vue inputs natively
|
|
1045
|
+
Step 2: If fill fails → try type (simulates keystrokes, works on stubborn React inputs)
|
|
1046
|
+
Step 3: If type fails → click the input first, then type again
|
|
1047
|
+
Step 4: If ALL 3 fail → take a snapshot to find a better selector, then retry
|
|
1049
1048
|
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
3. If gap was not detected, use "slider-analyze" to re-scan and get the offset
|
|
1054
|
-
4. NEVER guess the offset — always use the value from solve-captcha or slider-analyze
|
|
1055
|
-
5. Then: drag-to target=".geetest_slider_button" value="<offset>,0"
|
|
1049
|
+
# Captcha Auto-Solve (all types)
|
|
1050
|
+
- solve-captcha: ONE call auto-solves image grids, sliders, FunCaptcha. Use this FIRST.
|
|
1051
|
+
- If solve-captcha fails after 2 attempts → tell the user, do NOT keep retrying.
|
|
1056
1052
|
|
|
1057
|
-
|
|
1053
|
+
# Action Reference
|
|
1054
|
+
Forms: signup-assist, signin-assist, fill, type, click, select, press-key, upload
|
|
1055
|
+
Navigation: navigate, back, forward, scroll, new-tab, switch-tab, close-tab, open-tabs
|
|
1056
|
+
Read: screenshot, snapshot, text, html, url, title, cookies
|
|
1057
|
+
Advanced: evaluate (READ ONLY), drag-to, hold-click, wait
|
|
1058
|
+
Captcha: detect-captcha, solve-captcha, captcha-grid, click-tile, captcha-verify, slider-analyze
|
|
1059
|
+
Config: set-proxy, set-ui, status, close
|
|
1058
1060
|
|
|
1059
|
-
|
|
1061
|
+
Target: CSS (#id, .class, [attr]), text="...", role=button, placeholder="...", label="...", or plain text.
|
|
1062
|
+
Sessions: session="a"/"b"/"c" for parallel browsers. proxy="host:port:user:pass" per session.`,
|
|
1060
1063
|
parameters: {
|
|
1061
1064
|
type: 'object',
|
|
1062
1065
|
properties: {
|
|
@@ -1232,9 +1235,19 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
1232
1235
|
const msg = e.message || String(e);
|
|
1233
1236
|
if (msg.includes('Timeout'))
|
|
1234
1237
|
return err(`Input "${target}" not found within timeout`, 'Use "snapshot" to see available form fields');
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
+
try {
|
|
1239
|
+
const locator = await resolveLocator(p, target);
|
|
1240
|
+
await locator.first().click({ timeout: 3000 });
|
|
1241
|
+
await locator.first().pressSequentially(value, { delay: 30, timeout: 10000 });
|
|
1242
|
+
const ss = await autoScreenshot(p, 'fill-fallback-type');
|
|
1243
|
+
return ok(`Filled "${target}" (via keystroke fallback)`, {
|
|
1244
|
+
value: value.length > 50 ? value.slice(0, 50) + '...' : value,
|
|
1245
|
+
screenshot: ss,
|
|
1246
|
+
});
|
|
1247
|
+
}
|
|
1248
|
+
catch (e2) {
|
|
1249
|
+
return err(`Fill failed on "${target}": ${msg.slice(0, 150)}`, 'Use "type" action directly, or "snapshot" to find a better selector');
|
|
1250
|
+
}
|
|
1238
1251
|
}
|
|
1239
1252
|
}
|
|
1240
1253
|
case 'type': {
|
|
@@ -2598,6 +2611,27 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2598
2611
|
results.push('=== SIGNUP ASSIST ===');
|
|
2599
2612
|
results.push(`Provided: ${Object.keys(data).join(', ')}`);
|
|
2600
2613
|
results.push('');
|
|
2614
|
+
const cookieSelectors = [
|
|
2615
|
+
'button:has-text("Accept All")', 'button:has-text("Accept all")', 'button:has-text("accept all")',
|
|
2616
|
+
'button:has-text("Accept")', 'button:has-text("Accept Cookies")',
|
|
2617
|
+
'button:has-text("I agree")', 'button:has-text("Got it")', 'button:has-text("OK")',
|
|
2618
|
+
'button:has-text("Allow All")', 'button:has-text("Allow all")',
|
|
2619
|
+
'[id*="cookie"] button', '[class*="cookie"] button',
|
|
2620
|
+
'[id*="consent"] button', '[class*="consent"] button',
|
|
2621
|
+
'.cc-accept', '.cookie-accept', '#accept-cookies',
|
|
2622
|
+
];
|
|
2623
|
+
for (const sel of cookieSelectors) {
|
|
2624
|
+
try {
|
|
2625
|
+
const btn = p.locator(sel).first();
|
|
2626
|
+
if (await btn.count() > 0 && await btn.isVisible()) {
|
|
2627
|
+
await btn.click({ timeout: 2000 });
|
|
2628
|
+
results.push(` ✓ Dismissed cookie banner: ${sel}`);
|
|
2629
|
+
await p.waitForTimeout(500);
|
|
2630
|
+
break;
|
|
2631
|
+
}
|
|
2632
|
+
}
|
|
2633
|
+
catch { }
|
|
2634
|
+
}
|
|
2601
2635
|
const allFrames = [p, ...p.frames().filter(f => f !== p.mainFrame())];
|
|
2602
2636
|
let activeFrame = p;
|
|
2603
2637
|
for (const frame of allFrames) {
|
|
@@ -2607,6 +2641,42 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2607
2641
|
break;
|
|
2608
2642
|
}
|
|
2609
2643
|
}
|
|
2644
|
+
const hasEmailField = await activeFrame.locator('input[type="email"]:visible, input[name*="email" i]:visible, input[autocomplete="email"]:visible').count() > 0;
|
|
2645
|
+
const hasPasswordField = await activeFrame.locator('input[type="password"]:visible').count() > 0;
|
|
2646
|
+
if (!hasEmailField && !hasPasswordField) {
|
|
2647
|
+
const ctaSelectors = [
|
|
2648
|
+
'button:has-text("Sign Up With Email")', 'button:has-text("sign up with email")',
|
|
2649
|
+
'a:has-text("Sign Up With Email")', 'a:has-text("sign up with email")',
|
|
2650
|
+
'button:has-text("Sign up with email")',
|
|
2651
|
+
'button:has-text("Create Account")', 'button:has-text("create account")',
|
|
2652
|
+
'button:has-text("Sign Up")', 'button:has-text("sign up")',
|
|
2653
|
+
'button:has-text("Register")', 'button:has-text("register")',
|
|
2654
|
+
'button:has-text("Get Started")', 'button:has-text("get started")',
|
|
2655
|
+
'button:has-text("Continue with Email")', 'button:has-text("continue with email")',
|
|
2656
|
+
'button:has-text("Use Email")', 'button:has-text("use email")',
|
|
2657
|
+
'a:has-text("Sign Up")', 'a:has-text("Register")',
|
|
2658
|
+
'[data-testid*="signup"]', '[data-testid*="email"]',
|
|
2659
|
+
];
|
|
2660
|
+
for (const sel of ctaSelectors) {
|
|
2661
|
+
try {
|
|
2662
|
+
const btn = activeFrame.locator(sel).first();
|
|
2663
|
+
if (await btn.count() > 0 && await btn.isVisible()) {
|
|
2664
|
+
await btn.click({ timeout: 3000 });
|
|
2665
|
+
results.push(` ✓ Clicked CTA: ${sel}`);
|
|
2666
|
+
await p.waitForTimeout(1500);
|
|
2667
|
+
break;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
catch { }
|
|
2671
|
+
}
|
|
2672
|
+
for (const frame of [p, ...p.frames().filter(f => f !== p.mainFrame())]) {
|
|
2673
|
+
const inputs = await frame.locator('input:visible, select:visible, textarea:visible').count();
|
|
2674
|
+
if (inputs > 0) {
|
|
2675
|
+
activeFrame = frame;
|
|
2676
|
+
break;
|
|
2677
|
+
}
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2610
2680
|
results.push(`Active frame: ${activeFrame === p ? 'main page' : 'iframe'} (${await activeFrame.locator('input:visible, select:visible, textarea:visible').count()} fields)`);
|
|
2611
2681
|
const fillField = async (selectors, val, label) => {
|
|
2612
2682
|
for (const sel of selectors) {
|
|
@@ -2618,7 +2688,13 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2618
2688
|
results.push(` ✓ ${label}: already filled`);
|
|
2619
2689
|
return true;
|
|
2620
2690
|
}
|
|
2621
|
-
|
|
2691
|
+
try {
|
|
2692
|
+
await loc.fill(val, { timeout: 1500 });
|
|
2693
|
+
}
|
|
2694
|
+
catch {
|
|
2695
|
+
await loc.click({ timeout: 1500 });
|
|
2696
|
+
await loc.pressSequentially(val, { delay: 30, timeout: 5000 });
|
|
2697
|
+
}
|
|
2622
2698
|
results.push(` ✓ ${label}: filled`);
|
|
2623
2699
|
return true;
|
|
2624
2700
|
}
|
|
@@ -2637,7 +2713,7 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2637
2713
|
results.push(` ✓ ${label}: already checked`);
|
|
2638
2714
|
return true;
|
|
2639
2715
|
}
|
|
2640
|
-
await loc.click({ timeout:
|
|
2716
|
+
await loc.click({ timeout: 1500 });
|
|
2641
2717
|
results.push(` ✓ ${label}: clicked`);
|
|
2642
2718
|
return true;
|
|
2643
2719
|
}
|
|
@@ -2701,102 +2777,73 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2701
2777
|
results.push('--- Filling fields ---');
|
|
2702
2778
|
if (data.email) {
|
|
2703
2779
|
await fillField([
|
|
2704
|
-
'input[type="email"]',
|
|
2705
|
-
'input[
|
|
2706
|
-
'input[name*="username" i]', 'input[name*="MemberName"]',
|
|
2707
|
-
'input[id*="email" i]', 'input[id*="username" i]',
|
|
2708
|
-
'input[placeholder*="email" i]', 'input[placeholder*="Email"]',
|
|
2709
|
-
'input[autocomplete="email"]', 'input[autocomplete="username"]',
|
|
2710
|
-
'input[name="loginfmt"]',
|
|
2780
|
+
'input[type="email"]', 'input[name*="email" i]', 'input[id*="email" i]',
|
|
2781
|
+
'input[autocomplete="email"]', 'input[placeholder*="email" i]',
|
|
2711
2782
|
], data.email, 'Email');
|
|
2712
2783
|
}
|
|
2713
2784
|
if (data.password) {
|
|
2714
2785
|
await fillField([
|
|
2715
|
-
'input[type="password"]',
|
|
2716
|
-
'input[
|
|
2717
|
-
'input[id*="password" i]', 'input[name*="pass" i]',
|
|
2718
|
-
'input[autocomplete="new-password"]', 'input[autocomplete="current-password"]',
|
|
2786
|
+
'input[type="password"]', 'input[name*="password" i]', 'input[id*="password" i]',
|
|
2787
|
+
'input[autocomplete="new-password"]',
|
|
2719
2788
|
], data.password, 'Password');
|
|
2720
2789
|
}
|
|
2721
2790
|
if (data.firstName) {
|
|
2722
2791
|
await fillField([
|
|
2723
|
-
'input[name*="
|
|
2724
|
-
'input[
|
|
2725
|
-
'input[autocomplete="given-name"]',
|
|
2726
|
-
'input[placeholder*="first name" i]', 'input[placeholder*="First"]',
|
|
2727
|
-
'input[name="NameInput"]',
|
|
2792
|
+
'input[name*="first" i]', 'input[id*="first" i]',
|
|
2793
|
+
'input[autocomplete="given-name"]', 'input[placeholder*="first" i]',
|
|
2728
2794
|
], data.firstName, 'First name');
|
|
2729
2795
|
}
|
|
2730
2796
|
if (data.lastName) {
|
|
2731
2797
|
await fillField([
|
|
2732
|
-
'input[name*="
|
|
2733
|
-
'input[
|
|
2734
|
-
'input[autocomplete="family-name"]',
|
|
2735
|
-
'input[placeholder*="last name" i]', 'input[placeholder*="Last"]',
|
|
2736
|
-
'input[name="LastName"]',
|
|
2798
|
+
'input[name*="last" i]', 'input[id*="last" i]',
|
|
2799
|
+
'input[autocomplete="family-name"]', 'input[placeholder*="last" i]',
|
|
2737
2800
|
], data.lastName, 'Last name');
|
|
2738
2801
|
}
|
|
2739
2802
|
if (data.firstName && !data.lastName) {
|
|
2740
2803
|
await fillField([
|
|
2741
|
-
'input[name*="name" i]', 'input[id*="name" i]',
|
|
2742
|
-
'input[autocomplete="name"]',
|
|
2804
|
+
'input[name*="name" i]', 'input[id*="name" i]', 'input[autocomplete="name"]',
|
|
2743
2805
|
], data.firstName + ' User', 'Full name');
|
|
2744
2806
|
}
|
|
2745
2807
|
if (data.phone) {
|
|
2746
2808
|
await fillField([
|
|
2747
|
-
'input[type="tel"]', 'input[name*="phone" i]', 'input[
|
|
2748
|
-
'input[id*="phone" i]', 'input[autocomplete="tel"]',
|
|
2749
|
-
'input[placeholder*="phone" i]',
|
|
2809
|
+
'input[type="tel"]', 'input[name*="phone" i]', 'input[autocomplete="tel"]',
|
|
2750
2810
|
], data.phone, 'Phone');
|
|
2751
2811
|
}
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2812
|
+
if (data.birthYear || data.birthMonth || data.birthDay) {
|
|
2813
|
+
const birthYear = data.birthYear || '2003';
|
|
2814
|
+
const birthMonth = data.birthMonth || 'January';
|
|
2815
|
+
const birthDay = data.birthDay || '15';
|
|
2816
|
+
await selectDropdown([
|
|
2817
|
+
'select[id*="year" i]', 'select[name*="year" i]',
|
|
2818
|
+
], birthYear, 'Birth year');
|
|
2819
|
+
await selectDropdown([
|
|
2820
|
+
'select[id*="month" i]', 'select[name*="month" i]',
|
|
2821
|
+
], birthMonth, 'Birth month');
|
|
2822
|
+
await selectDropdown([
|
|
2823
|
+
'select[id*="day" i]', 'select[name*="day" i]',
|
|
2824
|
+
], birthDay, 'Birth day');
|
|
2825
|
+
}
|
|
2826
|
+
if (data.country) {
|
|
2827
|
+
await selectDropdown([
|
|
2828
|
+
'select[name*="country" i]', 'select[id*="country" i]',
|
|
2829
|
+
], data.country, 'Country');
|
|
2830
|
+
}
|
|
2831
|
+
if (data.username) {
|
|
2832
|
+
await fillField([
|
|
2833
|
+
'input[name*="username" i]', 'input[id*="username" i]',
|
|
2834
|
+
], data.username, 'Username');
|
|
2835
|
+
}
|
|
2775
2836
|
await clickField([
|
|
2776
2837
|
'input[type="checkbox"][name*="agree" i]',
|
|
2777
|
-
'input[type="checkbox"][name*="tos" i]',
|
|
2778
2838
|
'input[type="checkbox"][name*="terms" i]',
|
|
2779
2839
|
'input[type="checkbox"][name*="consent" i]',
|
|
2780
|
-
'input[type="checkbox"][name*="privacy" i]',
|
|
2781
|
-
'input[type="checkbox"][name*="policy" i]',
|
|
2782
2840
|
'input[type="checkbox"][id*="agree" i]',
|
|
2783
2841
|
'input[type="checkbox"][id*="terms" i]',
|
|
2784
|
-
'input[type="checkbox"][id*="consent" i]',
|
|
2785
|
-
'input[type="checkbox"][id*="privacy" i]',
|
|
2786
|
-
'input[type="checkbox"][aria-label*="agree" i]',
|
|
2787
|
-
'input[type="checkbox"][aria-label*="terms" i]',
|
|
2788
|
-
'input[type="checkbox"][aria-label*="consent" i]',
|
|
2789
|
-
'input[type="checkbox"][aria-label*="accept" i]',
|
|
2790
2842
|
'label:has-text("agree") input[type="checkbox"]',
|
|
2791
2843
|
'label:has-text("terms") input[type="checkbox"]',
|
|
2792
2844
|
'label:has-text("accept") input[type="checkbox"]',
|
|
2793
|
-
'label:has-text("consent") input[type="checkbox"]',
|
|
2794
|
-
'label:has-text("privacy") input[type="checkbox"]',
|
|
2795
2845
|
'label:has-text("I agree") input[type="checkbox"]',
|
|
2796
|
-
'label:has-text("I accept") input[type="checkbox"]',
|
|
2797
2846
|
'[role="checkbox"][aria-checked="false"]',
|
|
2798
|
-
'div:has-text("I agree"):not(:has(div:has-text("I agree")))',
|
|
2799
|
-
'span:has-text("I agree"):not(:has(span:has-text("I agree")))',
|
|
2800
2847
|
], 'Terms/Agreement checkbox');
|
|
2801
2848
|
await p.waitForTimeout(500);
|
|
2802
2849
|
const hasCaptcha = p.frames().some(f => {
|
|
@@ -2809,7 +2856,16 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2809
2856
|
results.push('');
|
|
2810
2857
|
results.push('--- Verification step detected ---');
|
|
2811
2858
|
results.push('Attempting to complete automatically...');
|
|
2812
|
-
|
|
2859
|
+
let solveResults;
|
|
2860
|
+
try {
|
|
2861
|
+
solveResults = await Promise.race([
|
|
2862
|
+
autoSolveCaptcha(p),
|
|
2863
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error('auto-solve timed out (30s)')), 30000)),
|
|
2864
|
+
]);
|
|
2865
|
+
}
|
|
2866
|
+
catch (e) {
|
|
2867
|
+
solveResults = [`Auto-solve: ${e.message}`];
|
|
2868
|
+
}
|
|
2813
2869
|
solveResults.forEach(r => results.push(` ${r}`));
|
|
2814
2870
|
const needsVision = solveResults.some(r => r.includes('VERIFICATION COMPLETION STEPS') || r.includes('REQUIRES_VISION'));
|
|
2815
2871
|
const unconfirmed = solveResults.some(r => /unconfirmed|shows an error/i.test(r));
|
|
@@ -2826,17 +2882,11 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2826
2882
|
}
|
|
2827
2883
|
}
|
|
2828
2884
|
const clicked = await clickField([
|
|
2829
|
-
'button[type="submit"]',
|
|
2830
|
-
'
|
|
2831
|
-
'button:has-text("Next")', 'button:has-text("
|
|
2832
|
-
'button:has-text("
|
|
2833
|
-
'button
|
|
2834
|
-
'button:has-text("Create")', 'button:has-text("create")',
|
|
2835
|
-
'button:has-text("Sign up")', 'button:has-text("sign up")',
|
|
2836
|
-
'button:has-text("Register")', 'button:has-text("register")',
|
|
2837
|
-
'button:has-text("Accept")', 'button:has-text("accept")',
|
|
2838
|
-
'#iSignupAction', '#signup-button', '#submit-btn',
|
|
2839
|
-
'button.fui-Button[type="button"]:visible',
|
|
2885
|
+
'button[type="submit"]', 'input[type="submit"]',
|
|
2886
|
+
'button:has-text("Sign up")', 'button:has-text("Register")',
|
|
2887
|
+
'button:has-text("Next")', 'button:has-text("Continue")',
|
|
2888
|
+
'button:has-text("Submit")', 'button:has-text("Create")',
|
|
2889
|
+
'#signup-button', '#submit-btn',
|
|
2840
2890
|
], 'Submit/Next button');
|
|
2841
2891
|
await p.waitForTimeout(2000);
|
|
2842
2892
|
results.push('');
|
|
@@ -2881,6 +2931,27 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2881
2931
|
}
|
|
2882
2932
|
const results = [];
|
|
2883
2933
|
results.push('=== SIGNIN ASSIST ===');
|
|
2934
|
+
const cookieSelectors = [
|
|
2935
|
+
'button:has-text("Accept All")', 'button:has-text("Accept all")', 'button:has-text("accept all")',
|
|
2936
|
+
'button:has-text("Accept")', 'button:has-text("Accept Cookies")',
|
|
2937
|
+
'button:has-text("I agree")', 'button:has-text("Got it")', 'button:has-text("OK")',
|
|
2938
|
+
'button:has-text("Allow All")', 'button:has-text("Allow all")',
|
|
2939
|
+
'[id*="cookie"] button', '[class*="cookie"] button',
|
|
2940
|
+
'[id*="consent"] button', '[class*="consent"] button',
|
|
2941
|
+
'.cc-accept', '.cookie-accept', '#accept-cookies',
|
|
2942
|
+
];
|
|
2943
|
+
for (const sel of cookieSelectors) {
|
|
2944
|
+
try {
|
|
2945
|
+
const btn = p.locator(sel).first();
|
|
2946
|
+
if (await btn.count() > 0 && await btn.isVisible()) {
|
|
2947
|
+
await btn.click({ timeout: 2000 });
|
|
2948
|
+
results.push(` ✓ Dismissed cookie banner: ${sel}`);
|
|
2949
|
+
await p.waitForTimeout(500);
|
|
2950
|
+
break;
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
catch { }
|
|
2954
|
+
}
|
|
2884
2955
|
const allFrames = [p, ...p.frames().filter(f => f !== p.mainFrame())];
|
|
2885
2956
|
let activeFrame = p;
|
|
2886
2957
|
for (const frame of allFrames) {
|
|
@@ -2901,7 +2972,13 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2901
2972
|
results.push(` ✓ ${label}: already filled`);
|
|
2902
2973
|
return true;
|
|
2903
2974
|
}
|
|
2904
|
-
|
|
2975
|
+
try {
|
|
2976
|
+
await loc.fill(val, { timeout: 1500 });
|
|
2977
|
+
}
|
|
2978
|
+
catch {
|
|
2979
|
+
await loc.click({ timeout: 1500 });
|
|
2980
|
+
await loc.pressSequentially(val, { delay: 30, timeout: 5000 });
|
|
2981
|
+
}
|
|
2905
2982
|
results.push(` ✓ ${label}: filled`);
|
|
2906
2983
|
return true;
|
|
2907
2984
|
}
|
|
@@ -2920,7 +2997,7 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2920
2997
|
results.push(` ✓ ${label}: already checked`);
|
|
2921
2998
|
return true;
|
|
2922
2999
|
}
|
|
2923
|
-
await loc.click({ timeout:
|
|
3000
|
+
await loc.click({ timeout: 1500 });
|
|
2924
3001
|
results.push(` ✓ ${label}: clicked`);
|
|
2925
3002
|
return true;
|
|
2926
3003
|
}
|
|
@@ -2969,7 +3046,16 @@ The browser profile persists at ~/.aurix-browser-profile — if the user is logg
|
|
|
2969
3046
|
results.push('');
|
|
2970
3047
|
results.push('--- Verification step detected ---');
|
|
2971
3048
|
results.push('Attempting to complete automatically...');
|
|
2972
|
-
|
|
3049
|
+
let solveResults;
|
|
3050
|
+
try {
|
|
3051
|
+
solveResults = await Promise.race([
|
|
3052
|
+
autoSolveCaptcha(p),
|
|
3053
|
+
new Promise((_, rej) => setTimeout(() => rej(new Error('auto-solve timed out (30s)')), 30000)),
|
|
3054
|
+
]);
|
|
3055
|
+
}
|
|
3056
|
+
catch (e) {
|
|
3057
|
+
solveResults = [`Auto-solve: ${e.message}`];
|
|
3058
|
+
}
|
|
2973
3059
|
solveResults.forEach(r => results.push(` ${r}`));
|
|
2974
3060
|
const needsVision = solveResults.some(r => r.includes('VERIFICATION COMPLETION STEPS') || r.includes('REQUIRES_VISION'));
|
|
2975
3061
|
const unconfirmed = solveResults.some(r => /unconfirmed|shows an error/i.test(r));
|