@trusty-squire/mcp 0.9.16 → 0.9.17-rc.2
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/bot/affordance-probe.d.ts +15 -0
- package/dist/bot/affordance-probe.d.ts.map +1 -0
- package/dist/bot/affordance-probe.js +63 -0
- package/dist/bot/affordance-probe.js.map +1 -0
- package/dist/bot/agent.d.ts +31 -1
- package/dist/bot/agent.d.ts.map +1 -1
- package/dist/bot/agent.js +1826 -129
- package/dist/bot/agent.js.map +1 -1
- package/dist/bot/browser.d.ts +9 -0
- package/dist/bot/browser.d.ts.map +1 -1
- package/dist/bot/browser.js +281 -8
- package/dist/bot/browser.js.map +1 -1
- package/dist/bot/extraction.d.ts +18 -0
- package/dist/bot/extraction.d.ts.map +1 -0
- package/dist/bot/extraction.js +55 -0
- package/dist/bot/extraction.js.map +1 -0
- package/dist/bot/form-fill.d.ts +144 -0
- package/dist/bot/form-fill.d.ts.map +1 -0
- package/dist/bot/form-fill.js +320 -0
- package/dist/bot/form-fill.js.map +1 -0
- package/dist/bot/google-login.d.ts.map +1 -1
- package/dist/bot/google-login.js +6 -2
- package/dist/bot/google-login.js.map +1 -1
- package/dist/bot/llm-client.d.ts +12 -0
- package/dist/bot/llm-client.d.ts.map +1 -1
- package/dist/bot/llm-client.js +99 -0
- package/dist/bot/llm-client.js.map +1 -1
- package/dist/bot/nav-search.d.ts +80 -0
- package/dist/bot/nav-search.d.ts.map +1 -0
- package/dist/bot/nav-search.js +409 -0
- package/dist/bot/nav-search.js.map +1 -0
- package/dist/bot/oauth-flow.d.ts +48 -0
- package/dist/bot/oauth-flow.d.ts.map +1 -0
- package/dist/bot/oauth-flow.js +111 -0
- package/dist/bot/oauth-flow.js.map +1 -0
- package/dist/bot/onboarding-capture.d.ts +4 -0
- package/dist/bot/onboarding-capture.d.ts.map +1 -1
- package/dist/bot/onboarding-capture.js +5 -0
- package/dist/bot/onboarding-capture.js.map +1 -1
- package/dist/bot/redact.d.ts +1 -0
- package/dist/bot/redact.d.ts.map +1 -1
- package/dist/bot/redact.js +46 -0
- package/dist/bot/redact.js.map +1 -1
- package/dist/skill-registry-client.d.ts +4 -0
- package/dist/skill-registry-client.d.ts.map +1 -1
- package/dist/skill-registry-client.js +4 -0
- package/dist/skill-registry-client.js.map +1 -1
- package/dist/tools/provision-any.d.ts +21 -0
- package/dist/tools/provision-any.d.ts.map +1 -1
- package/dist/tools/provision-any.js +16 -7
- package/dist/tools/provision-any.js.map +1 -1
- package/dist/tools/signup-telemetry.d.ts +6 -0
- package/dist/tools/signup-telemetry.d.ts.map +1 -1
- package/dist/tools/signup-telemetry.js +4 -0
- package/dist/tools/signup-telemetry.js.map +1 -1
- package/package.json +1 -1
package/dist/bot/browser.d.ts
CHANGED
|
@@ -56,6 +56,8 @@ export declare class BrowserController {
|
|
|
56
56
|
private proxyServer;
|
|
57
57
|
private readonly profileDir;
|
|
58
58
|
private oauthProductPage;
|
|
59
|
+
private oauthNetLog;
|
|
60
|
+
private oauthNetListenerAttached;
|
|
59
61
|
private xvfb;
|
|
60
62
|
private launchedMode;
|
|
61
63
|
get launchMode(): "display" | "xvfb" | "headless" | "unknown";
|
|
@@ -65,6 +67,7 @@ export declare class BrowserController {
|
|
|
65
67
|
get proxied(): string | null;
|
|
66
68
|
get stealthProfile(): StealthProfile;
|
|
67
69
|
private launchSelfManagedContext;
|
|
70
|
+
private installResourceBlocking;
|
|
68
71
|
start(): Promise<void>;
|
|
69
72
|
private probeEgressGeo;
|
|
70
73
|
private resolveProxy;
|
|
@@ -114,6 +117,7 @@ export declare class BrowserController {
|
|
|
114
117
|
getState(): Promise<BrowserState>;
|
|
115
118
|
private snapshotState;
|
|
116
119
|
extractText(): Promise<string>;
|
|
120
|
+
extractVisibleText(): Promise<string>;
|
|
117
121
|
readClipboard(): Promise<string>;
|
|
118
122
|
extractAllInputValues(): Promise<string[]>;
|
|
119
123
|
extractCredentialsNearCopyButtons(): Promise<string[]>;
|
|
@@ -144,6 +148,8 @@ export declare class BrowserController {
|
|
|
144
148
|
name: string | null;
|
|
145
149
|
}>;
|
|
146
150
|
startOAuth(selector: string): Promise<void>;
|
|
151
|
+
private maybeAttachOAuthNetListener;
|
|
152
|
+
dumpOAuthDebug(service: string, label: string): Promise<void>;
|
|
147
153
|
getMetaCsrfToken(): Promise<string | null>;
|
|
148
154
|
getElementAttribute(selector: string, attr: string): Promise<string | null>;
|
|
149
155
|
submitPostForm(action: string, fields: Record<string, string>): Promise<void>;
|
|
@@ -153,6 +159,8 @@ export declare class BrowserController {
|
|
|
153
159
|
via: "fedcm" | "popup" | "none";
|
|
154
160
|
}>;
|
|
155
161
|
currentUrl(): string;
|
|
162
|
+
pressKey(key: string): Promise<void>;
|
|
163
|
+
expandLatentNav(): Promise<void>;
|
|
156
164
|
fetchText(url: string): Promise<{
|
|
157
165
|
finalUrl: string;
|
|
158
166
|
status: number;
|
|
@@ -161,6 +169,7 @@ export declare class BrowserController {
|
|
|
161
169
|
oauthPageClosed(): boolean;
|
|
162
170
|
detectSessionProviders(): Promise<OAuthProviderId[]>;
|
|
163
171
|
advanceOAuthConsent(provider: OAuthProviderId): Promise<boolean>;
|
|
172
|
+
waitForClerkSession(timeoutMs?: number): Promise<boolean>;
|
|
164
173
|
settleAfterOAuth(): Promise<void>;
|
|
165
174
|
close(): Promise<void>;
|
|
166
175
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/bot/browser.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAS5D,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,cAAc,CAAC;AAoFzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,wBAAwB;IAKvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAInB,UAAU,CAAC,EAAE,MAAM,CAAC;IAMpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,CAAC;AAQjE,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,GACtE,eAAe,EAAE,CAwBnB;AASD,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,cAAc,GACd,cAAc,GACd,UAAU,GACV,SAAS,CAAC;AAed,MAAM,MAAM,kBAAkB,GAC1B;IAAE,KAAK,EAAE,KAAK,CAAA;CAAE,GAChB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAChD;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAAC;AA+FtD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAe1E;AAsBD,wBAAgB,iBAAiB,IAAI,OAAO,CAG3C;AA8CD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG;IACtD,cAAc,EAAE,OAAO,CAAC;IACxB,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAUA;AAYD,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5E;AAED,qBAAa,iBAAiB;IAI5B,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAqB;IAIjC,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,UAAU,CAAwB;IAK1C,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IAGnC,OAAO,CAAC,MAAM,CAAO;IACrB,OAAO,CAAC,MAAM,CAAO;IAMrB,OAAO,CAAC,eAAe,CAAuB;IAK9C,OAAO,CAAC,WAAW,CAAuB;IAE1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAMpC,OAAO,CAAC,gBAAgB,CAAqB;
|
|
1
|
+
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/bot/browser.ts"],"names":[],"mappings":"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"}
|
package/dist/bot/browser.js
CHANGED
|
@@ -390,6 +390,12 @@ export class BrowserController {
|
|
|
390
390
|
// parked here so settleAfterOAuth() can switch back to it once the
|
|
391
391
|
// Google handshake completes.
|
|
392
392
|
oauthProductPage = null;
|
|
393
|
+
// Deep-investigation instrumentation (UNIVERSAL_BOT_OAUTH_DEBUG): a ring
|
|
394
|
+
// buffer of OAuth/SSO-relevant network responses, so we can see WHY a Clerk/
|
|
395
|
+
// Stytch SSO callback fails to persist a session (cookie not set, FAPI
|
|
396
|
+
// rejection, etc.) without guessing. Off by default; zero cost when unset.
|
|
397
|
+
oauthNetLog = [];
|
|
398
|
+
oauthNetListenerAttached = false;
|
|
393
399
|
// F13 — on-demand Xvfb. Set when start() determined the host has no
|
|
394
400
|
// display surface but Xvfb is available, so Chrome can run with
|
|
395
401
|
// `headless: false` against a virtual display (Cloudflare/Stytch et
|
|
@@ -501,6 +507,60 @@ export class BrowserController {
|
|
|
501
507
|
}
|
|
502
508
|
return ctx;
|
|
503
509
|
}
|
|
510
|
+
// Resource blocking for speed (BOT_BLOCK_RESOURCES, default OFF). Aborts
|
|
511
|
+
// image/media/font requests + known analytics/tracker hosts to cut page-load
|
|
512
|
+
// wall-clock (3-5x on byte-heavy pages; also stops trackers from holding the
|
|
513
|
+
// network "busy"). HARD ALLOW-GUARD first for captcha/challenge + payment
|
|
514
|
+
// scripts (blocking those breaks the Turnstile/hCaptcha token poll and the
|
|
515
|
+
// signup form). CSS + first-party JS are never blocked (not in BLOCK_TYPES) —
|
|
516
|
+
// the SPA form renders from them and the vision planner reads the styled
|
|
517
|
+
// render. DUAL RISK, hence default-OFF + an OF#2 A/B before flipping on:
|
|
518
|
+
// (1) a browser that loads ZERO images is itself an anti-bot fingerprint;
|
|
519
|
+
// (2) the screenshot the vision planner reads loses detail — mitigated
|
|
520
|
+
// because the DOM inventory is the authoritative action space, but
|
|
521
|
+
// still a regression risk on image-only affordances.
|
|
522
|
+
// Registered on the CONTEXT so it covers OAuth popups + iframes.
|
|
523
|
+
async installResourceBlocking() {
|
|
524
|
+
const ctx = this.context;
|
|
525
|
+
if (ctx === null)
|
|
526
|
+
return;
|
|
527
|
+
if (!/^(1|true|on)$/i.test(process.env.BOT_BLOCK_RESOURCES ?? ""))
|
|
528
|
+
return;
|
|
529
|
+
const BLOCK_TYPES = new Set(["image", "media", "font"]);
|
|
530
|
+
const BLOCK_HOSTS = [
|
|
531
|
+
"google-analytics.com", "googletagmanager.com", "analytics.google.com",
|
|
532
|
+
"doubleclick.net", "static.hotjar.com", "script.hotjar.com",
|
|
533
|
+
"segment.com", "segment.io", "cdn.segment.com", "fullstory.com",
|
|
534
|
+
"mixpanel.com", "bugsnag.com", "intercom.io", "intercomcdn.com",
|
|
535
|
+
"widget.intercom.io", "connect.facebook.net", "analytics.tiktok.com",
|
|
536
|
+
"clarity.ms", "cdn.heapanalytics.com", "wistia.com",
|
|
537
|
+
];
|
|
538
|
+
// NEVER block — these break signup (captcha/challenge widgets + payment SDK).
|
|
539
|
+
const ALWAYS_ALLOW = [
|
|
540
|
+
"challenges.cloudflare.com", "turnstile", "hcaptcha.com",
|
|
541
|
+
"newassets.hcaptcha.com", "recaptcha", "gstatic.com/recaptcha",
|
|
542
|
+
"js.stripe.com",
|
|
543
|
+
];
|
|
544
|
+
await ctx.route("**/*", async (route) => {
|
|
545
|
+
try {
|
|
546
|
+
const url = route.request().url();
|
|
547
|
+
if (ALWAYS_ALLOW.some((h) => url.includes(h))) {
|
|
548
|
+
await route.continue();
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const type = route.request().resourceType();
|
|
552
|
+
if (BLOCK_TYPES.has(type) || BLOCK_HOSTS.some((h) => url.includes(h))) {
|
|
553
|
+
await route.abort();
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
await route.continue();
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
// Routing race / already-handled — never let a decision crash nav.
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
console.error("[universal-bot] resource blocking ON (image/media/font + analytics aborted; captcha/CSS/JS allowed)");
|
|
563
|
+
}
|
|
504
564
|
async start() {
|
|
505
565
|
const channel = await detectChromiumChannel();
|
|
506
566
|
this.launchedChannel = channel;
|
|
@@ -715,6 +775,8 @@ export class BrowserController {
|
|
|
715
775
|
this.context = context;
|
|
716
776
|
// We own the profile now — close() may reap a leaked Chrome.
|
|
717
777
|
this.launchedContext = true;
|
|
778
|
+
// Speed: optionally abort heavy/irrelevant requests before any navigation.
|
|
779
|
+
await this.installResourceBlocking();
|
|
718
780
|
// Patch navigator.webdriver — BASELINE ONLY. Measured against the
|
|
719
781
|
// rebrowser bot-detector, this manual `defineProperty` is
|
|
720
782
|
// COUNTERPRODUCTIVE under patchright: it re-adds `webdriver` as an own
|
|
@@ -1341,27 +1403,48 @@ export class BrowserController {
|
|
|
1341
1403
|
.$eval(selector, (el) => {
|
|
1342
1404
|
const t = el;
|
|
1343
1405
|
const inputKind = t.tagName === "INPUT" && (t.type === "radio" || t.type === "checkbox") ? t.type : "";
|
|
1406
|
+
// The planner's selector often resolves to a CHILD of the real option
|
|
1407
|
+
// (the inner <span> with the visible text, or a positional wrapper), not
|
|
1408
|
+
// the role=option element itself. Walk up to the nearest combobox-option
|
|
1409
|
+
// ancestor so the role-based re-resolution below fires. cmdk items carry
|
|
1410
|
+
// role=option but the `[cmdk-item]` attribute is the most stable tell.
|
|
1411
|
+
// MEASURED 2026-06-16 (meilisearch /welcome-informations cmdk multi-
|
|
1412
|
+
// select): a plain getByRole("option",{name}).click() COMMITS the value
|
|
1413
|
+
// — the trigger updates + Next un-gates — but only when we target the
|
|
1414
|
+
// option element, not its child span (which a raw coordinate click drops).
|
|
1415
|
+
const optEl = el.closest('[role="option"],[role="menuitem"],[role="menuitemradio"],[cmdk-item]');
|
|
1416
|
+
const optRole = optEl !== null ? optEl.getAttribute("role") ?? "option" : "";
|
|
1417
|
+
const optText = optEl !== null ? (optEl.textContent ?? "").trim().slice(0, 80) : "";
|
|
1344
1418
|
return {
|
|
1345
1419
|
inputKind,
|
|
1346
1420
|
role: el.getAttribute("role") ?? "",
|
|
1347
1421
|
text: (el.textContent ?? "").trim().slice(0, 80),
|
|
1422
|
+
optRole,
|
|
1423
|
+
optText,
|
|
1348
1424
|
};
|
|
1349
1425
|
})
|
|
1350
|
-
.catch(() => ({ inputKind: "", role: "", text: "" }));
|
|
1426
|
+
.catch(() => ({ inputKind: "", role: "", text: "", optRole: "", optText: "" }));
|
|
1351
1427
|
const inputKind = probe.inputKind;
|
|
1352
1428
|
// Custom-combobox / listbox options (role=option|menuitem) — react-select,
|
|
1353
|
-
// Radix, downshift, MUI. Two failure modes the humanized RAW-COORDINATE
|
|
1429
|
+
// Radix, downshift, cmdk, MUI. Two failure modes the humanized RAW-COORDINATE
|
|
1354
1430
|
// click hits: (1) the menu is a PORTAL that re-renders/repositions, so the
|
|
1355
1431
|
// captured POSITIONAL selector (e.g. `div…>> nth=42`) resolves to the wrong
|
|
1356
1432
|
// element at click time — nothing selects, planner loops (MEASURED
|
|
1357
1433
|
// 2026-06-11, meilisearch Radix combobox); (2) options bind pointer/select
|
|
1358
1434
|
// handlers a raw coordinate click misses. Fix: re-resolve by role+accessible
|
|
1359
|
-
// name (robust to portal/positional drift
|
|
1360
|
-
// locator click. Options are post-load,
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1435
|
+
// name (robust to portal/positional drift + the planner targeting a child),
|
|
1436
|
+
// and use the actionability-checked locator click. Options are post-load,
|
|
1437
|
+
// NOT the anti-bot-scored gate.
|
|
1438
|
+
const optRole = probe.role === "option" || probe.role === "menuitem" || probe.role === "menuitemradio"
|
|
1439
|
+
? probe.role
|
|
1440
|
+
: probe.optRole === "option" || probe.optRole === "menuitem" || probe.optRole === "menuitemradio"
|
|
1441
|
+
? probe.optRole
|
|
1442
|
+
: "";
|
|
1443
|
+
const optName = probe.role !== "" ? probe.text : probe.optText;
|
|
1444
|
+
if (optRole !== "") {
|
|
1445
|
+
const role = optRole;
|
|
1446
|
+
if (optName.length > 0) {
|
|
1447
|
+
const byName = this.page.getByRole(role, { name: optName, exact: false }).first();
|
|
1365
1448
|
if ((await byName.count().catch(() => 0)) > 0) {
|
|
1366
1449
|
await byName.click({ timeout: 8000 });
|
|
1367
1450
|
return;
|
|
@@ -3111,6 +3194,18 @@ export class BrowserController {
|
|
|
3111
3194
|
if (k !== null && k.length > 10)
|
|
3112
3195
|
return k;
|
|
3113
3196
|
}
|
|
3197
|
+
// INVISIBLE hCaptcha (huggingface, 2026-06-17): no .h-captcha div, no
|
|
3198
|
+
// rendered iframe — the sitekey lives in the page's JS config
|
|
3199
|
+
// (`captchaApiKey:"<uuid>"`, `sitekey:"<uuid>"`). Scan the HTML for a
|
|
3200
|
+
// UUID-shaped key next to a sitekey/captcha hint, but ONLY when an
|
|
3201
|
+
// hCaptcha script is present (so an unrelated config UUID can't match).
|
|
3202
|
+
// UUID shape excludes reCAPTCHA `6L…` and Turnstile `0x…` keys.
|
|
3203
|
+
const html = document.documentElement.outerHTML;
|
|
3204
|
+
if (/hcaptcha\.com|h-captcha|hcaptcha/i.test(html)) {
|
|
3205
|
+
const m = html.match(/(?:sitekey|captchaApiKey|data-(?:hcaptcha-)?sitekey)["'\s]*[:=]\s*["']([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})["']/i);
|
|
3206
|
+
if (m !== null && m[1] !== undefined)
|
|
3207
|
+
return m[1];
|
|
3208
|
+
}
|
|
3114
3209
|
return null;
|
|
3115
3210
|
});
|
|
3116
3211
|
}
|
|
@@ -3226,6 +3321,21 @@ export class BrowserController {
|
|
|
3226
3321
|
throw new Error("Browser not started");
|
|
3227
3322
|
return await this.page.textContent("body") || "";
|
|
3228
3323
|
}
|
|
3324
|
+
// RENDERED, visibility-respecting body text. extractText() reads
|
|
3325
|
+
// textContent("body"), which includes display:none / visibility:hidden /
|
|
3326
|
+
// off-screen nodes — so a fully-rendered dashboard whose DOM merely
|
|
3327
|
+
// CONTAINS a hidden skeleton / "Loading…" / "Please wait 30 seconds…"
|
|
3328
|
+
// string (Next.js RSC inline payloads, lazy placeholders, aria-hidden
|
|
3329
|
+
// spinners) reads as still-loading and false-trips the loading-shell gate.
|
|
3330
|
+
// innerText is layout-aware: it omits hidden text and reflects what a user
|
|
3331
|
+
// would actually see. Use this for the SHELL decision ONLY — credential/key
|
|
3332
|
+
// extraction and wall-text checks deliberately read RAW text via
|
|
3333
|
+
// extractText() and must stay byte-identical, so this is purely additive.
|
|
3334
|
+
async extractVisibleText() {
|
|
3335
|
+
if (!this.page)
|
|
3336
|
+
throw new Error("Browser not started");
|
|
3337
|
+
return await this.page.evaluate(() => document.body?.innerText ?? "");
|
|
3338
|
+
}
|
|
3229
3339
|
// Discrete strings an API key might occupy — for credential
|
|
3230
3340
|
// extraction. Gathered so a key is read WHOLE and un-glued from its
|
|
3231
3341
|
// neighbours: extractText() concatenates the whole <body>, which
|
|
@@ -4629,6 +4739,7 @@ export class BrowserController {
|
|
|
4629
4739
|
async startOAuth(selector) {
|
|
4630
4740
|
if (!this.page || !this.context)
|
|
4631
4741
|
throw new Error("Browser not started");
|
|
4742
|
+
this.maybeAttachOAuthNetListener();
|
|
4632
4743
|
this.oauthProductPage = this.page;
|
|
4633
4744
|
// Race a popup `page` event against the click. context-level
|
|
4634
4745
|
// "page" fires for both window.open popups and target=_blank.
|
|
@@ -4647,6 +4758,109 @@ export class BrowserController {
|
|
|
4647
4758
|
// best-effort — the agent's consent loop re-reads state regardless
|
|
4648
4759
|
}
|
|
4649
4760
|
}
|
|
4761
|
+
// ── OAuth/SSO debug instrumentation (UNIVERSAL_BOT_OAUTH_DEBUG) ──
|
|
4762
|
+
// Attach a context-level response recorder ONCE. Records SSO-relevant
|
|
4763
|
+
// responses (the service host + Clerk/Stytch/WorkOS FAPI hosts) with their
|
|
4764
|
+
// status + whether they set a cookie — the signal for "did the callback's
|
|
4765
|
+
// session-establish request succeed and set the session cookie?"
|
|
4766
|
+
maybeAttachOAuthNetListener() {
|
|
4767
|
+
if (this.oauthNetListenerAttached)
|
|
4768
|
+
return;
|
|
4769
|
+
if (!/^(1|true|on)$/i.test(process.env.UNIVERSAL_BOT_OAUTH_DEBUG ?? ""))
|
|
4770
|
+
return;
|
|
4771
|
+
if (!this.context)
|
|
4772
|
+
return;
|
|
4773
|
+
this.oauthNetListenerAttached = true;
|
|
4774
|
+
const RELEVANT = /clerk|stytch|workos|accounts\.|\/sso|\/oauth|\/session|\/sign|callback|\/v1\/client/i;
|
|
4775
|
+
this.context.on("response", (res) => {
|
|
4776
|
+
void (async () => {
|
|
4777
|
+
try {
|
|
4778
|
+
const url = res.url();
|
|
4779
|
+
if (!RELEVANT.test(url))
|
|
4780
|
+
return;
|
|
4781
|
+
const headers = res.headers();
|
|
4782
|
+
if (this.oauthNetLog.length >= 200)
|
|
4783
|
+
return;
|
|
4784
|
+
const entry = {
|
|
4785
|
+
url: url.slice(0, 200),
|
|
4786
|
+
status: res.status(),
|
|
4787
|
+
setCookie: "set-cookie" in headers || "Set-Cookie" in headers,
|
|
4788
|
+
ct: (headers["content-type"] ?? "").slice(0, 40),
|
|
4789
|
+
};
|
|
4790
|
+
// Capture the body of a Clerk/Stytch/WorkOS sign-in/up/callback error
|
|
4791
|
+
// (>=400) — its error code is the definitive tell (captcha_invalid vs
|
|
4792
|
+
// transfer vs identifier_*). JSON only, bounded.
|
|
4793
|
+
if (res.status() >= 400 && /\/v1\/client\/(sign_ins|sign_ups)|oauth_callback|\/session/i.test(url)) {
|
|
4794
|
+
entry.body = (await res.text().catch(() => "")).slice(0, 800);
|
|
4795
|
+
}
|
|
4796
|
+
this.oauthNetLog.push(entry);
|
|
4797
|
+
}
|
|
4798
|
+
catch {
|
|
4799
|
+
// best-effort observability — never perturb the run
|
|
4800
|
+
}
|
|
4801
|
+
})();
|
|
4802
|
+
});
|
|
4803
|
+
}
|
|
4804
|
+
// Dump cookies + the SSO network log to a file for post-mortem. Called at the
|
|
4805
|
+
// oauth_session_not_persisted decision point when UNIVERSAL_BOT_OAUTH_DEBUG.
|
|
4806
|
+
async dumpOAuthDebug(service, label) {
|
|
4807
|
+
if (!/^(1|true|on)$/i.test(process.env.UNIVERSAL_BOT_OAUTH_DEBUG ?? ""))
|
|
4808
|
+
return;
|
|
4809
|
+
if (!this.context)
|
|
4810
|
+
return;
|
|
4811
|
+
try {
|
|
4812
|
+
const cookies = await this.context.cookies();
|
|
4813
|
+
const cookieSummary = cookies.map((c) => ({
|
|
4814
|
+
name: c.name,
|
|
4815
|
+
domain: c.domain,
|
|
4816
|
+
path: c.path,
|
|
4817
|
+
len: c.value.length,
|
|
4818
|
+
httpOnly: c.httpOnly,
|
|
4819
|
+
secure: c.secure,
|
|
4820
|
+
sameSite: c.sameSite,
|
|
4821
|
+
}));
|
|
4822
|
+
const url = this.page ? this.page.url() : "(no page)";
|
|
4823
|
+
// Capture the live Clerk SDK state — the definitive read on whether a
|
|
4824
|
+
// sign-up transfer is available (the new-user-OAuth fix hinges on this).
|
|
4825
|
+
const clerkState = this.page
|
|
4826
|
+
? await this.page
|
|
4827
|
+
.evaluate(() => {
|
|
4828
|
+
const w = window;
|
|
4829
|
+
const c = w.Clerk;
|
|
4830
|
+
if (c === undefined)
|
|
4831
|
+
return { present: false };
|
|
4832
|
+
const client = c.client;
|
|
4833
|
+
const si = client?.["signIn"];
|
|
4834
|
+
const su = client?.["signUp"];
|
|
4835
|
+
const ffv = si?.["firstFactorVerification"];
|
|
4836
|
+
return {
|
|
4837
|
+
present: true,
|
|
4838
|
+
loaded: c.loaded ?? null,
|
|
4839
|
+
signInStatus: si?.["status"] ?? null,
|
|
4840
|
+
signInFFVStatus: ffv?.["status"] ?? null,
|
|
4841
|
+
signInFFVError: ffv?.["error"] ?? null,
|
|
4842
|
+
signUpStatus: su?.["status"] ?? null,
|
|
4843
|
+
signUpMissingFields: su?.["missingFields"] ?? null,
|
|
4844
|
+
hasSignUpCreate: typeof su?.create === "function",
|
|
4845
|
+
};
|
|
4846
|
+
})
|
|
4847
|
+
.catch((e) => ({ present: "evalError", err: String(e).slice(0, 120) }))
|
|
4848
|
+
: { present: false };
|
|
4849
|
+
const consoleText = await this.extractText().catch(() => "");
|
|
4850
|
+
const { writeFileSync, mkdirSync } = await import("node:fs");
|
|
4851
|
+
const { join } = await import("node:path");
|
|
4852
|
+
const { homedir } = await import("node:os");
|
|
4853
|
+
const dir = join(homedir(), ".trusty-squire", "oauth-debug");
|
|
4854
|
+
mkdirSync(dir, { recursive: true });
|
|
4855
|
+
const ts = process.env.OAUTH_DEBUG_TS ?? String(this.oauthNetLog.length);
|
|
4856
|
+
const path = join(dir, `${service}-${label}-${ts}.json`);
|
|
4857
|
+
writeFileSync(path, JSON.stringify({ service, label, finalUrl: url, clerkState, cookies: cookieSummary, netLog: this.oauthNetLog, pageText: consoleText.slice(0, 600) }, null, 2));
|
|
4858
|
+
console.error(`[oauth-debug] wrote ${path} (${cookieSummary.length} cookies, ${this.oauthNetLog.length} net entries)`);
|
|
4859
|
+
}
|
|
4860
|
+
catch (err) {
|
|
4861
|
+
console.error(`[oauth-debug] dump failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
4862
|
+
}
|
|
4863
|
+
}
|
|
4650
4864
|
// Read the page's Rails/OmniAuth CSRF token (<meta name="csrf-token">).
|
|
4651
4865
|
// Needed to recover OmniAuth 2.0 POST-only OAuth when the provider button is
|
|
4652
4866
|
// a GET <a> that page-JS upgrades to a POST.
|
|
@@ -4896,6 +5110,39 @@ export class BrowserController {
|
|
|
4896
5110
|
currentUrl() {
|
|
4897
5111
|
return this.page !== null ? this.page.url() : "";
|
|
4898
5112
|
}
|
|
5113
|
+
// Press a keyboard key (e.g. "Escape" to dismiss a focus-trapped modal that
|
|
5114
|
+
// exposes no in-DOM close control). Best-effort. Used by the nav-search
|
|
5115
|
+
// overlay handler's dismiss fallback.
|
|
5116
|
+
async pressKey(key) {
|
|
5117
|
+
if (!this.page)
|
|
5118
|
+
return;
|
|
5119
|
+
await this.page.keyboard.press(key).catch(() => { });
|
|
5120
|
+
}
|
|
5121
|
+
// Open obvious collapsed menus (hamburger / avatar / account / "Settings"
|
|
5122
|
+
// toggles) so nav links hidden behind them mount in the DOM before the
|
|
5123
|
+
// nav-search enumerates candidates (outside-voice #1: the keys link is often
|
|
5124
|
+
// behind a menu, not in the rendered top nav). CONSERVATIVE: only clicks
|
|
5125
|
+
// elements that ADVERTISE a popup menu (aria-haspopup=menu/true), capped at 3,
|
|
5126
|
+
// short timeouts, best-effort — never a plain link, so it can't wander.
|
|
5127
|
+
async expandLatentNav() {
|
|
5128
|
+
if (!this.page)
|
|
5129
|
+
return;
|
|
5130
|
+
try {
|
|
5131
|
+
const n = await this.page
|
|
5132
|
+
.$$eval('[aria-haspopup="menu"], [aria-haspopup="true"]', (els) => {
|
|
5133
|
+
const slice = els.slice(0, 3);
|
|
5134
|
+
slice.forEach((e, i) => e.setAttribute("data-navsearch-toggle", String(i)));
|
|
5135
|
+
return slice.length;
|
|
5136
|
+
})
|
|
5137
|
+
.catch(() => 0);
|
|
5138
|
+
for (let i = 0; i < n; i++) {
|
|
5139
|
+
await this.page.click(`[data-navsearch-toggle="${i}"]`, { timeout: 1200 }).catch(() => { });
|
|
5140
|
+
}
|
|
5141
|
+
}
|
|
5142
|
+
catch {
|
|
5143
|
+
// best-effort — never fail the search over menu expansion
|
|
5144
|
+
}
|
|
5145
|
+
}
|
|
4899
5146
|
// Fetch a URL's final response (following redirects) and return its
|
|
4900
5147
|
// status, final URL, and body text — or null on any failure.
|
|
4901
5148
|
//
|
|
@@ -5133,6 +5380,32 @@ export class BrowserController {
|
|
|
5133
5380
|
`${seen.length === 0 ? "<none>" : seen.map((s) => JSON.stringify(s)).join(", ")}`);
|
|
5134
5381
|
return false;
|
|
5135
5382
|
}
|
|
5383
|
+
// Wait on a Clerk callback for a session to establish, polling COOKIES (which
|
|
5384
|
+
// are world-agnostic — unlike window.Clerk, invisible to our isolated-world
|
|
5385
|
+
// page.evaluate under patchright). Clerk's main-world JS, if left alone on the
|
|
5386
|
+
// /sso-callback page (not navigated away), completes the new-user sign-up
|
|
5387
|
+
// transfer and sets a session; this detects that. Returns true once a Clerk
|
|
5388
|
+
// session indicator appears (`__session` cookie, or `__client_uat` flips off
|
|
5389
|
+
// "0"), false on timeout. Cheap + safe: only the bot's own context cookies.
|
|
5390
|
+
async waitForClerkSession(timeoutMs = 12000) {
|
|
5391
|
+
if (!this.context)
|
|
5392
|
+
return false;
|
|
5393
|
+
const deadline = Date.now() + timeoutMs;
|
|
5394
|
+
while (Date.now() < deadline) {
|
|
5395
|
+
try {
|
|
5396
|
+
const cookies = await this.context.cookies();
|
|
5397
|
+
const signedIn = cookies.some((c) => (c.name === "__session" && c.value.length > 0) ||
|
|
5398
|
+
(c.name.startsWith("__client_uat") && c.value.length > 0 && c.value !== "0"));
|
|
5399
|
+
if (signedIn)
|
|
5400
|
+
return true;
|
|
5401
|
+
}
|
|
5402
|
+
catch {
|
|
5403
|
+
// transient — keep polling
|
|
5404
|
+
}
|
|
5405
|
+
await this.sleep(1000);
|
|
5406
|
+
}
|
|
5407
|
+
return false;
|
|
5408
|
+
}
|
|
5136
5409
|
// Restore the product page once the OAuth handshake completes. A
|
|
5137
5410
|
// no-op for the same-tab redirect flow (the active page already IS
|
|
5138
5411
|
// the product page); for the popup flow, waits briefly for the popup
|