@trusty-squire/mcp 1.0.0 → 1.0.1-rc.1

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.
Files changed (177) hide show
  1. package/README.md +9 -15
  2. package/dist/bot/credential-text.d.ts +4 -0
  3. package/dist/bot/credential-text.d.ts.map +1 -0
  4. package/dist/bot/credential-text.js +297 -0
  5. package/dist/bot/credential-text.js.map +1 -0
  6. package/dist/bot/email-verification.d.ts +2 -0
  7. package/dist/bot/email-verification.d.ts.map +1 -0
  8. package/dist/bot/email-verification.js +47 -0
  9. package/dist/bot/email-verification.js.map +1 -0
  10. package/dist/bot/google-login.d.ts +1 -0
  11. package/dist/bot/google-login.d.ts.map +1 -1
  12. package/dist/bot/google-login.js +47 -2
  13. package/dist/bot/google-login.js.map +1 -1
  14. package/dist/bot/index.d.ts +0 -40
  15. package/dist/bot/index.d.ts.map +1 -1
  16. package/dist/bot/index.js +8 -156
  17. package/dist/bot/index.js.map +1 -1
  18. package/dist/bot/login-state.d.ts +2 -0
  19. package/dist/bot/login-state.d.ts.map +1 -1
  20. package/dist/bot/login-state.js +44 -0
  21. package/dist/bot/login-state.js.map +1 -1
  22. package/dist/bot/oauth-detect.d.ts +8 -0
  23. package/dist/bot/oauth-detect.d.ts.map +1 -0
  24. package/dist/bot/oauth-detect.js +329 -0
  25. package/dist/bot/oauth-detect.js.map +1 -0
  26. package/dist/bot/onboarding-capture.d.ts +1 -1
  27. package/dist/bot/onboarding-capture.d.ts.map +1 -1
  28. package/dist/bot/operator-recipe.d.ts +24 -24
  29. package/dist/bot/promote-to-skill.d.ts +1 -1
  30. package/dist/bot/promote-to-skill.d.ts.map +1 -1
  31. package/dist/bot/promote-to-skill.js +7 -5
  32. package/dist/bot/promote-to-skill.js.map +1 -1
  33. package/dist/bot/provision-session.d.ts +10 -0
  34. package/dist/bot/provision-session.d.ts.map +1 -1
  35. package/dist/bot/provision-session.js +126 -5
  36. package/dist/bot/provision-session.js.map +1 -1
  37. package/dist/bot/provision-types.d.ts +69 -0
  38. package/dist/bot/provision-types.d.ts.map +1 -0
  39. package/dist/bot/provision-types.js +9 -0
  40. package/dist/bot/provision-types.js.map +1 -0
  41. package/dist/bot/semantic-transition.d.ts +1 -1
  42. package/dist/bot/semantic-transition.d.ts.map +1 -1
  43. package/dist/skill-cli/cli.d.ts +1 -7
  44. package/dist/skill-cli/cli.d.ts.map +1 -1
  45. package/dist/skill-cli/cli.js +1 -69
  46. package/dist/skill-cli/cli.js.map +1 -1
  47. package/dist/tools/provision-drive.d.ts +48 -8
  48. package/dist/tools/provision-drive.d.ts.map +1 -1
  49. package/dist/tools/provision-drive.js +127 -2
  50. package/dist/tools/provision-drive.js.map +1 -1
  51. package/dist/tools/store-credential.d.ts +4 -4
  52. package/dist/tools/use-credential.d.ts +6 -6
  53. package/package.json +2 -6
  54. package/dist/bot/affordance-probe.d.ts +0 -15
  55. package/dist/bot/affordance-probe.d.ts.map +0 -1
  56. package/dist/bot/affordance-probe.js +0 -61
  57. package/dist/bot/affordance-probe.js.map +0 -1
  58. package/dist/bot/agent.d.ts +0 -449
  59. package/dist/bot/agent.d.ts.map +0 -1
  60. package/dist/bot/agent.js +0 -13634
  61. package/dist/bot/agent.js.map +0 -1
  62. package/dist/bot/debug.d.ts +0 -3
  63. package/dist/bot/debug.d.ts.map +0 -1
  64. package/dist/bot/debug.js +0 -35
  65. package/dist/bot/debug.js.map +0 -1
  66. package/dist/bot/email-code-fetcher.d.ts +0 -5
  67. package/dist/bot/email-code-fetcher.d.ts.map +0 -1
  68. package/dist/bot/email-code-fetcher.js +0 -33
  69. package/dist/bot/email-code-fetcher.js.map +0 -1
  70. package/dist/bot/flow-engine.d.ts +0 -7
  71. package/dist/bot/flow-engine.d.ts.map +0 -1
  72. package/dist/bot/flow-engine.js +0 -13
  73. package/dist/bot/flow-engine.js.map +0 -1
  74. package/dist/bot/form-fill.d.ts +0 -172
  75. package/dist/bot/form-fill.d.ts.map +0 -1
  76. package/dist/bot/form-fill.js +0 -444
  77. package/dist/bot/form-fill.js.map +0 -1
  78. package/dist/bot/inbox-client.d.ts +0 -45
  79. package/dist/bot/inbox-client.d.ts.map +0 -1
  80. package/dist/bot/inbox-client.js +0 -220
  81. package/dist/bot/inbox-client.js.map +0 -1
  82. package/dist/bot/llm-client.d.ts +0 -89
  83. package/dist/bot/llm-client.d.ts.map +0 -1
  84. package/dist/bot/llm-client.js +0 -493
  85. package/dist/bot/llm-client.js.map +0 -1
  86. package/dist/bot/nav-search.d.ts +0 -114
  87. package/dist/bot/nav-search.d.ts.map +0 -1
  88. package/dist/bot/nav-search.js +0 -670
  89. package/dist/bot/nav-search.js.map +0 -1
  90. package/dist/bot/notify-api.d.ts +0 -9
  91. package/dist/bot/notify-api.d.ts.map +0 -1
  92. package/dist/bot/notify-api.js +0 -49
  93. package/dist/bot/notify-api.js.map +0 -1
  94. package/dist/bot/oauth-flow.d.ts +0 -48
  95. package/dist/bot/oauth-flow.d.ts.map +0 -1
  96. package/dist/bot/oauth-flow.js +0 -111
  97. package/dist/bot/oauth-flow.js.map +0 -1
  98. package/dist/bot/observation-frame.d.ts +0 -16
  99. package/dist/bot/observation-frame.d.ts.map +0 -1
  100. package/dist/bot/observation-frame.js +0 -22
  101. package/dist/bot/observation-frame.js.map +0 -1
  102. package/dist/bot/post-signup-action-executor.d.ts +0 -53
  103. package/dist/bot/post-signup-action-executor.d.ts.map +0 -1
  104. package/dist/bot/post-signup-action-executor.js +0 -104
  105. package/dist/bot/post-signup-action-executor.js.map +0 -1
  106. package/dist/bot/post-signup-flow.d.ts +0 -51
  107. package/dist/bot/post-signup-flow.d.ts.map +0 -1
  108. package/dist/bot/post-signup-flow.js +0 -155
  109. package/dist/bot/post-signup-flow.js.map +0 -1
  110. package/dist/bot/post-signup-login-flow.d.ts +0 -28
  111. package/dist/bot/post-signup-login-flow.d.ts.map +0 -1
  112. package/dist/bot/post-signup-login-flow.js +0 -35
  113. package/dist/bot/post-signup-login-flow.js.map +0 -1
  114. package/dist/bot/post-signup-recovery-state.d.ts +0 -150
  115. package/dist/bot/post-signup-recovery-state.d.ts.map +0 -1
  116. package/dist/bot/post-signup-recovery-state.js +0 -253
  117. package/dist/bot/post-signup-recovery-state.js.map +0 -1
  118. package/dist/bot/post-signup-synthetic-capture.d.ts +0 -43
  119. package/dist/bot/post-signup-synthetic-capture.d.ts.map +0 -1
  120. package/dist/bot/post-signup-synthetic-capture.js +0 -84
  121. package/dist/bot/post-signup-synthetic-capture.js.map +0 -1
  122. package/dist/bot/prewarm-cache.d.ts +0 -3
  123. package/dist/bot/prewarm-cache.d.ts.map +0 -1
  124. package/dist/bot/prewarm-cache.js +0 -91
  125. package/dist/bot/prewarm-cache.js.map +0 -1
  126. package/dist/bot/read-otp.d.ts +0 -21
  127. package/dist/bot/read-otp.d.ts.map +0 -1
  128. package/dist/bot/read-otp.js +0 -170
  129. package/dist/bot/read-otp.js.map +0 -1
  130. package/dist/bot/redact.d.ts +0 -3
  131. package/dist/bot/redact.d.ts.map +0 -1
  132. package/dist/bot/redact.js +0 -132
  133. package/dist/bot/redact.js.map +0 -1
  134. package/dist/bot/rejection-record.d.ts +0 -70
  135. package/dist/bot/rejection-record.d.ts.map +0 -1
  136. package/dist/bot/rejection-record.js +0 -76
  137. package/dist/bot/rejection-record.js.map +0 -1
  138. package/dist/bot/replay-skill.d.ts +0 -180
  139. package/dist/bot/replay-skill.d.ts.map +0 -1
  140. package/dist/bot/replay-skill.js +0 -4361
  141. package/dist/bot/replay-skill.js.map +0 -1
  142. package/dist/bot/signup-lock.d.ts +0 -17
  143. package/dist/bot/signup-lock.d.ts.map +0 -1
  144. package/dist/bot/signup-lock.js +0 -174
  145. package/dist/bot/signup-lock.js.map +0 -1
  146. package/dist/bot/signup-oauth-flow.d.ts +0 -16
  147. package/dist/bot/signup-oauth-flow.d.ts.map +0 -1
  148. package/dist/bot/signup-oauth-flow.js +0 -31
  149. package/dist/bot/signup-oauth-flow.js.map +0 -1
  150. package/dist/bot/state-classifier.d.ts +0 -18
  151. package/dist/bot/state-classifier.d.ts.map +0 -1
  152. package/dist/bot/state-classifier.js +0 -127
  153. package/dist/bot/state-classifier.js.map +0 -1
  154. package/dist/bot/terminal-gate.d.ts +0 -22
  155. package/dist/bot/terminal-gate.d.ts.map +0 -1
  156. package/dist/bot/terminal-gate.js +0 -184
  157. package/dist/bot/terminal-gate.js.map +0 -1
  158. package/dist/bot/unwinnable-services.d.ts +0 -7
  159. package/dist/bot/unwinnable-services.d.ts.map +0 -1
  160. package/dist/bot/unwinnable-services.js +0 -69
  161. package/dist/bot/unwinnable-services.js.map +0 -1
  162. package/dist/data/service-categories.d.ts +0 -11
  163. package/dist/data/service-categories.d.ts.map +0 -1
  164. package/dist/data/service-categories.js +0 -149
  165. package/dist/data/service-categories.js.map +0 -1
  166. package/dist/provision-run.d.ts +0 -45
  167. package/dist/provision-run.d.ts.map +0 -1
  168. package/dist/provision-run.js +0 -99
  169. package/dist/provision-run.js.map +0 -1
  170. package/dist/tools/provision-any.d.ts +0 -207
  171. package/dist/tools/provision-any.d.ts.map +0 -1
  172. package/dist/tools/provision-any.js +0 -1519
  173. package/dist/tools/provision-any.js.map +0 -1
  174. package/dist/tools/signup-telemetry.d.ts +0 -38
  175. package/dist/tools/signup-telemetry.d.ts.map +0 -1
  176. package/dist/tools/signup-telemetry.js +0 -103
  177. package/dist/tools/signup-telemetry.js.map +0 -1
@@ -1,18 +0,0 @@
1
- import type { ObservationFrame } from "./observation-frame.js";
2
- export type ProvisionFrameState = "signup_form" | "oauth_provider_login" | "oauth_login_only" | "email_verification_pending" | "captcha_gate" | "api_key_surface" | "api_key_create_modal" | "account_review_gate" | "payment_gate" | "phone_gate" | "unknown";
3
- export interface StateEvidence {
4
- kind: string;
5
- detail: string;
6
- }
7
- export interface Falsifier {
8
- kind: string;
9
- description: string;
10
- }
11
- export interface StateVerdict {
12
- state: ProvisionFrameState;
13
- confidence: number;
14
- evidence: StateEvidence[];
15
- falsifiers: Falsifier[];
16
- }
17
- export declare function classifyObservationFrame(frame: ObservationFrame): StateVerdict;
18
- //# sourceMappingURL=state-classifier.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state-classifier.d.ts","sourceRoot":"","sources":["../../src/bot/state-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,MAAM,mBAAmB,GAC3B,aAAa,GACb,sBAAsB,GACtB,kBAAkB,GAClB,4BAA4B,GAC5B,cAAc,GACd,iBAAiB,GACjB,sBAAsB,GACtB,qBAAqB,GACrB,cAAc,GACd,YAAY,GACZ,SAAS,CAAC;AAEd,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,mBAAmB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,UAAU,EAAE,SAAS,EAAE,CAAC;CACzB;AAgJD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,gBAAgB,GAAG,YAAY,CAW9E"}
@@ -1,127 +0,0 @@
1
- function materialize(value, facts) {
2
- return typeof value === "function" ? value(facts) : value;
3
- }
4
- function verdict(rule, facts) {
5
- return {
6
- state: rule.state,
7
- confidence: materialize(rule.confidence, facts),
8
- evidence: materialize(rule.evidence, facts),
9
- falsifiers: rule.falsifiers ?? [],
10
- };
11
- }
12
- function textOf(frame) {
13
- return `${frame.state.title}\n${frame.visibleText}`.toLowerCase();
14
- }
15
- function hasVisibleInput(frame, types) {
16
- return frame.inventory.some((element) => element.visible === true &&
17
- element.tag === "input" &&
18
- element.type !== null &&
19
- types.includes(element.type));
20
- }
21
- function hasVisibleButtonText(frame, pattern) {
22
- return frame.inventory.some((element) => {
23
- if (element.visible !== true)
24
- return false;
25
- const label = [element.visibleText, element.labelText, element.ariaLabel, element.placeholder, element.iconLabel]
26
- .filter((part) => typeof part === "string" && part.length > 0)
27
- .join(" ");
28
- return pattern.test(label);
29
- });
30
- }
31
- function factsFor(frame) {
32
- return {
33
- frame,
34
- text: textOf(frame),
35
- url: frame.state.url.toLowerCase(),
36
- hasEmail: hasVisibleInput(frame, ["email"]),
37
- hasPassword: hasVisibleInput(frame, ["password"]),
38
- hasButtonText: (pattern) => hasVisibleButtonText(frame, pattern),
39
- };
40
- }
41
- const RULES = [
42
- {
43
- state: "account_review_gate",
44
- confidence: 0.9,
45
- matches: ({ text }) => /waiting room|waitlist|pending review|account review|reviewing your account|approval pending/.test(text),
46
- evidence: [{ kind: "visible_text", detail: "Page text indicates account review / waiting room." }],
47
- falsifiers: [{ kind: "api_key_surface", description: "A visible API-key surface would falsify the review gate." }],
48
- },
49
- {
50
- state: "payment_gate",
51
- confidence: 0.82,
52
- matches: ({ text }) => /add\s+(?:a\s+)?payment\s+method|payment\s+method\s+(?:is\s+)?required|add\s+(?:a\s+)?credit\s+card|credit\s+card\s+required|enter\s+(?:your\s+)?(?:card|payment)|billing\s+setup\s+(?:is\s+)?required|payment\s+required|upgrade\s+your\s+plan\s+to/.test(text),
53
- evidence: [{ kind: "visible_text", detail: "Page text indicates billing/payment is required." }],
54
- falsifiers: [{ kind: "free_key_surface", description: "A key surface reachable without billing would falsify the payment gate." }],
55
- },
56
- {
57
- state: "phone_gate",
58
- confidence: 0.82,
59
- matches: ({ text }) => /phone verification|verify your phone|enter your phone|sms code|text message/.test(text),
60
- evidence: [{ kind: "visible_text", detail: "Page text indicates phone/SMS verification is required." }],
61
- falsifiers: [{ kind: "non_phone_path", description: "A visible non-phone verification path would falsify the phone gate." }],
62
- },
63
- {
64
- state: "captcha_gate",
65
- confidence: 0.78,
66
- matches: ({ text }) => /complete the verification challenge|verify you are human|are you human|captcha|turnstile|cf-turnstile|recaptcha|hcaptcha/.test(text),
67
- evidence: [{ kind: "visible_text", detail: "Page text indicates a captcha or human-verification challenge." }],
68
- falsifiers: [{ kind: "inbox_email_arrived", description: "A verification email after submit can prove a managed captcha passed server-side." }],
69
- },
70
- {
71
- state: "email_verification_pending",
72
- confidence: 0.86,
73
- matches: ({ text }) => /check your email|verify your email|verification email|confirmation email|enter (?:the )?(?:code|otp)/.test(text),
74
- evidence: [{ kind: "visible_text", detail: "Page text indicates email verification is pending." }],
75
- falsifiers: [{ kind: "credential_visible", description: "Visible credentials would falsify the pending verification state." }],
76
- },
77
- {
78
- state: "oauth_login_only",
79
- confidence: 0.82,
80
- matches: ({ text }) => /couldn.t find your account|account doesn.t exist|no account found|sign in to continue/.test(text),
81
- evidence: [{ kind: "visible_text", detail: "Provider/app text indicates login-only OAuth for a new identity." }],
82
- falsifiers: [{ kind: "sign_up_transfer", description: "A successful provider signup transfer would falsify login-only OAuth." }],
83
- },
84
- {
85
- state: "oauth_provider_login",
86
- confidence: 0.74,
87
- matches: ({ url }) => /accounts\.google\.com|github\.com\/login|github\.com\/sessions|oauth|sso|sign[_-]?in/.test(url),
88
- evidence: ({ frame }) => [{ kind: "url", detail: `Provider/auth URL: ${frame.state.url}` }],
89
- falsifiers: [{ kind: "app_callback", description: "Returning to the app callback/dashboard would falsify provider-login state." }],
90
- },
91
- {
92
- state: "api_key_create_modal",
93
- confidence: 0.78,
94
- matches: ({ text, hasButtonText }) => /api key|api token|access token|secret key|developer token|personal access token/.test(text) &&
95
- hasButtonText(/create|generate|new|issue|mint/i),
96
- evidence: [{ kind: "visible_text", detail: "API-key terminology plus create/generate affordance is visible." }],
97
- falsifiers: [{ kind: "credential_extracted", description: "Extracting a fresh credential would supersede create-modal state." }],
98
- },
99
- {
100
- state: "api_key_surface",
101
- confidence: 0.74,
102
- matches: ({ text }) => /api key|api token|access token|secret key|developer token|personal access token/.test(text),
103
- evidence: [{ kind: "visible_text", detail: "API-key/token terminology is visible." }],
104
- falsifiers: [{ kind: "no_extractable_or_creatable_key", description: "No visible value or create path would falsify key-surface readiness." }],
105
- },
106
- {
107
- state: "signup_form",
108
- confidence: ({ hasEmail, hasPassword }) => (hasEmail || hasPassword ? 0.8 : 0.65),
109
- matches: ({ hasEmail, hasPassword, hasButtonText }) => hasEmail || hasPassword || hasButtonText(/sign up|create account|continue with email|start free/i),
110
- evidence: [{ kind: "inventory", detail: "Visible signup/email form affordances are present." }],
111
- falsifiers: [{ kind: "post_submit_transition", description: "A submitted form transitioning to verification/onboarding falsifies signup-form state." }],
112
- },
113
- ];
114
- export function classifyObservationFrame(frame) {
115
- const facts = factsFor(frame);
116
- for (const rule of RULES) {
117
- if (rule.matches(facts))
118
- return verdict(rule, facts);
119
- }
120
- return {
121
- state: "unknown",
122
- confidence: 0.2,
123
- evidence: [{ kind: "frame", detail: `No classifier matched frame ${frame.frameId}.` }],
124
- falsifiers: [],
125
- };
126
- }
127
- //# sourceMappingURL=state-classifier.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"state-classifier.js","sourceRoot":"","sources":["../../src/bot/state-classifier.ts"],"names":[],"mappings":"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"}
@@ -1,22 +0,0 @@
1
- import type { ObservationFrame } from "./observation-frame.js";
2
- import { type StateVerdict } from "./state-classifier.js";
3
- export declare function isAtPaywall(text: string): boolean;
4
- export declare function isAtAccountReviewGate(text: string): boolean;
5
- export declare function isAtPermissionDeniedGate(text: string): boolean;
6
- export declare function isOnboardingReviewGate(verificationFailed: string | undefined, pageText: string): boolean;
7
- export declare function isAtPhoneGate(text: string): boolean;
8
- export declare function isAtOAuthAccountLinkVerificationGate(text: string): boolean;
9
- export declare function isSignupsClosed(text: string): boolean;
10
- export type TerminalGateKind = "none" | "signups_closed" | "payment" | "phone" | "oauth_account_link_verification" | "account_review" | "permission_denied";
11
- export interface TerminalGateInput {
12
- frame: ObservationFrame | null;
13
- fallbackText: string;
14
- lastDoneReason: string | null;
15
- }
16
- export interface TerminalGateVerdict {
17
- kind: TerminalGateKind;
18
- text: string;
19
- stateVerdict: StateVerdict | null;
20
- }
21
- export declare function classifyTerminalGate(input: TerminalGateInput): TerminalGateVerdict;
22
- //# sourceMappingURL=terminal-gate.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"terminal-gate.d.ts","sourceRoot":"","sources":["../../src/bot/terminal-gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AA+B/B,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUjD;AAuBD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAI9D;AAED,wBAAgB,sBAAsB,CACpC,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,QAAQ,EAAE,MAAM,GACf,OAAO,CAET;AAqED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,oCAAoC,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAW1E;AAWD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,gBAAgB,GAChB,SAAS,GACT,OAAO,GACP,iCAAiC,GACjC,gBAAgB,GAChB,mBAAmB,CAAC;AAExB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;CACnC;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,iBAAiB,GAAG,mBAAmB,CAiClF"}
@@ -1,184 +0,0 @@
1
- import { classifyObservationFrame, } from "./state-classifier.js";
2
- // Post-OAuth API key pages that require billing/payment before key issuance.
3
- const ONBOARDING_PAYWALL_PATTERNS = [
4
- /\badd\s+a\s+payment\s+method\b/i,
5
- /\badd\s+(?:a\s+)?credit\s+card\b/i,
6
- /\bpayment\s+method\s+(?:is\s+)?required\b/i,
7
- /\bcredit\s+card\s+required\b/i,
8
- /\benter\s+your\s+card\b/i,
9
- /\benter\s+your\s+payment\b/i,
10
- /\benter\s+payment\s+details\b/i,
11
- /\bconnect\s+a(?:\s+valid)?\s+payment\s+method\b/i,
12
- /\byour\s+(?:free\s+)?trial\s+(?:is\s+)?ending\b/i,
13
- /\bupgrade\s+your\s+plan\s+to\b/i,
14
- /\bstart\s+your\s+paid\s+plan\b/i,
15
- /\brequir(?:es?|ing)\s+(?:a\s+)?credit\s+card\b/i,
16
- /\b(?:credit\s+card|payment)\s+wall\b/i,
17
- /\bcredit\s+card\s+verification\b/i,
18
- /\b(?:plan\s+|account\s+)?payment\s+required\b/i,
19
- /\bcomplet(?:e|ing)\s+(?:billing|payment)\b/i,
20
- /\bbilling\s+setup\s+(?:is\s+)?required\b/i,
21
- /\bpayment\s+form\b/i,
22
- /\binput(?:ting)?\s+payment\s+information\b/i,
23
- /\benter(?:ing)?\s+payment\s+information\b/i,
24
- ];
25
- const PAYWALL_NEGATION_PREFIX = /\b(?:no|without|doesn'?t\s+(?:need|require)|don'?t\s+(?:need|require)|isn'?t)\s+$/i;
26
- const PAYWALL_NEGATION_TEXT = /\b(?:no\s+(?:credit\s+card|payment|payment\s+method)\s+required|without\s+(?:credit\s+card|payment|payment\s+method)\s+required|doesn'?t\s+require\s+(?:a\s+)?(?:credit\s+card|payment|payment\s+method)|don'?t\s+(?:need|require)\s+(?:a\s+)?(?:credit\s+card|payment|payment\s+method))\b/i;
27
- export function isAtPaywall(text) {
28
- for (const pattern of ONBOARDING_PAYWALL_PATTERNS) {
29
- const m = pattern.exec(text);
30
- if (m === null)
31
- continue;
32
- const start = Math.max(0, m.index - 30);
33
- const prefix = text.slice(start, m.index);
34
- if (PAYWALL_NEGATION_PREFIX.test(prefix))
35
- continue;
36
- return true;
37
- }
38
- return false;
39
- }
40
- function hasPaywallNegation(text) {
41
- return PAYWALL_NEGATION_TEXT.test(text);
42
- }
43
- const ACCOUNT_REVIEW_GATE_PATTERNS = [
44
- /\bwaiting\s+room\b/i,
45
- /\b(?:join|on|added\s+to)\s+(?:the\s+|our\s+)?waitlist\b/i,
46
- /\byou'?re\s+on\s+the\s+(?:list|waitlist)\b/i,
47
- /\brequest\s+(?:early\s+)?access\b/i,
48
- /\baccess\s+(?:is\s+)?pending\b/i,
49
- /\bmore\s+information\s+to\s+approve\s+your\s+account\b/i,
50
- /\bto\s+speed\s+up\s+your\s+approval\b/i,
51
- /\byou[’']?ll\s+receive\s+an\s+email\s+when\s+your\s+account\s+is\s+approved\b/i,
52
- /\b(?:your\s+)?account\s+is\s+pending\b/i,
53
- /\bpending\s+approval\b/i,
54
- /\baccount\s+(?:is\s+)?(?:currently\s+)?under\s+review\b/i,
55
- /\byour\s+account\s+is\s+being\s+reviewed\b/i,
56
- /\bwe'?ll\s+email\s+you\s+when\b/i,
57
- /\bawaiting\s+(?:approval|access)\b/i,
58
- ];
59
- export function isAtAccountReviewGate(text) {
60
- return ACCOUNT_REVIEW_GATE_PATTERNS.some((p) => p.test(text));
61
- }
62
- export function isAtPermissionDeniedGate(text) {
63
- return /\b(?:not enough permissions|insufficient permissions|permission denied|access denied|not authorized|unauthorized to|you do not have permission|you don'?t have permission)\b/i.test(text) || /\byou do not have enough permissions\b/i.test(text);
64
- }
65
- export function isOnboardingReviewGate(verificationFailed, pageText) {
66
- return verificationFailed === undefined && isAtAccountReviewGate(pageText);
67
- }
68
- function hasActiveLegalOnboardingForm(frame) {
69
- if (frame === null)
70
- return false;
71
- const text = `${frame.state.title}\n${frame.visibleText}`.toLowerCase();
72
- const hasLegalAcceptance = /\b(?:i\s+am\s+at\s+least\s+\d+|agree\s+to\b.*\b(?:terms|policy|privacy)|accept\s+(?:the\s+)?terms|commercial\s+terms|usage\s+policy|privacy\s+policy)\b/i.test(text) ||
73
- frame.inventory.some((element) => {
74
- if (element.visible !== true)
75
- return false;
76
- if (element.tag !== "input" &&
77
- element.role !== "checkbox" &&
78
- element.role !== "radio") {
79
- return false;
80
- }
81
- const label = [
82
- element.visibleText,
83
- element.labelText,
84
- element.ariaLabel,
85
- element.placeholder,
86
- element.name,
87
- ]
88
- .filter((part) => typeof part === "string" && part.length > 0)
89
- .join(" ");
90
- return /\b(?:terms|policy|privacy|age|accept|agree)\b/i.test(label);
91
- });
92
- if (!hasLegalAcceptance)
93
- return false;
94
- const hasFillableInput = frame.inventory.some((element) => {
95
- if (element.visible !== true)
96
- return false;
97
- if (element.tag !== "input" && element.tag !== "textarea")
98
- return false;
99
- if (element.type !== null &&
100
- !["", "text", "email", "search", "tel", "url"].includes(element.type)) {
101
- return false;
102
- }
103
- const label = [
104
- element.labelText,
105
- element.placeholder,
106
- element.name,
107
- element.ariaLabel,
108
- ]
109
- .filter((part) => typeof part === "string" && part.length > 0)
110
- .join(" ");
111
- return /\b(?:name|call\s+you|display|nickname|organization|organisation|company|team|workspace)\b/i.test(label);
112
- });
113
- if (!hasFillableInput)
114
- return false;
115
- return frame.inventory.some((element) => {
116
- if (element.visible !== true)
117
- return false;
118
- if (element.tag !== "button" && element.role !== "button")
119
- return false;
120
- const label = [
121
- element.visibleText,
122
- element.labelText,
123
- element.ariaLabel,
124
- element.placeholder,
125
- ]
126
- .filter((part) => typeof part === "string" && part.length > 0)
127
- .join(" ");
128
- return /\b(?:continue|next|submit|finish|done|get\s+started|create)\b/i.test(label);
129
- });
130
- }
131
- export function isAtPhoneGate(text) {
132
- return /phone verification|verify your phone|enter your phone|sms code|text message/i.test(text);
133
- }
134
- export function isAtOAuthAccountLinkVerificationGate(text) {
135
- const hay = text.toLowerCase().replace(/\s+/g, " ");
136
- const linkIntent = /\blink\s+(?:your\s+)?(?:google|github|oauth|social)\b/.test(hay) ||
137
- /\blink\s+(?:google|github|oauth|social)\s+account\b/.test(hay) ||
138
- /\baccount\s+already\s+exists\b/.test(hay);
139
- const verifyEmail = /\bverify\s+your\s+email\s+address\b/.test(hay) ||
140
- /\bemail\s+with\s+instructions\b/.test(hay) ||
141
- /\binstructions\s+to\s+link\b/.test(hay);
142
- return linkIntent && verifyEmail;
143
- }
144
- const SIGNUPS_CLOSED_PATTERNS = [
145
- /\bsign[\s-]?ups?\s+(?:are|is)\s+(?:currently\s+)?(?:closed|disabled|paused|not\s+(?:open|available|being\s+accepted))\b/i,
146
- /\b(?:we\s+are|we're)\s+not\s+(?:currently\s+)?accepting\s+(?:new\s+)?(?:sign[\s-]?ups|registrations|users|accounts)\b/i,
147
- /\bregistration\s+(?:is\s+)?(?:currently\s+)?(?:closed|disabled)\b/i,
148
- /\b(?:sign[\s-]?up|registration|access)\s+is\s+(?:by\s+)?invite[\s-]?only\b/i,
149
- /\binvite[\s-]?only\s+(?:beta|access|signup|registration)\b/i,
150
- /\brequest\s+an\s+invite\b/i,
151
- ];
152
- export function isSignupsClosed(text) {
153
- return SIGNUPS_CLOSED_PATTERNS.some((p) => p.test(text));
154
- }
155
- export function classifyTerminalGate(input) {
156
- const text = input.lastDoneReason !== null
157
- ? `${input.fallbackText}\n${input.lastDoneReason}`
158
- : input.fallbackText;
159
- const stateVerdict = input.frame !== null
160
- ? classifyObservationFrame({ ...input.frame, visibleText: text })
161
- : null;
162
- if (isSignupsClosed(text)) {
163
- return { kind: "signups_closed", text, stateVerdict };
164
- }
165
- if (stateVerdict?.state === "phone_gate" || isAtPhoneGate(text)) {
166
- return { kind: "phone", text, stateVerdict };
167
- }
168
- if (isAtOAuthAccountLinkVerificationGate(text)) {
169
- return { kind: "oauth_account_link_verification", text, stateVerdict };
170
- }
171
- if (isAtPaywall(text) || (stateVerdict?.state === "payment_gate" && !hasPaywallNegation(text))) {
172
- return { kind: "payment", text, stateVerdict };
173
- }
174
- if (isAtPermissionDeniedGate(text)) {
175
- return { kind: "permission_denied", text, stateVerdict };
176
- }
177
- if ((stateVerdict?.state === "account_review_gate" ||
178
- isAtAccountReviewGate(text)) &&
179
- !(hasActiveLegalOnboardingForm(input.frame) && !isAtAccountReviewGate(text))) {
180
- return { kind: "account_review", text, stateVerdict };
181
- }
182
- return { kind: "none", text, stateVerdict };
183
- }
184
- //# sourceMappingURL=terminal-gate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"terminal-gate.js","sourceRoot":"","sources":["../../src/bot/terminal-gate.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,GAEzB,MAAM,uBAAuB,CAAC;AAE/B,6EAA6E;AAC7E,MAAM,2BAA2B,GAAsB;IACrD,iCAAiC;IACjC,mCAAmC;IACnC,4CAA4C;IAC5C,+BAA+B;IAC/B,0BAA0B;IAC1B,6BAA6B;IAC7B,gCAAgC;IAChC,kDAAkD;IAClD,kDAAkD;IAClD,iCAAiC;IACjC,iCAAiC;IACjC,iDAAiD;IACjD,uCAAuC;IACvC,mCAAmC;IACnC,gDAAgD;IAChD,6CAA6C;IAC7C,2CAA2C;IAC3C,qBAAqB;IACrB,6CAA6C;IAC7C,4CAA4C;CAC7C,CAAC;AAEF,MAAM,uBAAuB,GAC3B,oFAAoF,CAAC;AACvF,MAAM,qBAAqB,GACzB,8RAA8R,CAAC;AAEjS,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,KAAK,MAAM,OAAO,IAAI,2BAA2B,EAAE,CAAC;QAClD,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,KAAK,IAAI;YAAE,SAAS;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,SAAS;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY;IACtC,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,4BAA4B,GAAsB;IACtD,qBAAqB;IACrB,0DAA0D;IAC1D,6CAA6C;IAC7C,oCAAoC;IACpC,iCAAiC;IACjC,yDAAyD;IACzD,wCAAwC;IACxC,gFAAgF;IAChF,yCAAyC;IACzC,yBAAyB;IACzB,0DAA0D;IAC1D,6CAA6C;IAC7C,kCAAkC;IAClC,qCAAqC;CACtC,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,OAAO,4BAA4B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,IAAY;IACnD,OAAO,+KAA+K,CAAC,IAAI,CACzL,IAAI,CACL,IAAI,yCAAyC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,kBAAsC,EACtC,QAAgB;IAEhB,OAAO,kBAAkB,KAAK,SAAS,IAAI,qBAAqB,CAAC,QAAQ,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,4BAA4B,CAAC,KAA8B;IAClE,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,IAAI,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;IACxE,MAAM,kBAAkB,GACtB,0JAA0J,CAAC,IAAI,CAC7J,IAAI,CACL;QACD,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;YAC/B,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI;gBAAE,OAAO,KAAK,CAAC;YAC3C,IACE,OAAO,CAAC,GAAG,KAAK,OAAO;gBACvB,OAAO,CAAC,IAAI,KAAK,UAAU;gBAC3B,OAAO,CAAC,IAAI,KAAK,OAAO,EACxB,CAAC;gBACD,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,KAAK,GAAG;gBACZ,OAAO,CAAC,WAAW;gBACnB,OAAO,CAAC,SAAS;gBACjB,OAAO,CAAC,SAAS;gBACjB,OAAO,CAAC,WAAW;gBACnB,OAAO,CAAC,IAAI;aACb;iBACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;iBAC7E,IAAI,CAAC,GAAG,CAAC,CAAC;YACb,OAAO,gDAAgD,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,IAAI,CAAC,kBAAkB;QAAE,OAAO,KAAK,CAAC;IAEtC,MAAM,gBAAgB,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACxD,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,OAAO,CAAC,GAAG,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,KAAK,UAAU;YAAE,OAAO,KAAK,CAAC;QACxE,IACE,OAAO,CAAC,IAAI,KAAK,IAAI;YACrB,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,EACrE,CAAC;YACD,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,KAAK,GAAG;YACZ,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,WAAW;YACnB,OAAO,CAAC,IAAI;YACZ,OAAO,CAAC,SAAS;SAClB;aACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;aAC7E,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,4FAA4F,CAAC,IAAI,CACtG,KAAK,CACN,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,gBAAgB;QAAE,OAAO,KAAK,CAAC;IAEpC,OAAO,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;QACtC,IAAI,OAAO,CAAC,OAAO,KAAK,IAAI;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACxE,MAAM,KAAK,GAAG;YACZ,OAAO,CAAC,WAAW;YACnB,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,SAAS;YACjB,OAAO,CAAC,WAAW;SACpB;aACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;aAC7E,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,gEAAgE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,OAAO,8EAA8E,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,UAAU,oCAAoC,CAAC,IAAY;IAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpD,MAAM,UAAU,GACd,uDAAuD,CAAC,IAAI,CAAC,GAAG,CAAC;QACjE,qDAAqD,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/D,gCAAgC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,MAAM,WAAW,GACf,qCAAqC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/C,iCAAiC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3C,8BAA8B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,UAAU,IAAI,WAAW,CAAC;AACnC,CAAC;AAED,MAAM,uBAAuB,GAAsB;IACjD,0HAA0H;IAC1H,wHAAwH;IACxH,oEAAoE;IACpE,6EAA6E;IAC7E,6DAA6D;IAC7D,4BAA4B;CAC7B,CAAC;AAEF,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3D,CAAC;AAuBD,MAAM,UAAU,oBAAoB,CAAC,KAAwB;IAC3D,MAAM,IAAI,GACR,KAAK,CAAC,cAAc,KAAK,IAAI;QAC3B,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,cAAc,EAAE;QAClD,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;IACzB,MAAM,YAAY,GAChB,KAAK,CAAC,KAAK,KAAK,IAAI;QAClB,CAAC,CAAC,wBAAwB,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QACjE,CAAC,CAAC,IAAI,CAAC;IAEX,IAAI,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACxD,CAAC;IACD,IAAI,YAAY,EAAE,KAAK,KAAK,YAAY,IAAI,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC/C,CAAC;IACD,IAAI,oCAAoC,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,OAAO,EAAE,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACzE,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,KAAK,cAAc,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAC/F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACjD,CAAC;IACD,IAAI,wBAAwB,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC3D,CAAC;IACD,IACE,CAAC,YAAY,EAAE,KAAK,KAAK,qBAAqB;QAC5C,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC9B,CAAC,CAAC,4BAA4B,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAC5E,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;AAC9C,CAAC"}
@@ -1,7 +0,0 @@
1
- export type ManualGate = "spa_broken" | "max_antibot" | "sms_phone" | "totp" | "credit_card" | "github_2fa";
2
- export interface ManualRoute {
3
- gate: ManualGate;
4
- reason: string;
5
- }
6
- export declare function classifyUnwinnable(service: string): ManualRoute | null;
7
- //# sourceMappingURL=unwinnable-services.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unwinnable-services.d.ts","sourceRoot":"","sources":["../../src/bot/unwinnable-services.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,UAAU,GAElB,YAAY,GAEZ,aAAa,GAEb,WAAW,GAEX,MAAM,GAEN,aAAa,GAEb,YAAY,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AA0DD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAGtE"}
@@ -1,69 +0,0 @@
1
- // unwinnable-services.ts — services the bot should NOT attempt (AB6).
2
- //
3
- // A handful of services are a 0% prospect for automated signup, for reasons
4
- // that are NOT our bug and won't change by re-running: their own SPA refuses to
5
- // initialize under automation, their own dashboard runs maximum anti-bot, or
6
- // the API token sits behind a human gate (SMS, authenticator TOTP, a credit
7
- // card). Driving the bot at them wastes ~6 minutes + LLM calls per run and adds
8
- // nothing. classifyUnwinnable lets the entry point short-circuit to a clear
9
- // `manual_signup_required` outcome before launching Chrome.
10
- //
11
- // This is a curated denylist, not a heuristic — edit it as gates change (e.g.
12
- // drop the sms_phone entries once F12's relay ships and the bot can clear them).
13
- // Keyed by the normalized service slug.
14
- const UNWINNABLE = {
15
- // clerk REMOVED 2026-06-24 — the spa_broken flag was STALE. A forced run
16
- // (UNIVERSAL_BOT_FORCE_UNWINNABLE=1) drove the dashboard SPA fine: Google
17
- // OAuth (login-only) → email path → OTP arrived (verifications@clerk.dev via
18
- // the workspace catch-all) → extracted api_key → auto-promoted skill
19
- // 8YACTGEPASNKRA7AS2W7KXHRFM. The SPA does initialize under automation.
20
- cloudflare: {
21
- gate: "max_antibot",
22
- reason: "Cloudflare's own dashboard runs maximum Turnstile + IP risk-score; " +
23
- "manual signup is the realistic call.",
24
- },
25
- vercel: {
26
- gate: "sms_phone",
27
- reason: "API tokens gated behind phone + SMS verification — needs the F12 relay or the operator.",
28
- },
29
- mailersend: {
30
- gate: "sms_phone",
31
- reason: "Signup completes but stops at a phone-verification wall — F12 relay or operator.",
32
- },
33
- twilio: {
34
- gate: "sms_phone",
35
- reason: "Phone + SMS verification required before API access — F12 relay or operator.",
36
- },
37
- sendgrid: {
38
- gate: "sms_phone",
39
- reason: "Phone/SMS + (historically) credit-card gate before API key access.",
40
- },
41
- mailgun: {
42
- gate: "credit_card",
43
- reason: "Credit card / phone verification required before the API key is reachable.",
44
- },
45
- circleci: {
46
- gate: "credit_card",
47
- reason: "Credit-card gate on token access.",
48
- },
49
- betterstack: {
50
- gate: "credit_card",
51
- reason: "Credit-card gate before the API token.",
52
- },
53
- northflank: {
54
- gate: "github_2fa",
55
- reason: "Signup needs a GitHub-app install with install-time sudo-2FA — operator-only, " +
56
- "not automatable.",
57
- },
58
- };
59
- function normalizeSlug(service) {
60
- return service.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
61
- }
62
- // Returns the manual route for an unwinnable service, or null. Matches on the
63
- // normalized slug AND a hyphen-stripped form so "BetterStack" / "better-stack"
64
- // / "betterstack" all resolve.
65
- export function classifyUnwinnable(service) {
66
- const slug = normalizeSlug(service);
67
- return UNWINNABLE[slug] ?? UNWINNABLE[slug.replace(/-/g, "")] ?? null;
68
- }
69
- //# sourceMappingURL=unwinnable-services.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"unwinnable-services.js","sourceRoot":"","sources":["../../src/bot/unwinnable-services.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,4EAA4E;AAC5E,gFAAgF;AAChF,6EAA6E;AAC7E,4EAA4E;AAC5E,gFAAgF;AAChF,4EAA4E;AAC5E,4DAA4D;AAC5D,EAAE;AACF,8EAA8E;AAC9E,iFAAiF;AAqBjF,wCAAwC;AACxC,MAAM,UAAU,GAA0C;IACxD,yEAAyE;IACzE,0EAA0E;IAC1E,6EAA6E;IAC7E,qEAAqE;IACrE,wEAAwE;IACxE,UAAU,EAAE;QACV,IAAI,EAAE,aAAa;QACnB,MAAM,EACJ,qEAAqE;YACrE,sCAAsC;KACzC;IACD,MAAM,EAAE;QACN,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,yFAAyF;KAClG;IACD,UAAU,EAAE;QACV,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,kFAAkF;KAC3F;IACD,MAAM,EAAE;QACN,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,8EAA8E;KACvF;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,oEAAoE;KAC7E;IACD,OAAO,EAAE;QACP,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,4EAA4E;KACrF;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,mCAAmC;KAC5C;IACD,WAAW,EAAE;QACX,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,wCAAwC;KACjD;IACD,UAAU,EAAE;QACV,IAAI,EAAE,YAAY;QAClB,MAAM,EACJ,gFAAgF;YAChF,kBAAkB;KACrB;CACF,CAAC;AAEF,SAAS,aAAa,CAAC,OAAe;IACpC,OAAO,OAAO,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,8EAA8E;AAC9E,+EAA+E;AAC/E,+BAA+B;AAC/B,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IACpC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC;AACxE,CAAC"}
@@ -1,11 +0,0 @@
1
- export interface ServiceCategoryEntry {
2
- slug: string;
3
- category: string;
4
- }
5
- export declare const SERVICE_CATEGORIES: readonly ServiceCategoryEntry[];
6
- /** Return the category for `slug`, or null if unknown. */
7
- export declare function categoryFor(slug: string): string | null;
8
- /** Category-peer slugs for `slug`, EXCLUDING `slug` itself.
9
- * Empty array when the slug is unknown or its category has no peers. */
10
- export declare function categoryPeersOf(slug: string): string[];
11
- //# sourceMappingURL=service-categories.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"service-categories.d.ts","sourceRoot":"","sources":["../../src/data/service-categories.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,eAAO,MAAM,kBAAkB,EAAE,SAAS,oBAAoB,EAgI7D,CAAC;AAgBF,0DAA0D;AAC1D,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEvD;AAED;yEACyE;AACzE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAMtD"}
@@ -1,149 +0,0 @@
1
- // T44 — service-category map. Inlined as a TypeScript constant
2
- // (instead of a yaml-at-runtime read) so the data ships in the
3
- // compiled tarball without a separate file-copy step in the build,
4
- // and there's no production-vs-dev path discrepancy. The yaml at
5
- // service-categories.yaml is the human-editable source of truth —
6
- // regenerate this file from it via `pnpm gen:service-categories`
7
- // when adding services.
8
- //
9
- // Slug = registry canonical (anthropic-api, together-ai, …). Agent-
10
- // provided service strings that don't match here just don't get a
11
- // category-peer recommendation — soft hint, not an error.
12
- // Categories — keep stable; downstream queries reference these names.
13
- export const SERVICE_CATEGORIES = [
14
- // Email — transactional + marketing
15
- { slug: "resend", category: "email-transactional" },
16
- { slug: "postmark", category: "email-transactional" },
17
- { slug: "mailgun", category: "email-transactional" },
18
- { slug: "sendgrid", category: "email-transactional" },
19
- { slug: "brevo", category: "email-transactional" },
20
- { slug: "mailtrap", category: "email-transactional" },
21
- { slug: "loops", category: "email-transactional" },
22
- { slug: "plunk", category: "email-transactional" },
23
- { slug: "mailersend", category: "email-transactional" },
24
- // LLM API (chat / completion / embedding endpoints)
25
- { slug: "openrouter", category: "llm-api" },
26
- { slug: "anthropic-api", category: "llm-api" },
27
- { slug: "deepinfra", category: "llm-api" },
28
- { slug: "replicate", category: "llm-api" },
29
- { slug: "together-ai", category: "llm-api" },
30
- { slug: "groq", category: "llm-api" },
31
- { slug: "fireworks", category: "llm-api" },
32
- { slug: "mistral", category: "llm-api" },
33
- { slug: "perplexity", category: "llm-api" },
34
- { slug: "cohere", category: "llm-api" },
35
- { slug: "hyperbolic", category: "llm-api" },
36
- { slug: "baseten", category: "llm-api" },
37
- // Vector DB
38
- { slug: "pinecone", category: "vector-db" },
39
- { slug: "weaviate", category: "vector-db" },
40
- { slug: "qdrant", category: "vector-db" },
41
- { slug: "chroma", category: "vector-db" },
42
- // Managed relational + KV databases
43
- { slug: "planetscale", category: "managed-db" },
44
- { slug: "supabase", category: "managed-db" },
45
- { slug: "neon", category: "managed-db" },
46
- { slug: "turso", category: "managed-db" },
47
- { slug: "xata", category: "managed-db" },
48
- { slug: "convex", category: "managed-db" },
49
- { slug: "upstash", category: "managed-db" },
50
- { slug: "redis-cloud", category: "managed-db" },
51
- { slug: "cockroachdb", category: "managed-db" },
52
- // Application hosting / PaaS
53
- { slug: "railway", category: "app-hosting" },
54
- { slug: "porter", category: "app-hosting" },
55
- { slug: "zeabur", category: "app-hosting" },
56
- { slug: "render", category: "app-hosting" },
57
- { slug: "vercel", category: "app-hosting" },
58
- { slug: "netlify", category: "app-hosting" },
59
- { slug: "fly", category: "app-hosting" },
60
- { slug: "northflank", category: "app-hosting" },
61
- { slug: "digitalocean", category: "app-hosting" },
62
- // Error tracking / observability / logging
63
- { slug: "sentry", category: "error-tracking" },
64
- { slug: "highlight", category: "error-tracking" },
65
- { slug: "axiom", category: "error-tracking" },
66
- { slug: "honeycomb", category: "error-tracking" },
67
- { slug: "baselime", category: "error-tracking" },
68
- { slug: "last9", category: "error-tracking" },
69
- { slug: "betterstack-logs", category: "error-tracking" },
70
- { slug: "grafana-cloud", category: "error-tracking" },
71
- // Product analytics
72
- { slug: "posthog", category: "product-analytics" },
73
- { slug: "mixpanel", category: "product-analytics" },
74
- { slug: "amplitude", category: "product-analytics" },
75
- { slug: "plausible", category: "product-analytics" },
76
- { slug: "fathom", category: "product-analytics" },
77
- // Image / video CDN + transformation
78
- { slug: "cloudinary", category: "image-media-cdn" },
79
- { slug: "uploadcare", category: "image-media-cdn" },
80
- { slug: "imagekit", category: "image-media-cdn" },
81
- // Search-as-a-service
82
- { slug: "algolia", category: "search" },
83
- { slug: "meilisearch", category: "search" },
84
- { slug: "typesense", category: "search" },
85
- // Auth / identity / SSO
86
- { slug: "clerk", category: "auth-identity" },
87
- { slug: "stytch", category: "auth-identity" },
88
- { slug: "workos", category: "auth-identity" },
89
- { slug: "kinde", category: "auth-identity" },
90
- // Feature flags / experimentation
91
- { slug: "launchdarkly", category: "feature-flags" },
92
- { slug: "statsig", category: "feature-flags" },
93
- { slug: "growthbook", category: "feature-flags" },
94
- { slug: "flagsmith", category: "feature-flags" },
95
- // Background jobs / workflows / webhooks
96
- { slug: "inngest", category: "background-jobs" },
97
- { slug: "temporal", category: "background-jobs" },
98
- { slug: "hatchet", category: "background-jobs" },
99
- { slug: "trigger", category: "background-jobs" },
100
- { slug: "hookdeck", category: "background-jobs" },
101
- { slug: "svix", category: "background-jobs" },
102
- // Forms
103
- { slug: "tally", category: "forms" },
104
- { slug: "typeform", category: "forms" },
105
- // Scraping / browser-as-a-service
106
- { slug: "apify", category: "scraping" },
107
- { slug: "firecrawl", category: "scraping" },
108
- { slug: "scrapingbee", category: "scraping" },
109
- { slug: "browserbase", category: "scraping" },
110
- // Geo / IP intelligence
111
- { slug: "ipinfo", category: "geo-ip" },
112
- { slug: "ipdata", category: "geo-ip" },
113
- // Uptime / availability monitoring
114
- { slug: "betterstack-uptime", category: "uptime" },
115
- { slug: "cronitor", category: "uptime" },
116
- // Dev environments / sandboxes
117
- { slug: "e2b", category: "dev-environments" },
118
- { slug: "daytona", category: "dev-environments" },
119
- { slug: "replit", category: "dev-environments" },
120
- { slug: "codesandbox", category: "dev-environments" },
121
- { slug: "stackblitz", category: "dev-environments" },
122
- // Comms — SMS / voice
123
- { slug: "twilio", category: "comms" },
124
- ];
125
- const BY_SLUG = new Map(SERVICE_CATEGORIES.map((e) => [e.slug.toLowerCase(), e.category]));
126
- const BY_CATEGORY = (() => {
127
- const m = new Map();
128
- for (const e of SERVICE_CATEGORIES) {
129
- const arr = m.get(e.category) ?? [];
130
- arr.push(e.slug.toLowerCase());
131
- m.set(e.category, arr);
132
- }
133
- return m;
134
- })();
135
- /** Return the category for `slug`, or null if unknown. */
136
- export function categoryFor(slug) {
137
- return BY_SLUG.get(slug.toLowerCase()) ?? null;
138
- }
139
- /** Category-peer slugs for `slug`, EXCLUDING `slug` itself.
140
- * Empty array when the slug is unknown or its category has no peers. */
141
- export function categoryPeersOf(slug) {
142
- const lc = slug.toLowerCase();
143
- const cat = BY_SLUG.get(lc);
144
- if (cat === undefined)
145
- return [];
146
- const peers = BY_CATEGORY.get(cat) ?? [];
147
- return peers.filter((p) => p !== lc);
148
- }
149
- //# sourceMappingURL=service-categories.js.map