@trusty-squire/mcp 0.8.2-rc.1 → 0.8.2-rc.11

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.
@@ -22,6 +22,12 @@ export declare function expectsVerificationEmail(pageText: string): boolean;
22
22
  export declare class LLMCallBudgetExceeded extends Error {
23
23
  constructor(budget: number);
24
24
  }
25
+ export declare function detectExistingAccountNoExtract(input: {
26
+ url: string;
27
+ pageText: string;
28
+ lastPlannerReason: string;
29
+ }): boolean;
30
+ export declare function pickStuckLoopFallbackUrl(currentUrl: string, alreadyTried: ReadonlySet<string>): string | null;
25
31
  export declare function guessSignupUrl(service: string): string;
26
32
  export declare function isKnownDomainFullUrlMatch(service: string, url: string): boolean;
27
33
  export declare function isGoogleSearchUrl(url: string): boolean;
@@ -223,7 +229,9 @@ export declare class SignupAgent {
223
229
  extractFailureUploader?: ExtractFailureUploader;
224
230
  roundUploader?: RoundUploader;
225
231
  captchaSolver?: TwoCaptchaSolver;
232
+ googleChallengeTimeoutMs?: number;
226
233
  });
234
+ private googleChallengeTimeoutMs;
227
235
  get backends(): readonly string[];
228
236
  private callLLM;
229
237
  private callLLMInner;
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/bot/agent.ts"],"names":[],"mappings":"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"}
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
@@ -93,6 +93,22 @@ const ONBOARDING_PAYWALL_PATTERNS = [
93
93
  /\b(?:plan\s+|account\s+)?payment\s+required\b/i,
94
94
  /\bcomplet(?:e|ing)\s+(?:billing|payment)\b/i,
95
95
  /\bbilling\s+setup\s+(?:is\s+)?required\b/i,
96
+ // 0.8.2-rc.5 — Together.ai's post-OAuth landing surfaces a "payment
97
+ // form" gate that the post-verify planner reliably describes in its
98
+ // `done` reason:
99
+ //
100
+ // "This page shows a payment form, and it's not possible to proceed
101
+ // further without inputting payment information."
102
+ //
103
+ // None of the rc.39 patterns covered "payment form" / "payment
104
+ // information" — together fell through to `oauth_onboarding_failed`,
105
+ // which is misleading (the OAuth handshake succeeded; the wall is
106
+ // billing). Patterns are scoped to the "form/information requirement"
107
+ // shape so a marketing tile mentioning "payment information" doesn't
108
+ // false-positive.
109
+ /\bpayment\s+form\b/i,
110
+ /\binput(?:ting)?\s+payment\s+information\b/i,
111
+ /\benter(?:ing)?\s+payment\s+information\b/i,
96
112
  ];
97
113
  // Negators that, if they appear in the ~30 characters immediately
98
114
  // before a paywall pattern match, flip its meaning from a demand
@@ -129,6 +145,104 @@ export class LLMCallBudgetExceeded extends Error {
129
145
  this.name = "LLMCallBudgetExceeded";
130
146
  }
131
147
  }
148
+ // 0.8.2-rc.10 — common dashboard paths that vendors host their
149
+ // per-account API key UI at. Ordered most-specific first so a
150
+ // fallback navigate doesn't land short of the actual page. Returned
151
+ // as an array of path-strings; the caller composes them onto the
152
+ // origin of the currently-stuck URL and skips any already tried.
153
+ //
154
+ // Patterns harvested from Anthropic (settings/keys), Sentry
155
+ // (settings/account/api/auth-tokens), Neon (settings#api-keys),
156
+ // Render (account/api-keys), Postmark (account/api_tokens),
157
+ // OpenRouter (keys), and a long tail of vendors converging on the
158
+ // same conventions.
159
+ const STUCK_LOOP_FALLBACK_PATHS = [
160
+ "/settings/keys",
161
+ "/settings/api-keys",
162
+ "/settings/api_keys",
163
+ "/settings/tokens",
164
+ "/settings/api-tokens",
165
+ "/settings/account/api/auth-tokens/",
166
+ "/account/api-keys",
167
+ "/account/api_tokens",
168
+ "/account/keys",
169
+ "/account/tokens",
170
+ "/api-keys",
171
+ "/api_keys",
172
+ "/keys",
173
+ "/tokens",
174
+ "/auth-tokens",
175
+ "/dashboard/api-keys",
176
+ "/dashboard/keys",
177
+ ];
178
+ // 0.8.2-rc.10 — heuristic for "this account already exists on the
179
+ // service and its API keys are masked, with no path to reveal them."
180
+ // The test identity (methoxine@gmail.com) accumulates state across
181
+ // batches; subsequent runs land on a dashboard whose API-keys page
182
+ // shows only the NAMES of existing keys (the values were revealed
183
+ // once at create-time and aren't recoverable). Without this
184
+ // classifier those runs fall through to a generic
185
+ // oauth_onboarding_failed and the harvester treats them like a
186
+ // repairable bug.
187
+ //
188
+ // Conservative rules: must be on a URL that names an API-key page
189
+ // (keys / api-keys / api-tokens / auth-tokens / api_keys), AND the
190
+ // page text shows BOTH a masking glyph pattern (•••, ***, ─•) AND
191
+ // an existing-key word, OR the planner's last reason explicitly
192
+ // describes the same shape.
193
+ const EXISTING_KEY_URL_HINT = /(?:api[-_/]keys?|api[-_/]tokens?|auth[-_/]tokens?|personal[-_/]access[-_/]tokens?|\/keys(?:\b|\/|$)|\/tokens(?:\b|\/|$)|\/settings\/keys\b|\/settings\/tokens\b|#api[-_/]keys\b|#api[-_/]tokens\b)/i;
194
+ const MASKED_KEY_GLYPHS = /(?:•{3,}|\*{3,}|─•|·{3,}|•{3,}|x{6,}|[A-Za-z0-9]{2,4}[•*]{5,})/;
195
+ const EXISTING_KEY_WORDS = /\b(?:existing\s+(?:api\s+)?(?:key|token)|previously\s+created|created\s+by\b|api\s+keys?\s*\(\d+\)|tokens?\s*\(\d+\)|reveal|copy\s+key)\b/i;
196
+ const NO_CREATE_AFFORDANCE_HINT = /\b(?:cannot\s+(?:reveal|extract|read)|values?\s+(?:is\s+)?masked|only\s+shown\s+once|cannot\s+(?:see|view|copy)\s+(?:the\s+)?(?:key|secret|value))\b/i;
197
+ export function detectExistingAccountNoExtract(input) {
198
+ if (!EXISTING_KEY_URL_HINT.test(input.url))
199
+ return false;
200
+ // Planner reason naming the no-reveal shape is the strongest single
201
+ // signal — the planner has SEEN the page and is describing it.
202
+ if (NO_CREATE_AFFORDANCE_HINT.test(input.lastPlannerReason)) {
203
+ return true;
204
+ }
205
+ // Otherwise require BOTH a mask glyph and an existing-key word in
206
+ // the page text. Either alone is too weak: vendors decorate
207
+ // marketing tiles with bullet-pointed dots; "existing" appears in
208
+ // unrelated dashboard copy.
209
+ return (MASKED_KEY_GLYPHS.test(input.pageText) &&
210
+ EXISTING_KEY_WORDS.test(input.pageText));
211
+ }
212
+ // Pick the next fallback URL to try from STUCK_LOOP_FALLBACK_PATHS
213
+ // keyed against the origin of the currently-stuck URL. Returns null
214
+ // when every path has already been attempted. Exported for unit tests.
215
+ export function pickStuckLoopFallbackUrl(currentUrl, alreadyTried) {
216
+ let origin;
217
+ try {
218
+ origin = new URL(currentUrl).origin;
219
+ }
220
+ catch {
221
+ return null;
222
+ }
223
+ // Skip a candidate when the current URL's path ALREADY matches it
224
+ // (case-insensitive, trailing-slash tolerant). The planner is stuck
225
+ // ON the page the candidate points to — navigating to the same URL
226
+ // again won't break the cycle, only a different path will.
227
+ const currentPath = (() => {
228
+ try {
229
+ return new URL(currentUrl).pathname.replace(/\/+$/, "").toLowerCase();
230
+ }
231
+ catch {
232
+ return "";
233
+ }
234
+ })();
235
+ for (const path of STUCK_LOOP_FALLBACK_PATHS) {
236
+ const candidate = `${origin}${path}`;
237
+ if (alreadyTried.has(candidate))
238
+ continue;
239
+ const candidatePath = path.replace(/\/+$/, "").toLowerCase();
240
+ if (candidatePath === currentPath)
241
+ continue;
242
+ return candidate;
243
+ }
244
+ return null;
245
+ }
132
246
  // Best-effort canonical signup URL for a service when the caller
133
247
  // didn't pass one. Most dev-SaaS targets (Resend, Postmark, Mailgun,
134
248
  // MailerSend, IPInfo, Stripe, PostHog) live at <name>.com/signup —
@@ -746,6 +860,46 @@ export function detectAlreadySignedIn(args) {
746
860
  })) {
747
861
  return true;
748
862
  }
863
+ // 0.8.2-rc.5 — PostHog-class onboarding wizard. When the URL is
864
+ // dashboard-y (path like /project/<id>/onboarding) and the page
865
+ // shows project-picker / account-menu / onboarding-skip
866
+ // affordances WITHOUT a credential input or OAuth provider button,
867
+ // the user is authenticated and the wizard is interstitial. The
868
+ // rc.3 overnight run for posthog landed exactly here and bailed
869
+ // `oauth_required` because the inventory had only:
870
+ // - "Default project" (project picker)
871
+ // - "BBento" (account avatar toggle)
872
+ // - "Hand off setup" (skip-onboarding affordance)
873
+ //
874
+ // Detect this shape via a second-tier signal set. Conservative —
875
+ // we already gated on "no credential inputs" and "dashboardyPath",
876
+ // so a true signup chooser (which has neither of those AND the
877
+ // path is /signup or /login) cannot reach this branch.
878
+ const POST_AUTH_AFFORDANCE = /^\s*(?:hand\s*off\s*setup|skip\s*(?:onboarding|setup|for\s*now)|invite\s*(?:teammates|members|your\s*team)|set\s*up\s*billing|finish\s*setup|get\s*started|continue\s*to\s*(?:dashboard|app|console))\s*$/i;
879
+ // Workspace / project / org picker shape. We pattern-match
880
+ // generously because PostHog's reads "Default project" but other
881
+ // SaaS dashboards read "My workspace" / "Acme org" / similar. The
882
+ // structural cue is "button with one of the workspace-noun words"
883
+ // — see TS-1923 (PostHog rc.3 regression).
884
+ const WORKSPACE_PICKER = /\b(?:workspace|workspaces|project(?:s)?|organization|organizations|team(?:s)?)\b/i;
885
+ const hasPostAuthAffordance = inventory.some((e) => POST_AUTH_AFFORDANCE.test((e.visibleText ?? e.ariaLabel ?? "").trim()));
886
+ if (hasPostAuthAffordance) {
887
+ // Single signal — the skip-onboarding / handoff verb is strong
888
+ // enough on its own. No login page ever offers "Hand off setup".
889
+ return true;
890
+ }
891
+ // Weaker pair: a workspace-picker shape AND the page lacks a
892
+ // primary call-to-action that reads as signup ("Continue with
893
+ // Google", "Sign up", etc.). Used as a backstop for SPA dashboards
894
+ // whose only visible buttons are picker toggles.
895
+ const hasWorkspacePicker = inventory.some((e) => WORKSPACE_PICKER.test((e.visibleText ?? e.ariaLabel ?? "").trim()));
896
+ const hasSignupOrOAuthAffordance = inventory.some((e) => {
897
+ const t = (e.visibleText ?? e.ariaLabel ?? "").trim();
898
+ return /\b(?:sign[\s-]*up|signup|continue\s+with|log\s+in\s+with|sign\s+in\s+with)\b/i.test(t);
899
+ });
900
+ if (hasWorkspacePicker && !hasSignupOrOAuthAffordance) {
901
+ return true;
902
+ }
749
903
  }
750
904
  return false;
751
905
  }
@@ -1894,12 +2048,27 @@ export class SignupAgent {
1894
2048
  // Parse/validation failure — includes a hallucinated selector
1895
2049
  // rejected by the inventory check. An error replan.
1896
2050
  const reason = err instanceof Error ? err.message : String(err);
1897
- if (++errorReplans > MAX_ERROR_REPLANS) {
2051
+ // 0.8.2-rc.6 mirror the post-verify upstream-blip carve-out.
2052
+ // The form-fill planner is also vulnerable to sustained
2053
+ // upstream-proxy degradation: the rc.3 + rc.5 batch runs
2054
+ // showed openrouter / resend / sentry losing 4+ consecutive
2055
+ // proxy calls in a row when the free-tier upstream was
2056
+ // throttling. Don't punt to planning_failed for upstream
2057
+ // weather — keep re-planning until the budget runs out at the
2058
+ // top-level F2 deadline, OR a true logic failure shows up.
2059
+ const isUpstreamBlip = /\b50[234]\b/.test(reason) ||
2060
+ /\bupstream_(?:error|unreachable)\b/i.test(reason) ||
2061
+ /\bnetwork error\b/i.test(reason);
2062
+ if (!isUpstreamBlip && ++errorReplans > MAX_ERROR_REPLANS) {
1898
2063
  return { kind: "planning_failed", reason: `planner output never validated: ${reason}` };
1899
2064
  }
1900
- steps.push(`⚠ plan rejected (${reason}) — re-planning`);
1901
- hint =
1902
- "Your previous plan used a selector not in the inventory. Use ONLY selectors copied verbatim from a `selector=` field.";
2065
+ steps.push(isUpstreamBlip
2066
+ ? `⚠ planner request hit a transient upstream blip (${reason}) — retrying`
2067
+ : `⚠ plan rejected (${reason}) re-planning`);
2068
+ if (!isUpstreamBlip) {
2069
+ hint =
2070
+ "Your previous plan used a selector not in the inventory. Use ONLY selectors copied verbatim from a `selector=` field.";
2071
+ }
1903
2072
  continue;
1904
2073
  }
1905
2074
  steps.push(`Plan: ${plan.actions.length} action(s), confidence=${plan.confidence}` +
@@ -2316,7 +2485,13 @@ export class SignupAgent {
2316
2485
  this.roundUploader = opts.roundUploader;
2317
2486
  }
2318
2487
  this.captchaSolver = opts.captchaSolver ?? new TwoCaptchaSolver();
2488
+ if (opts.googleChallengeTimeoutMs !== undefined) {
2489
+ this.googleChallengeTimeoutMs = opts.googleChallengeTimeoutMs;
2490
+ }
2319
2491
  }
2492
+ // Default: 2 minutes — enough time for the human to unlock phone,
2493
+ // open the Google app, and tap a verification number.
2494
+ googleChallengeTimeoutMs = 120_000;
2320
2495
  // Read-only view of how many calls landed on which backend. Exported
2321
2496
  // through SignupResult.llm_backends so tests and ops can verify the
2322
2497
  // dual-mode fallback is actually engaging when expected.
@@ -2338,12 +2513,22 @@ export class SignupAgent {
2338
2513
  if (this.llmCallCount >= MAX_LLM_CALLS_PER_SIGNUP) {
2339
2514
  throw new LLMCallBudgetExceeded(MAX_LLM_CALLS_PER_SIGNUP);
2340
2515
  }
2341
- this.llmCallCount += 1;
2516
+ // 0.8.2-rc.8 count the call only AFTER the upstream actually
2517
+ // replied. The old code incremented before the proxy fetch which
2518
+ // means a proxy 502 (caught & surfaced after the 4-attempt retry
2519
+ // budget exhausts) cost the same budget unit as a real planner
2520
+ // reply. The rc.7 sentry batch run hit this: 2 upstream-blip
2521
+ // retries consumed 2 of the 15 calls on top of the 9 successful
2522
+ // post-verify rounds — the planner ran out of budget on the 8th
2523
+ // permission scope, 5 short of the API key. Failed calls produce
2524
+ // no progress; charging them against the budget is wrong. Behave
2525
+ // like a meter: only count consumption that actually delivered.
2342
2526
  const resp = await client.createMessage({
2343
2527
  system: args.system,
2344
2528
  user: args.userBlocks,
2345
2529
  max_tokens: args.maxTokens,
2346
2530
  });
2531
+ this.llmCallCount += 1;
2347
2532
  this.backendsUsed.push(resp.backend);
2348
2533
  return resp.text;
2349
2534
  };
@@ -2679,6 +2864,34 @@ export class SignupAgent {
2679
2864
  ...this.resultTail(),
2680
2865
  };
2681
2866
  }
2867
+ // 0.8.2-rc.10 — same sentinel-pattern routing the runOAuthFlow
2868
+ // path uses. The post-verify loop sets lastPostVerifyDoneReason
2869
+ // with [stuck_loop] or [existing_account_no_extract] markers
2870
+ // when it bails on a planner-loop or pre-existing-key state;
2871
+ // surface those distinctly rather than as the generic
2872
+ // no_credentials_after_already_signed_in.
2873
+ if (this.lastPostVerifyDoneReason !== null &&
2874
+ this.lastPostVerifyDoneReason.startsWith("[stuck_loop]")) {
2875
+ return {
2876
+ success: false,
2877
+ error: `planner_stuck: ${task.service}'s dashboard re-picked the same step repeatedly ` +
2878
+ `with no inventory change and the bot's hardcoded API-key URL fallbacks did not ` +
2879
+ `advance the page — finish the signup manually.`,
2880
+ steps,
2881
+ ...this.resultTail(),
2882
+ };
2883
+ }
2884
+ if (this.lastPostVerifyDoneReason !== null &&
2885
+ this.lastPostVerifyDoneReason.startsWith("[existing_account_no_extract]")) {
2886
+ return {
2887
+ success: false,
2888
+ error: `existing_account_no_extract: ${task.service}'s dashboard shows pre-existing API ` +
2889
+ `keys for this identity but the values are masked and unrecoverable — wipe the ` +
2890
+ `test identity's account on ${task.service} or sign in manually and reveal the key.`,
2891
+ steps,
2892
+ ...this.resultTail(),
2893
+ };
2894
+ }
2682
2895
  return {
2683
2896
  success: false,
2684
2897
  error: "no_credentials_after_already_signed_in: bot detected an authenticated dashboard " +
@@ -3325,6 +3538,41 @@ export class SignupAgent {
3325
3538
  ...this.resultTail(),
3326
3539
  };
3327
3540
  }
3541
+ // 0.8.2-rc.10 — planner stuck-loop, fallback URLs exhausted. The
3542
+ // postVerifyLoop marks this with the [stuck_loop] sentinel so the
3543
+ // operator sees a distinct status (it's not an "OAuth onboarding"
3544
+ // failure — OAuth succeeded; the planner got stuck on the
3545
+ // post-OAuth navigation).
3546
+ if (this.lastPostVerifyDoneReason !== null &&
3547
+ this.lastPostVerifyDoneReason.startsWith("[stuck_loop]")) {
3548
+ return {
3549
+ success: false,
3550
+ error: `planner_stuck: ${task.service}'s post-OAuth dashboard re-picked the same step ` +
3551
+ `repeatedly with no inventory change and the bot's hardcoded API-key URL fallbacks ` +
3552
+ `did not advance the page — finish the signup manually.`,
3553
+ steps,
3554
+ ...this.resultTail(),
3555
+ };
3556
+ }
3557
+ // 0.8.2-rc.10 — existing-account state with no extractable
3558
+ // credential. The postVerifyLoop's existing-key detector
3559
+ // (detectExistingAccountNoExtract) classifies a run that lands on
3560
+ // an authenticated dashboard whose API-keys page surfaces only
3561
+ // masked existing keys + no path to a fresh value. Surfacing this
3562
+ // distinctly so the harvester can flag it (e.g. periodically wipe
3563
+ // the chrome profile for the test identity) rather than treat it
3564
+ // as a real bot failure.
3565
+ if (this.lastPostVerifyDoneReason !== null &&
3566
+ this.lastPostVerifyDoneReason.startsWith("[existing_account_no_extract]")) {
3567
+ return {
3568
+ success: false,
3569
+ error: `existing_account_no_extract: ${task.service}'s dashboard shows pre-existing API ` +
3570
+ `keys for this identity but the values are masked and unrecoverable — wipe the ` +
3571
+ `test identity's account on ${task.service} or sign in manually and reveal the key.`,
3572
+ steps,
3573
+ ...this.resultTail(),
3574
+ };
3575
+ }
3328
3576
  return {
3329
3577
  success: false,
3330
3578
  error: `oauth_onboarding_failed: signed in to ${task.service} via ${provider.label} but ` +
@@ -3351,7 +3599,7 @@ export class SignupAgent {
3351
3599
  // unlock a phone, open the Google app, and tap a number; longer
3352
3600
  // would mask a stuck/abandoned flow.
3353
3601
  async waitForGoogleChallenge(provider, steps) {
3354
- const deadline = Date.now() + 120_000;
3602
+ const deadline = Date.now() + this.googleChallengeTimeoutMs;
3355
3603
  while (Date.now() < deadline) {
3356
3604
  await this.browser.wait(3);
3357
3605
  if (this.browser.oauthPageClosed())
@@ -3605,6 +3853,15 @@ ${formatInventory(input.inventory)}`,
3605
3853
  let credentials = await this.extractCredentials();
3606
3854
  let loginAttempts = 0;
3607
3855
  let planFailures = 0;
3856
+ // 0.8.2-rc.6 — separate counter for upstream-blip retries. Doesn't
3857
+ // gate planFailures (so a transient 502 won't push us into the
3858
+ // terminal stop branch after 4 rounds), but is still bounded so a
3859
+ // permanently-down proxy can't loop forever. Generous because each
3860
+ // blip costs ~5s of network + retry-backoff and the run already
3861
+ // has a 10-min top-level timeout — but tight enough that a truly
3862
+ // dead upstream doesn't burn the whole maxRounds budget on noise.
3863
+ let upstreamBlipRetries = 0;
3864
+ const MAX_UPSTREAM_BLIP_RETRIES = 8;
3608
3865
  const oauth = args.credentials === undefined;
3609
3866
  // Re-plan hint for the next round — set when an `extract` step
3610
3867
  // found no key, which means the visible key text is masked /
@@ -3664,6 +3921,26 @@ ${formatInventory(input.inventory)}`,
3664
3921
  // navigate produced no progress. Inject a hint forcing a CLICK
3665
3922
  // on something visible in the current inventory.
3666
3923
  let prevNavigateFromUrl = null;
3924
+ // 0.8.2-rc.10 — escalation for the stuck-loop detector.
3925
+ //
3926
+ // The existing detector injects a re-plan hint when the planner
3927
+ // returns the same kind+selector twice with no inventory change,
3928
+ // but the planner often ignores the "pick a different KIND" hint
3929
+ // and just picks a slightly different SELECTOR for another click.
3930
+ // Anthropic's batch failure (rc.8) showed 6 wasted rounds of this
3931
+ // before a navigate finally broke the cycle: clicking the sidebar
3932
+ // "API Keys" link on a dashboard that wasn't routing to it.
3933
+ //
3934
+ // Escalation strategy: after N stuck-fires within the SAME URL,
3935
+ // try a hard navigate to a guessed API-keys URL (one per origin).
3936
+ // If the URL has already advanced past the stuck zone, reset the
3937
+ // counter. After every fallback URL is exhausted AND we're still
3938
+ // stuck, mark the run [stuck_loop] so the caller surfaces the
3939
+ // dedicated error code instead of the generic
3940
+ // oauth_onboarding_failed.
3941
+ let stuckFiresAtUrl = 0;
3942
+ let lastStuckFireUrl = null;
3943
+ const triedFallbackUrls = new Set();
3667
3944
  // 0.8.1 — capture chain index is independent of the planner loop
3668
3945
  // round. The loop has two early-`continue` paths (page mid-navigation
3669
3946
  // throw, planner-rejection re-plan) that increment `round` WITHOUT
@@ -3727,17 +4004,47 @@ ${formatInventory(input.inventory)}`,
3727
4004
  // form-fill planner has. Bounded so a persistently broken
3728
4005
  // planner still terminates.
3729
4006
  const reason = err instanceof Error ? err.message : String(err);
3730
- planFailures += 1;
4007
+ // 0.8.2-rc.6 — distinguish upstream-blip from planner-logic
4008
+ // failure. The proxy retry-with-backoff (rc.5) handles most
4009
+ // transient 502s within a single call, but during a sustained
4010
+ // upstream degradation the retry budget exhausts and surfaces
4011
+ // here as a planFailure. Counting those toward the 4x stop
4012
+ // threshold is wrong — they're not the planner's fault, the
4013
+ // upstream is just temporarily unavailable. We allow these to
4014
+ // burn a round (forward progress is impossible without a
4015
+ // planner reply) but don't tick planFailures, so a transient
4016
+ // blip can't push us into the terminal stop branch.
4017
+ const isUpstreamBlip = /\b50[234]\b/.test(reason) ||
4018
+ /\bupstream_(?:error|unreachable)\b/i.test(reason) ||
4019
+ /\bnetwork error\b/i.test(reason);
4020
+ if (isUpstreamBlip) {
4021
+ upstreamBlipRetries += 1;
4022
+ if (upstreamBlipRetries > MAX_UPSTREAM_BLIP_RETRIES) {
4023
+ args.steps.push(`Post-verify round ${round}: upstream proxy degraded for ${upstreamBlipRetries} rounds — stopping (likely sustained outage).`);
4024
+ break;
4025
+ }
4026
+ }
4027
+ else {
4028
+ planFailures += 1;
4029
+ }
3731
4030
  if (planFailures > 3) {
3732
4031
  args.steps.push(`Post-verify round ${round}: planner failed ${planFailures}x (${reason}) — stopping.`);
3733
4032
  break;
3734
4033
  }
3735
- args.steps.push(`Post-verify round ${round}: planner output rejected (${reason}) — re-planning.`);
3736
- hint =
3737
- "Your previous step was REJECTED. A click/fill/select `selector` must be " +
3738
- "EXACTLY the value after `selector=` on one inventory line copy only that " +
3739
- "value (it runs to the end of the line), never the leading `[n] tag …` part " +
3740
- "and never the whole line.";
4034
+ const label = isUpstreamBlip ? "transient upstream blip" : "planner output rejected";
4035
+ args.steps.push(`Post-verify round ${round}: ${label} (${reason})` +
4036
+ (isUpstreamBlip
4037
+ ? ` — retrying (${upstreamBlipRetries}/${MAX_UPSTREAM_BLIP_RETRIES}).`
4038
+ : " re-planning."));
4039
+ // No re-plan hint on an upstream blip — the planner's previous
4040
+ // output (if any) was fine; only the request itself failed.
4041
+ if (!isUpstreamBlip) {
4042
+ hint =
4043
+ "Your previous step was REJECTED. A click/fill/select `selector` must be " +
4044
+ "EXACTLY the value after `selector=` on one inventory line — copy only that " +
4045
+ "value (it runs to the end of the line), never the leading `[n] tag …` part " +
4046
+ "and never the whole line.";
4047
+ }
3741
4048
  continue;
3742
4049
  }
3743
4050
  // rc.22 — redact tokens before pushing to the step trail.
@@ -3942,6 +4249,59 @@ ${formatInventory(input.inventory)}`,
3942
4249
  const uncheckedBoxHint = uncheckedBoxes.length > 0
3943
4250
  ? `\n\nVisible checkboxes you haven't ticked yet (often a TOS / agreement gate):\n${uncheckedBoxes.join("\n")}\n\nIssue {"kind":"check"} on any that look like agreements / required confirmations.`
3944
4251
  : "";
4252
+ // 0.8.2-rc.10 — escalation. Track stuck-fires per URL so we
4253
+ // can switch tactics once the gentle re-plan hint has clearly
4254
+ // failed (the planner refuses to break the cycle on its own,
4255
+ // see the Anthropic six-round pattern in rc.8).
4256
+ if (lastStuckFireUrl === state.url) {
4257
+ stuckFiresAtUrl += 1;
4258
+ }
4259
+ else {
4260
+ stuckFiresAtUrl = 1;
4261
+ lastStuckFireUrl = state.url;
4262
+ }
4263
+ // After two stuck fires at the same URL, escalate to a
4264
+ // hardcoded /settings/keys-style navigation. Vendors almost
4265
+ // always have ONE canonical path; the dashboard often gates
4266
+ // it behind a sidebar link the planner can't reliably resolve
4267
+ // (Anthropic, Neon, Sentry, Mistral, …). The fallback list is
4268
+ // ordered most-specific first so a service whose dashboard
4269
+ // root happens to share /settings with the API-keys page
4270
+ // doesn't land short of the actual page.
4271
+ if (stuckFiresAtUrl >= 2) {
4272
+ const fallback = pickStuckLoopFallbackUrl(state.url, triedFallbackUrls);
4273
+ if (fallback !== null) {
4274
+ triedFallbackUrls.add(fallback);
4275
+ args.steps.push(`Post-verify: stuck-loop detected ${stuckFiresAtUrl}x at ${state.url} — escalating to a hardcoded API-key URL: ${fallback}`);
4276
+ try {
4277
+ await this.browser.goto(fallback);
4278
+ await this.browser.waitForInteractiveDom(5, 15_000);
4279
+ }
4280
+ catch (err) {
4281
+ args.steps.push(`Post-verify: stuck-loop fallback navigate failed (${err instanceof Error ? err.message : String(err)}) — continuing.`);
4282
+ }
4283
+ // Reset signature tracking so the next round starts clean
4284
+ // against the new URL's inventory. Don't reset
4285
+ // stuckFiresAtUrl here — it's keyed by URL and the URL
4286
+ // about to be observed will be different, which naturally
4287
+ // resets it on the next loop entry.
4288
+ prevSignature = null;
4289
+ prevInventorySize = -1;
4290
+ hint = undefined;
4291
+ capturedRound += 1;
4292
+ continue;
4293
+ }
4294
+ // Every plausible fallback URL has been tried and we're
4295
+ // still stuck. Mark with the [stuck_loop] sentinel so the
4296
+ // caller surfaces planner_stuck instead of the generic
4297
+ // oauth_onboarding_failed, then break out of the loop.
4298
+ this.lastPostVerifyDoneReason =
4299
+ `[stuck_loop] planner re-picked the same ${nextStep.kind} step ${stuckFiresAtUrl} times at ${state.url} with no inventory change; ` +
4300
+ `hardcoded API-key URL fallbacks exhausted (tried: ${[...triedFallbackUrls].join(", ") || "none"}). ` +
4301
+ `Latest planner reason: ${nextStep.reason}`;
4302
+ args.steps.push(`Post-verify: stuck-loop unresolvable — breaking out with planner_stuck.`);
4303
+ break;
4304
+ }
3945
4305
  args.steps.push(sameSelector
3946
4306
  ? `Post-verify: no-progress detected — same ${nextStep.kind} on same selector, inventory unchanged. Re-planning instead of re-running.`
3947
4307
  : `Post-verify: no-progress detected — successive click steps with no inventory change. Forcing a non-click action.`);
@@ -4377,6 +4737,39 @@ ${formatInventory(input.inventory)}`,
4377
4737
  }
4378
4738
  }
4379
4739
  }
4740
+ // 0.8.2-rc.10 — existing-account-no-extract classifier. Runs once
4741
+ // at loop exit when no credential surfaced AND no more specific
4742
+ // marker (paywall, anti-bot, stuck_loop) was already set on
4743
+ // lastPostVerifyDoneReason. The test identity
4744
+ // (methoxine@gmail.com) accumulates real signups across batches;
4745
+ // re-running against the same vendor lands the bot on an
4746
+ // authenticated dashboard whose API-keys page shows a masked
4747
+ // pre-existing key it cannot reveal (most vendors only show the
4748
+ // key value once at create-time). Reporting these as
4749
+ // oauth_onboarding_failed is misleading — the bot did navigate
4750
+ // correctly, the state is just unrecoverable for this identity.
4751
+ const alreadyClassified = this.lastPostVerifyDoneReason !== null &&
4752
+ this.lastPostVerifyDoneReason.startsWith("[");
4753
+ if (credentials.api_key === undefined &&
4754
+ credentials.username === undefined &&
4755
+ !alreadyClassified) {
4756
+ try {
4757
+ const finalState = await this.browser.getState();
4758
+ const finalText = await this.browser.extractText().catch(() => "");
4759
+ if (detectExistingAccountNoExtract({
4760
+ url: finalState.url,
4761
+ pageText: finalText,
4762
+ lastPlannerReason: this.lastPostVerifyDoneReason ?? "",
4763
+ })) {
4764
+ this.lastPostVerifyDoneReason =
4765
+ `[existing_account_no_extract] at ${finalState.url}; latest planner reason: ${this.lastPostVerifyDoneReason ?? "(none — loop exhausted)"}`;
4766
+ args.steps.push("Post-verify: classified as existing_account_no_extract — masked pre-existing key on an authenticated dashboard.");
4767
+ }
4768
+ }
4769
+ catch {
4770
+ // best-effort classifier — never block returning the (empty) credentials
4771
+ }
4772
+ }
4380
4773
  return credentials;
4381
4774
  }
4382
4775
  // Sign in with the credentials created during signup, so the