@trusty-squire/mcp 0.6.14 → 0.6.15-rc.10
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/assets/screencaps/connect-walkthrough.png +0 -0
- package/assets/screencaps/connect-walkthrough.svg +6 -0
- package/dist/bot/agent.d.ts +1 -0
- package/dist/bot/agent.d.ts.map +1 -1
- package/dist/bot/agent.js +167 -7
- package/dist/bot/agent.js.map +1 -1
- package/dist/bot/browser.d.ts +1 -0
- package/dist/bot/browser.d.ts.map +1 -1
- package/dist/bot/browser.js +51 -1
- package/dist/bot/browser.js.map +1 -1
- package/dist/bot/google-login.d.ts.map +1 -1
- package/dist/bot/google-login.js +79 -23
- package/dist/bot/google-login.js.map +1 -1
- package/dist/bot/notify-api.d.ts +7 -0
- package/dist/bot/notify-api.d.ts.map +1 -0
- package/dist/bot/notify-api.js +41 -0
- package/dist/bot/notify-api.js.map +1 -0
- package/dist/bot/promote-to-skill.d.ts.map +1 -1
- package/dist/bot/promote-to-skill.js +161 -24
- package/dist/bot/promote-to-skill.js.map +1 -1
- package/dist/bot/replay-skill.js +86 -4
- package/dist/bot/replay-skill.js.map +1 -1
- package/dist/install/cli.d.ts +1 -0
- package/dist/install/cli.d.ts.map +1 -1
- package/dist/install/cli.js +169 -39
- package/dist/install/cli.js.map +1 -1
- package/dist/install/ui.d.ts +6 -2
- package/dist/install/ui.d.ts.map +1 -1
- package/dist/install/ui.js +108 -47
- package/dist/install/ui.js.map +1 -1
- package/dist/session.d.ts +1 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/tools/provision-any.d.ts.map +1 -1
- package/dist/tools/provision-any.js +25 -0
- package/dist/tools/provision-any.js.map +1 -1
- package/package.json +1 -1
|
Binary file
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg width="880.00" height="650.67" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<rect width="878.00" height="648.67" fill="#0d0d10" rx="8.00" ry="8.00" stroke="#1e1e23" stroke-width="1.00" x="0.50px" y="0.50px"/>
|
|
3
|
+
<g font-family="Menlo,'JetBrains Mono','Fira Code',Consolas,monospace" font-size="13.00px" fill="#c4c4c4" clip-path="url(#terminalMask)">
|
|
4
|
+
<text x="28.00px" y="61.85px" xml:space="preserve"/><text x="28.00px" y="80.70px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52"/><tspan xml:space="preserve">Trusty Squire</tspan></text><text x="28.00px" y="99.55px" xml:space="preserve"/><text x="28.00px" y="118.40px" xml:space="preserve"><tspan xml:space="preserve">Setting up this machine.</tspan></text><text x="28.00px" y="137.25px" xml:space="preserve"/><text x="28.00px" y="156.10px" xml:space="preserve"><tspan xml:space="preserve">Connect your Google and GitHub OAuth accounts so the bot can sign you</tspan></text><text x="28.00px" y="174.95px" xml:space="preserve"><tspan xml:space="preserve">up for any service — some support Google only, some GitHub only.</tspan></text><text x="28.00px" y="193.80px" xml:space="preserve"><tspan xml:space="preserve" fill="#31BB71"/><tspan xml:space="preserve">✓ Network detected</tspan></text><text x="28.00px" y="212.65px" xml:space="preserve"><tspan xml:space="preserve" fill="#31BB71"/><tspan xml:space="preserve">✓ Machine token issued</tspan></text><text x="28.00px" y="231.50px" xml:space="preserve"/><text x="28.00px" y="250.35px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52"/><tspan xml:space="preserve">1/2 · </tspan><tspan xml:space="preserve">Connect your Google account</tspan></text><text x="28.00px" y="269.20px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">┌ sign in ───────────────────────────────────────────────────────────────────┐</tspan></text><text x="28.00px" y="288.05px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ Open this URL to sign in and confirm: </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="306.90px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="325.75px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ </tspan><tspan xml:space="preserve" fill="#cf3a52"/><tspan xml:space="preserve" text-decoration="underline">https://vnc.trustysquire.ai/?p=k7m2x8q9p4r </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="344.60px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">└────────────────────────────────────────────────────────────────────────────┘</tspan></text><text x="28.00px" y="363.45px" xml:space="preserve"><tspan xml:space="preserve" fill="#31BB71"/><tspan xml:space="preserve">✓ Session saved (keytar)</tspan></text><text x="28.00px" y="382.30px" xml:space="preserve"><tspan xml:space="preserve" fill="#31BB71"/><tspan xml:space="preserve">✓ Wrote Cursor MCP config at ~/Library/.../mcp.json</tspan></text><text x="28.00px" y="401.15px" xml:space="preserve"/><text x="28.00px" y="420.00px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52"/><tspan xml:space="preserve">2/2 · </tspan><tspan xml:space="preserve">Connect your GitHub account</tspan></text><text x="28.00px" y="438.85px" xml:space="preserve"><tspan xml:space="preserve">Some services are GitHub-only (Railway, Vercel, parts of Cloudflare).</tspan></text><text x="28.00px" y="457.70px" xml:space="preserve"><tspan xml:space="preserve">Add GitHub? [Y/n] </tspan><tspan xml:space="preserve">y</tspan></text><text x="28.00px" y="476.55px" xml:space="preserve"><tspan xml:space="preserve">Opening browser for GitHub sign-in…</tspan></text><text x="28.00px" y="495.40px" xml:space="preserve"><tspan xml:space="preserve" fill="#31BB71"/><tspan xml:space="preserve">✓ GitHub session added.</tspan></text><text x="28.00px" y="514.25px" xml:space="preserve"><tspan xml:space="preserve">──────────────────────────────────────────────────────────────────────────────</tspan></text><text x="28.00px" y="533.10px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">┌────────────────────────────────────────────────────────────────────────────┐</tspan></text><text x="28.00px" y="551.95px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ Squire on duty. Restart Cursor to pick up the new tools. </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="570.80px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="589.65px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">│ Try it — ask your agent: </tspan><tspan xml:space="preserve"/><tspan xml:space="preserve" fill="#C5C8C6">"sign me up for Resend" </tspan><tspan xml:space="preserve" fill="#cf3a52">│</tspan></text><text x="28.00px" y="608.50px" xml:space="preserve"><tspan xml:space="preserve" fill="#cf3a52">└────────────────────────────────────────────────────────────────────────────┘</tspan></text>
|
|
5
|
+
</g>
|
|
6
|
+
<svg x="0.00px" y="0.00px"><circle cx="13.50" cy="12.00" r="5.50" fill="#FF5A54"/><circle cx="32.50" cy="12.00" r="5.50" fill="#E6BF29"/><circle cx="51.50" cy="12.00" r="5.50" fill="#52C12B"/></svg><defs><clipPath id="terminalMask"><rect x="0.00" y="0.00" width="878.00" height="620.67"/></clipPath></defs></svg>
|
package/dist/bot/agent.d.ts
CHANGED
|
@@ -155,6 +155,7 @@ export declare function detectAlreadySignedIn(args: {
|
|
|
155
155
|
inventory: readonly InteractiveElement[];
|
|
156
156
|
url: string;
|
|
157
157
|
}): boolean;
|
|
158
|
+
export declare function detectOAuthProvidersInInventory(inventory: readonly InteractiveElement[]): OAuthProviderId[];
|
|
158
159
|
export declare function isOauthOnlyChooser(inventory: readonly InteractiveElement[]): boolean;
|
|
159
160
|
export declare function findOAuthButton(inventory: readonly InteractiveElement[], provider: OAuthProviderId): InteractiveElement | null;
|
|
160
161
|
export declare function findFirstOAuthButton(inventory: readonly InteractiveElement[], providers: readonly OAuthProviderId[]): {
|
package/dist/bot/agent.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/bot/agent.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,iBAAiB,EAGjB,cAAc,EACd,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/bot/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/bot/agent.js
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
import { rankAndCapInventory, scoreSignupButton } from "./browser.js";
|
|
11
11
|
import { OAUTH_PROVIDERS, extractOAuthScopes, isGitHubDismissible2faSetup, GITHUB_DISMISSIBLE_2FA_SKIP_TEXT, } from "./oauth-providers.js";
|
|
12
12
|
import { extractGoogleNumberMatch, scrapeGoogleScopePhrases } from "./google-login.js";
|
|
13
|
+
import { notifyHeightenedAuth } from "./notify-api.js";
|
|
13
14
|
import { loggedInProviders, clearProviderLoggedIn } from "./login-state.js";
|
|
14
15
|
import { saveDebugSnapshot } from "./debug.js";
|
|
15
16
|
import { captureOnboardingRound } from "./onboarding-capture.js";
|
|
@@ -326,9 +327,26 @@ export function parseSignupPlan(raw, allowedSelectors) {
|
|
|
326
327
|
// Render the element inventory as a compact text block for the
|
|
327
328
|
// planner — one line per element, ending with the verified
|
|
328
329
|
// `selector=` the planner must copy verbatim (F3 T3).
|
|
330
|
+
//
|
|
331
|
+
// F15 — when multiple elements share the same effective text
|
|
332
|
+
// (visibleText / ariaLabel / labelText, normalized), tag each with
|
|
333
|
+
// its enclosing HTML5 landmark (header / main / footer / nav / etc.)
|
|
334
|
+
// so the planner has a discriminator. Without this, a Railway page
|
|
335
|
+
// with "Email" both in the body CTA and the footer made the planner
|
|
336
|
+
// pick the wrong one and loop. Single-occurrence text is rendered
|
|
337
|
+
// without the landmark tag to keep the inventory terse.
|
|
329
338
|
export function formatInventory(inventory) {
|
|
330
339
|
if (inventory.length === 0)
|
|
331
340
|
return "(no interactive elements found on the page)";
|
|
341
|
+
const textCounts = new Map();
|
|
342
|
+
const textKey = (e) => `${e.tag}|${(e.visibleText ?? e.ariaLabel ?? e.labelText ?? "").toLowerCase().trim()}`;
|
|
343
|
+
for (const e of inventory) {
|
|
344
|
+
const k = textKey(e);
|
|
345
|
+
if (k.endsWith("|"))
|
|
346
|
+
continue; // no text → skip
|
|
347
|
+
textCounts.set(k, (textCounts.get(k) ?? 0) + 1);
|
|
348
|
+
}
|
|
349
|
+
const isDuplicated = (e) => (textCounts.get(textKey(e)) ?? 0) > 1;
|
|
332
350
|
return inventory
|
|
333
351
|
.map((e) => {
|
|
334
352
|
const bits = [`[${e.index}] ${e.tag}`];
|
|
@@ -397,6 +415,12 @@ export function formatInventory(inventory) {
|
|
|
397
415
|
}
|
|
398
416
|
if (e.inConsentWidget)
|
|
399
417
|
bits.push("[cookie-consent — avoid]");
|
|
418
|
+
// F15 — disambiguating landmark tag for text-duplicates.
|
|
419
|
+
if (isDuplicated(e) &&
|
|
420
|
+
e.landmark !== null &&
|
|
421
|
+
e.landmark !== undefined) {
|
|
422
|
+
bits.push(`landmark=${e.landmark}`);
|
|
423
|
+
}
|
|
400
424
|
bits.push(`selector=${e.selector}`);
|
|
401
425
|
return bits.join(" ");
|
|
402
426
|
})
|
|
@@ -614,6 +638,26 @@ export function detectAlreadySignedIn(args) {
|
|
|
614
638
|
// True when the page has no fillable text input AND no button that
|
|
615
639
|
// reads as an email-signup option — a genuinely OAuth/SSO-only
|
|
616
640
|
// service with no form to automate (F3 Issue 4).
|
|
641
|
+
// rc.33-task — scan the inventory for any OAuth provider buttons,
|
|
642
|
+
// regardless of whether the bot has a session for them. Used by the
|
|
643
|
+
// OAuth-only-chooser branch to surface needs_oauth_provider_session
|
|
644
|
+
// with the SPECIFIC providers the page offers. Detection mirrors
|
|
645
|
+
// findOAuthButton's logic (visible text / aria-label / iconLabel
|
|
646
|
+
// containing the provider keyword + an auth verb, or href to the
|
|
647
|
+
// provider's OAuth endpoint).
|
|
648
|
+
//
|
|
649
|
+
// Returns providers in the order they were found in the inventory,
|
|
650
|
+
// deduped.
|
|
651
|
+
export function detectOAuthProvidersInInventory(inventory) {
|
|
652
|
+
const found = new Set();
|
|
653
|
+
const providers = ["google", "github"];
|
|
654
|
+
for (const provider of providers) {
|
|
655
|
+
if (findOAuthButton(inventory, provider) !== null) {
|
|
656
|
+
found.add(provider);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
return [...found];
|
|
660
|
+
}
|
|
617
661
|
export function isOauthOnlyChooser(inventory) {
|
|
618
662
|
const TEXTLIKE = new Set([
|
|
619
663
|
"text",
|
|
@@ -895,10 +939,15 @@ export function extractApiKeyFromText(text) {
|
|
|
895
939
|
// patterns first so a labeled-pattern fallback isn't load-
|
|
896
940
|
// bearing for them. Putting `sk-or-v1-` before `sk-` so it wins
|
|
897
941
|
// when both could match (cosmetic; both capture the same value).
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
942
|
+
// 0.6.15-rc.8 — character-class anchored so the greedy match
|
|
943
|
+
// doesn't glue trailing modal text. extractText() returns body
|
|
944
|
+
// as one concatenated string, so a key followed by "Please copy
|
|
945
|
+
// this" with no separator looked like `sk-or-v1-<64hex>Please…`.
|
|
946
|
+
// The hex-only class terminates at the first non-hex char.
|
|
947
|
+
/\bsk-or-v1-[a-f0-9]{40,80}/i, // OpenRouter (sk-or-v1-<64hex>)
|
|
948
|
+
/\bsk-ant-[a-zA-Z0-9_-]{40,120}/, // Anthropic (sk-ant-<urlsafe-b64>)
|
|
949
|
+
/\bsk-proj-[a-zA-Z0-9_-]{40,200}/, // OpenAI project key
|
|
950
|
+
/\bsk-[a-zA-Z0-9]{40,60}/, // OpenAI legacy (`sk-` + ~48 chars, no dashes)
|
|
902
951
|
];
|
|
903
952
|
for (const pattern of prefixed) {
|
|
904
953
|
const match = text.match(pattern);
|
|
@@ -1111,6 +1160,13 @@ export class SignupAgent {
|
|
|
1111
1160
|
let emptyPlans = 0;
|
|
1112
1161
|
let oauthScanRetries = 0;
|
|
1113
1162
|
let hint;
|
|
1163
|
+
// F14 — selectors the planner clicked WITHOUT advancing the page.
|
|
1164
|
+
// Each no-progress plan records its click selectors here; the next
|
|
1165
|
+
// plan that picks ONLY selectors in this set is failed as stuck
|
|
1166
|
+
// instead of looping. Cleared on any progress (fill action). The
|
|
1167
|
+
// Railway run that motivated F14 spun the same footer "Email" link
|
|
1168
|
+
// 5 times before timing out; this loop now bails after 2.
|
|
1169
|
+
let lastNoProgressClickSelectors = new Set();
|
|
1114
1170
|
// rc.31 — once the bot has explicitly clicked an email-flow
|
|
1115
1171
|
// button (e.g. Railway's "Log in using email" two-stage chooser),
|
|
1116
1172
|
// stay on the email path. Without this, the auto-OAuth-first
|
|
@@ -1221,6 +1277,31 @@ export class SignupAgent {
|
|
|
1221
1277
|
// OAuth-only: no fillable input AND no button that reads as an
|
|
1222
1278
|
// email-signup option — nothing to automate (Issue 4).
|
|
1223
1279
|
if (isOauthOnlyChooser(inventory)) {
|
|
1280
|
+
// rc.33-task — distinguish "the bot has no session for the
|
|
1281
|
+
// provider the page offers" (operator action: `mcp login
|
|
1282
|
+
// --provider=X`) from "service is OAuth-only in general"
|
|
1283
|
+
// (operator action: manual signup). When the inventory has
|
|
1284
|
+
// OAuth buttons for providers the profile does NOT have a
|
|
1285
|
+
// session for AND the operator HAS sessions for other
|
|
1286
|
+
// providers, the situation is recoverable — surface the
|
|
1287
|
+
// specific provider to seed.
|
|
1288
|
+
const visibleProviders = detectOAuthProvidersInInventory(inventory);
|
|
1289
|
+
const haveSessions = loggedInProviders();
|
|
1290
|
+
const missingProviders = visibleProviders.filter((p) => !haveSessions.includes(p));
|
|
1291
|
+
if (missingProviders.length > 0 &&
|
|
1292
|
+
// Only surface needs_oauth_provider_session when the user
|
|
1293
|
+
// can actually act on it — i.e. they have at least one
|
|
1294
|
+
// OAuth session already (so they know how to seed
|
|
1295
|
+
// others). A fresh install with zero sessions still gets
|
|
1296
|
+
// the generic oauth_required (which the install/connect
|
|
1297
|
+
// flow has its own help text for).
|
|
1298
|
+
haveSessions.length > 0) {
|
|
1299
|
+
return {
|
|
1300
|
+
kind: "needs_oauth_provider_session",
|
|
1301
|
+
missingProviders,
|
|
1302
|
+
haveSessions,
|
|
1303
|
+
};
|
|
1304
|
+
}
|
|
1224
1305
|
return { kind: "oauth_required" };
|
|
1225
1306
|
}
|
|
1226
1307
|
steps.push("Asking Claude to plan the signup form fill...");
|
|
@@ -1248,6 +1329,23 @@ export class SignupAgent {
|
|
|
1248
1329
|
}
|
|
1249
1330
|
steps.push(`Plan: ${plan.actions.length} action(s), confidence=${plan.confidence}` +
|
|
1250
1331
|
(plan.notes !== undefined ? ` — ${plan.notes}` : ""));
|
|
1332
|
+
// F14 — stuck-detection: if the plan picks ONLY click selectors
|
|
1333
|
+
// we already tried in the previous round without page progress,
|
|
1334
|
+
// it's a planner loop. Fail planning_failed with the offending
|
|
1335
|
+
// selector(s) so the operator sees what stalled. Doesn't fire
|
|
1336
|
+
// when the plan adds at least one new selector (legitimate
|
|
1337
|
+
// exploration). Doesn't fire on fill plans (forward progress).
|
|
1338
|
+
const planClickSelectors = plan.actions
|
|
1339
|
+
.filter((a) => a.kind === "click")
|
|
1340
|
+
.map((a) => a.selector);
|
|
1341
|
+
if (planClickSelectors.length > 0 &&
|
|
1342
|
+
lastNoProgressClickSelectors.size > 0 &&
|
|
1343
|
+
planClickSelectors.every((s) => lastNoProgressClickSelectors.has(s))) {
|
|
1344
|
+
return {
|
|
1345
|
+
kind: "planning_failed",
|
|
1346
|
+
reason: `stuck — planner re-picked the same click selector(s) after no-progress: ${planClickSelectors.join(", ")}`,
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1251
1349
|
// Verify the picks resolve on the live page — also catches a
|
|
1252
1350
|
// stale selector resolving to a recycled wrong node (Tension 4).
|
|
1253
1351
|
const bySelector = new Map(inventory.map((e) => [e.selector, e]));
|
|
@@ -1313,10 +1411,23 @@ export class SignupAgent {
|
|
|
1313
1411
|
steps.push(plan.actions.length === 0
|
|
1314
1412
|
? "Plan found nothing to act on — re-checking once for a late render"
|
|
1315
1413
|
: "Plan only revealed the page — re-planning the now-visible form");
|
|
1414
|
+
// F14 — record the click selectors that didn't advance the
|
|
1415
|
+
// page. The next plan's stuck-detection check (above) bails
|
|
1416
|
+
// if it picks the same ones again. Hint also tells the
|
|
1417
|
+
// planner which selectors NOT to re-pick.
|
|
1418
|
+
lastNoProgressClickSelectors = new Set(planClickSelectors);
|
|
1419
|
+
const avoidHint = planClickSelectors.length > 0
|
|
1420
|
+
? ` AVOID these selectors — they were clicked but the page did NOT advance: ${planClickSelectors.map((s) => JSON.stringify(s)).join(", ")}.`
|
|
1421
|
+
: "";
|
|
1316
1422
|
hint =
|
|
1317
|
-
"The previous step revealed or advanced the page. Plan the signup form that should now be visible."
|
|
1423
|
+
"The previous step revealed or advanced the page. Plan the signup form that should now be visible." +
|
|
1424
|
+
avoidHint;
|
|
1318
1425
|
continue;
|
|
1319
1426
|
}
|
|
1427
|
+
// F14 — fill action present = forward progress. Clear the
|
|
1428
|
+
// stuck-tracker so a legitimate later click isn't false-positive
|
|
1429
|
+
// rejected.
|
|
1430
|
+
lastNoProgressClickSelectors = new Set();
|
|
1320
1431
|
// Captcha gate + submit.
|
|
1321
1432
|
const preGate = await this.runCaptchaGate("Pre-submit", steps);
|
|
1322
1433
|
if (preGate.blocked)
|
|
@@ -1457,9 +1568,23 @@ export class SignupAgent {
|
|
|
1457
1568
|
const loggedIn = loggedInProviders();
|
|
1458
1569
|
if (loggedIn.length === 0)
|
|
1459
1570
|
return [];
|
|
1460
|
-
|
|
1571
|
+
// Stable tiebreak when both providers have a session: Google
|
|
1572
|
+
// first. Google's OAuth flow is one-click in the common case
|
|
1573
|
+
// (consent + redirect); GitHub's typically requires the explicit
|
|
1574
|
+
// authorize-then-grant double step. Lower friction, fewer
|
|
1575
|
+
// number-match challenges on warm sessions.
|
|
1576
|
+
const ordered = [...loggedIn].sort((a, b) => {
|
|
1577
|
+
if (a === b)
|
|
1578
|
+
return 0;
|
|
1579
|
+
if (a === "google")
|
|
1580
|
+
return -1;
|
|
1581
|
+
if (b === "google")
|
|
1582
|
+
return 1;
|
|
1583
|
+
return 0;
|
|
1584
|
+
});
|
|
1585
|
+
steps.push(`Auto-OAuth: profile has a session for ${ordered.join(", ")} — ` +
|
|
1461
1586
|
"preferring OAuth if the page offers it");
|
|
1462
|
-
return
|
|
1587
|
+
return ordered;
|
|
1463
1588
|
}
|
|
1464
1589
|
// Verify every selector the plan references still resolves on the
|
|
1465
1590
|
// live page, and — when the inventory entry had an id — that it
|
|
@@ -1825,6 +1950,31 @@ export class SignupAgent {
|
|
|
1825
1950
|
steps,
|
|
1826
1951
|
...this.resultTail(),
|
|
1827
1952
|
};
|
|
1953
|
+
case "needs_oauth_provider_session": {
|
|
1954
|
+
// rc.33-task — actionable: name the missing provider so
|
|
1955
|
+
// the user runs the right `mcp login` command. When more
|
|
1956
|
+
// than one provider is missing, the message lists them and
|
|
1957
|
+
// recommends any single one (operator picks).
|
|
1958
|
+
const missing = outcome.missingProviders;
|
|
1959
|
+
const have = outcome.haveSessions;
|
|
1960
|
+
const firstMissing = missing[0];
|
|
1961
|
+
const missingLabel = missing
|
|
1962
|
+
.map((p) => OAUTH_PROVIDERS[p].label)
|
|
1963
|
+
.join(" / ");
|
|
1964
|
+
const haveLabel = have.length > 0
|
|
1965
|
+
? have.map((p) => OAUTH_PROVIDERS[p].label).join(", ")
|
|
1966
|
+
: "(none)";
|
|
1967
|
+
return {
|
|
1968
|
+
success: false,
|
|
1969
|
+
error: `needs_oauth_provider_session: ${task.service} offers ${missingLabel} OAuth ` +
|
|
1970
|
+
`but the bot's chrome profile has no ${missingLabel} session ` +
|
|
1971
|
+
`(currently signed in to: ${haveLabel}). ` +
|
|
1972
|
+
`Run \`npx @trusty-squire/mcp login --provider=${firstMissing}\` ` +
|
|
1973
|
+
`to seed the session, then retry.`,
|
|
1974
|
+
steps,
|
|
1975
|
+
...this.resultTail(),
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1828
1978
|
case "anti_bot_blocked":
|
|
1829
1979
|
return {
|
|
1830
1980
|
success: false,
|
|
@@ -2078,6 +2228,11 @@ export class SignupAgent {
|
|
|
2078
2228
|
console.error(`[universal-bot] GOOGLE NUMBER-MATCH: tap "${matchNum}" on your phone — 2 minute window`);
|
|
2079
2229
|
steps.push(`Google: match the number ${matchNum} on your phone — ` +
|
|
2080
2230
|
`open the Google app on your phone and tap ${matchNum}`);
|
|
2231
|
+
void notifyHeightenedAuth({
|
|
2232
|
+
service: task.service,
|
|
2233
|
+
digit: String(matchNum),
|
|
2234
|
+
windowSeconds: 120,
|
|
2235
|
+
});
|
|
2081
2236
|
}
|
|
2082
2237
|
else {
|
|
2083
2238
|
// Extractor missed the number — Google phrasing has
|
|
@@ -2088,6 +2243,11 @@ export class SignupAgent {
|
|
|
2088
2243
|
`read the most recent google-challenge.png in the debug dir to find the number — 2 minute window`);
|
|
2089
2244
|
steps.push("Google: challenge detected, number-match extractor missed it. " +
|
|
2090
2245
|
"See the latest google-challenge snapshot in the debug dir to read the number.");
|
|
2246
|
+
void notifyHeightenedAuth({
|
|
2247
|
+
service: task.service,
|
|
2248
|
+
digit: null,
|
|
2249
|
+
windowSeconds: 120,
|
|
2250
|
+
});
|
|
2091
2251
|
}
|
|
2092
2252
|
// Either way (number found or not), the user can still
|
|
2093
2253
|
// clear the challenge in the bot's browser window or by
|