@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.
Files changed (37) hide show
  1. package/assets/screencaps/connect-walkthrough.png +0 -0
  2. package/assets/screencaps/connect-walkthrough.svg +6 -0
  3. package/dist/bot/agent.d.ts +1 -0
  4. package/dist/bot/agent.d.ts.map +1 -1
  5. package/dist/bot/agent.js +167 -7
  6. package/dist/bot/agent.js.map +1 -1
  7. package/dist/bot/browser.d.ts +1 -0
  8. package/dist/bot/browser.d.ts.map +1 -1
  9. package/dist/bot/browser.js +51 -1
  10. package/dist/bot/browser.js.map +1 -1
  11. package/dist/bot/google-login.d.ts.map +1 -1
  12. package/dist/bot/google-login.js +79 -23
  13. package/dist/bot/google-login.js.map +1 -1
  14. package/dist/bot/notify-api.d.ts +7 -0
  15. package/dist/bot/notify-api.d.ts.map +1 -0
  16. package/dist/bot/notify-api.js +41 -0
  17. package/dist/bot/notify-api.js.map +1 -0
  18. package/dist/bot/promote-to-skill.d.ts.map +1 -1
  19. package/dist/bot/promote-to-skill.js +161 -24
  20. package/dist/bot/promote-to-skill.js.map +1 -1
  21. package/dist/bot/replay-skill.js +86 -4
  22. package/dist/bot/replay-skill.js.map +1 -1
  23. package/dist/install/cli.d.ts +1 -0
  24. package/dist/install/cli.d.ts.map +1 -1
  25. package/dist/install/cli.js +169 -39
  26. package/dist/install/cli.js.map +1 -1
  27. package/dist/install/ui.d.ts +6 -2
  28. package/dist/install/ui.d.ts.map +1 -1
  29. package/dist/install/ui.js +108 -47
  30. package/dist/install/ui.js.map +1 -1
  31. package/dist/session.d.ts +1 -0
  32. package/dist/session.d.ts.map +1 -1
  33. package/dist/session.js.map +1 -1
  34. package/dist/tools/provision-any.d.ts.map +1 -1
  35. package/dist/tools/provision-any.js +25 -0
  36. package/dist/tools/provision-any.js.map +1 -1
  37. package/package.json +1 -1
@@ -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,&apos;JetBrains Mono&apos;,&apos;Fira Code&apos;,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">&quot;sign me up for Resend&quot; </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>
@@ -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[]): {
@@ -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":"AAUA,OAAO,KAAK,EACV,iBAAiB,EAGjB,cAAc,EACd,kBAAkB,EACnB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,sBAAsB,CAAC;AAO9B,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,OAAO,EACb,MAAM,iBAAiB,CAAC;AAMzB,MAAM,WAAW,UAAU;IACzB,YAAY,CAAC,KAAK,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,OAAO,EAAE;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAC;YAAC,aAAa,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrE,eAAe,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC;QACV,OAAO,EAAE,MAAM,CAAC;QAChB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;KACrC,CAAC,CAAC;CACJ;AAiFD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUjD;AAMD,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED,qBAAa,qBAAsB,SAAQ,KAAK;gBAClC,MAAM,EAAE,MAAM;CAI3B;AAwCD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMtD;AAQD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAI/E;AAID,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAUtD;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,MAAM,CAAC;IAC/B,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAI/B,0BAA0B,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAIhD,mBAAmB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAOzC,aAAa,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;IAO5C,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAK/B,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAQjC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;IAUtD,sBAAsB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC9C;AAQD,MAAM,MAAM,sBAAsB,GAAG,CAAC,KAAK,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAUpB,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEpB,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;KACnC,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAIhB,SAAS,CAAC,EAAE,MAAM,CAAC;IAMnB,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAMjC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAOhC,OAAO,CAAC,EAAE,OAAO,CAAC;IAQlB,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IAKvB,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;QAIhC,OAAO,EAAE,cAAc,CAAC;QACxB,kBAAkB,EAAE,OAAO,CAAC;QAI5B,OAAO,EAAE,OAAO,CAAC;KAClB,CAAC;CACH;AAGD,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,aAAa,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC/F;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAgDD,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAOjE;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAKD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAOnD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAKtD,QAAA,MAAM,gBAAgB,0EAOZ,CAAC;AACX,KAAK,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAkHvD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACrC,UAAU,CAoCZ;AAaD,wBAAgB,eAAe,CAAC,SAAS,EAAE,SAAS,kBAAkB,EAAE,GAAG,MAAM,CAiGhF;AA6ED,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAgCT;AASD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAItE;AAOD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe9D;AA+BD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE;IAC1C,SAAS,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACzC,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,OAAO,CA8DV;AAeD,wBAAgB,+BAA+B,CAC7C,SAAS,EAAE,SAAS,kBAAkB,EAAE,GACvC,eAAe,EAAE,CASnB;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,SAAS,kBAAkB,EAAE,GACvC,OAAO,CAmBT;AAgBD,wBAAgB,eAAe,CAC7B,SAAS,EAAE,SAAS,kBAAkB,EAAE,EACxC,QAAQ,EAAE,eAAe,GACxB,kBAAkB,GAAG,IAAI,CAkC3B;AAKD,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,SAAS,kBAAkB,EAAE,EACxC,SAAS,EAAE,SAAS,eAAe,EAAE,GACpC;IAAE,QAAQ,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAAG,IAAI,CAMlE;AAQD,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,EACX,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GACrC,cAAc,CAqFhB;AAgED,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAYnF;AAYD,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAcf;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAwEjE;AASD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAa5E;AASD,qBAAa,WAAW;IAqrBpB,OAAO,CAAC,OAAO;IAjrBjB,OAAO,CAAC,YAAY,CAAK;IAIzB,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;IAC7C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAOlC,OAAO,CAAC,gBAAgB,CAAsC;IAM9D,OAAO,CAAC,UAAU;YAuBJ,cAAc;YA2Cd,WAAW;YAsDX,oBAAoB;YAmYpB,cAAc;YA8Ed,sBAAsB;YAgCtB,UAAU;IA4CxB,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAyB;IAIjE,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAgB;IAG/C,OAAO,CAAC,cAAc,CAAM;gBAGlB,OAAO,EAAE,iBAAiB,EAClC,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,EACzB,IAAI,GAAE;QACJ,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;QAChD,aAAa,CAAC,EAAE,aAAa,CAAC;KAC1B;IAwBR,IAAI,QAAQ,IAAI,SAAS,MAAM,EAAE,CAEhC;YAOa,OAAO;YAcP,YAAY;YA+CZ,UAAU;IA6ClB,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC;YAsCvC,SAAS;YAiYT,YAAY;IAyX1B,OAAO,CAAC,UAAU;YAeJ,sBAAsB;YA0BtB,qBAAqB;YAerB,cAAc;IAkE5B,OAAO,CAAC,0BAA0B;IAYlC,OAAO,CAAC,oBAAoB;YAQd,wBAAwB;YA4CxB,cAAc;YAggBd,oBAAoB;YA6CpB,kBAAkB;YA+JlB,cAAc;YA2Ed,mBAAmB;YAsDnB,kBAAkB;YAuHlB,uBAAuB;CA4CtC"}
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
- /\bsk-or-v1-[a-zA-Z0-9_-]{20,}/, // OpenRouter (sk-or-v1-…)
899
- /\bsk-ant-[a-zA-Z0-9_-]{20,}/, // Anthropic (sk-ant-…)
900
- /\bsk-proj-[a-zA-Z0-9_-]{20,}/, // OpenAI project key
901
- /\bsk-[a-zA-Z0-9]{40,}/, // OpenAI legacy (`sk-` + ~48 chars, no dashes)
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
- steps.push(`Auto-OAuth: profile has a session for ${loggedIn.join(", ")} ` +
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 loggedIn;
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