@runcofactor/cli 0.52.0 → 0.53.0

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 (225) hide show
  1. package/README.md +2 -0
  2. package/dist/{account-3ZG24MOE.js → account-MRZ54P5P.js} +5 -5
  3. package/dist/{alert-5G7PTAX2.js → alert-XBHELHEI.js} +8 -8
  4. package/dist/{api-catalog-IBYAFKKQ.js → api-catalog-GWYRX53L.js} +5 -5
  5. package/dist/{api-key-UXC44BDR.js → api-key-FH6JN447.js} +5 -5
  6. package/dist/{attachment-T6IRFQW3.js → attachment-J7GRVT5F.js} +5 -5
  7. package/dist/{auth-SHOCJE6Z.js → auth-VZZQXRDR.js} +3 -3
  8. package/dist/{benchmark-NJ2U6VTC.js → benchmark-A3SNDARF.js} +5 -5
  9. package/dist/{blackcat-RQJVFGXQ.js → blackcat-UM6TBQBN.js} +3 -3
  10. package/dist/{chunk-DHAGRM2F.js → chunk-33U56YGD.js} +14 -5
  11. package/dist/{chunk-DHAGRM2F.js.map → chunk-33U56YGD.js.map} +1 -1
  12. package/dist/{chunk-M752EUK3.js → chunk-3JU4UYYN.js} +5 -5
  13. package/dist/{chunk-G6BCST3G.js → chunk-3ZOUNCA5.js} +7 -7
  14. package/dist/{chunk-76Z6E7XX.js → chunk-4UZN6TVT.js} +74 -131
  15. package/dist/chunk-4UZN6TVT.js.map +1 -0
  16. package/dist/{chunk-ABT3BLRC.js → chunk-5TKXHS3X.js} +3 -3
  17. package/dist/{chunk-QCYSONXI.js → chunk-CRYHWO4M.js} +2 -2
  18. package/dist/{chunk-QTYUM4ZB.js → chunk-EJ3ZPH5U.js} +23 -187
  19. package/dist/chunk-EJ3ZPH5U.js.map +1 -0
  20. package/dist/{chunk-I5RHTCPY.js → chunk-EL6KJ4PO.js} +4 -4
  21. package/dist/{chunk-ZL4O6C42.js → chunk-HXBK3AGD.js} +2 -2
  22. package/dist/{chunk-PRERH4DN.js → chunk-I2SOHQ2C.js} +3 -3
  23. package/dist/{chunk-CYSPCGO6.js → chunk-JEHHEMUL.js} +5 -5
  24. package/dist/{chunk-LIEADTEF.js → chunk-LJFVRJCA.js} +2 -2
  25. package/dist/{chunk-UEJ2HTKU.js → chunk-MJVUMVLO.js} +19 -1
  26. package/dist/chunk-MJVUMVLO.js.map +1 -0
  27. package/dist/chunk-N55RKCGR.js +24 -0
  28. package/dist/chunk-N55RKCGR.js.map +1 -0
  29. package/dist/{chunk-PHNH3CEU.js → chunk-O4Z44BR7.js} +5 -5
  30. package/dist/{chunk-QA37WVF6.js → chunk-OQFCZERZ.js} +6 -6
  31. package/dist/{chunk-EUVB6Y3C.js → chunk-P7L5KELH.js} +8 -8
  32. package/dist/chunk-P7L5KELH.js.map +1 -0
  33. package/dist/{chunk-Z3MDQSZG.js → chunk-PJFFGQSB.js} +2 -2
  34. package/dist/{chunk-IY3ZK46I.js → chunk-QOVJUSSL.js} +2 -2
  35. package/dist/{chunk-RPJMQBB5.js → chunk-QXU4G4YN.js} +3 -3
  36. package/dist/{chunk-SZSTJIYU.js → chunk-RRSUKARV.js} +4 -4
  37. package/dist/{chunk-775FI436.js → chunk-RVD6J6IZ.js} +2 -2
  38. package/dist/{chunk-5UUIBY6E.js → chunk-TAVBFLCR.js} +3 -3
  39. package/dist/{chunk-ROX7N3RK.js → chunk-V7HB5LAU.js} +10 -7
  40. package/dist/chunk-V7HB5LAU.js.map +1 -0
  41. package/dist/{chunk-LL6TSQWV.js → chunk-VKZOHJCE.js} +3 -3
  42. package/dist/chunk-VKZOHJCE.js.map +1 -0
  43. package/dist/{chunk-3HI6QC4V.js → chunk-WRBU6TX7.js} +2 -2
  44. package/dist/{proofs-TXJGAP5F.js → chunk-X7SUSIY3.js} +118 -20
  45. package/dist/chunk-X7SUSIY3.js.map +1 -0
  46. package/dist/{chunk-BF3IPGMP.js → chunk-XSSZMG65.js} +4 -4
  47. package/dist/{credential-TWSWV64F.js → credential-4RFRU6OH.js} +5 -5
  48. package/dist/{credential-template-XO5D5AI3.js → credential-template-36PFUTBN.js} +5 -5
  49. package/dist/{digest-SLEFOLPV.js → digest-THMKFMP7.js} +8 -8
  50. package/dist/{docs-IDC4V4WQ.js → docs-ZGM53L67.js} +5 -5
  51. package/dist/{doctor-SDAYEA6C.js → doctor-Z2XBGBM3.js} +3 -3
  52. package/dist/{environment-VBUIBQ6O.js → environment-5YVZXBN7.js} +7 -7
  53. package/dist/eval-SO5TPD37.js +1177 -0
  54. package/dist/eval-SO5TPD37.js.map +1 -0
  55. package/dist/{exploration-IREIR5PO.js → exploration-GZ4WUJJH.js} +5 -5
  56. package/dist/{exploratory-test-4Q7BMEFT.js → exploratory-test-Y7P4ZDLD.js} +5 -5
  57. package/dist/{external-run-S7LULKPT.js → external-run-IJGGZOGI.js} +7 -7
  58. package/dist/{feature-flag-IASHTUGU.js → feature-flag-UH6Z7774.js} +5 -5
  59. package/dist/{flow-IBEZFZTU.js → flow-MRWAQYZZ.js} +5 -5
  60. package/dist/{github-HAEZRULP.js → github-VDJU3PU3.js} +6 -6
  61. package/dist/index.js +101 -82
  62. package/dist/index.js.map +1 -1
  63. package/dist/{init-LT2TZMQY.js → init-CROSTPA6.js} +5 -5
  64. package/dist/{install-RTEYH6TK.js → install-ECR7OLAY.js} +5 -5
  65. package/dist/{issues-5GE277R2.js → issues-K5TL2S4Z.js} +7 -7
  66. package/dist/{knobs-AMIWGYUZ.js → knobs-OKQFBQLK.js} +5 -5
  67. package/dist/{landing-3VLVVQL5.js → landing-XANIBPVM.js} +7 -7
  68. package/dist/{list-GDJR6UY6.js → list-64GX47Q4.js} +5 -5
  69. package/dist/{local-4R6GVW7U.js → local-QMQY2ZUX.js} +7 -7
  70. package/dist/{login-IXVAWTLO.js → login-I7UQ3GTM.js} +5 -5
  71. package/dist/{mcp-BM2MJWX4.js → mcp-XZV63DX5.js} +11 -11
  72. package/dist/{mcp-BM2MJWX4.js.map → mcp-XZV63DX5.js.map} +1 -1
  73. package/dist/{metrics-SSIP5CEB.js → metrics-KBTQ3KGZ.js} +5 -5
  74. package/dist/{monitor-ESZYHXT2.js → monitor-UGWY43IU.js} +5 -5
  75. package/dist/perf-CCHWHCSR.js +961 -0
  76. package/dist/perf-CCHWHCSR.js.map +1 -0
  77. package/dist/{product-VCGUV5TH.js → product-KLG2ZTHC.js} +5 -5
  78. package/dist/{product-map-AXKZNQDM.js → product-map-AMEZ76EQ.js} +5 -5
  79. package/dist/{prompts-FVPSON2N.js → prompts-ZVQNGL7X.js} +5 -5
  80. package/dist/proofs-QCNSQAPX.js +20 -0
  81. package/dist/{property-XEPCC7KQ.js → property-PJDQFHAL.js} +6 -6
  82. package/dist/{psql-JKF3OYYJ.js → psql-AURAN27C.js} +5 -5
  83. package/dist/{record-REQ37S54.js → record-SYWBTUOB.js} +6 -6
  84. package/dist/{redis-WGHT2GJB.js → redis-2H752SKO.js} +5 -5
  85. package/dist/{release-SNDIVIA6.js → release-OSIYUXSC.js} +5 -5
  86. package/dist/{runbook-XFJG2LFC.js → runbook-7LVHF6KV.js} +5 -5
  87. package/dist/{sandbox-DYCKLCMY.js → sandbox-TJQPMRGS.js} +18 -30
  88. package/dist/sandbox-TJQPMRGS.js.map +1 -0
  89. package/dist/{scenarios-PVHCKP55.js → scenarios-P2ABU4HK.js} +5 -5
  90. package/dist/{schedule-DGC7CX23.js → schedule-XLS56NP5.js} +8 -8
  91. package/dist/{session-ERGUFDDI.js → session-ACSFC3UB.js} +8 -8
  92. package/dist/{skill-6QO2E3TB.js → skill-F7I5P6AI.js} +43 -28
  93. package/dist/{skill-6QO2E3TB.js.map → skill-F7I5P6AI.js.map} +1 -1
  94. package/dist/{slack-WE7THLLH.js → slack-ZEK4GRND.js} +6 -6
  95. package/dist/{spec-SEOY7N3L.js → spec-XPIRRSV6.js} +5 -5
  96. package/dist/{src-CCK3TKBX.js → src-N7ZCYCXU.js} +4 -4
  97. package/dist/{src-AEWV5HYH.js → src-XSBBMVGW.js} +3 -3
  98. package/dist/{start-EPGLHTND.js → start-DKWLOQI6.js} +5 -5
  99. package/dist/{status-DTE2GXM2.js → status-K7KH5DI3.js} +5 -5
  100. package/dist/{tag-GIFEWGBL.js → tag-2Y3OMQQC.js} +6 -6
  101. package/dist/{task-VLJCHSFB.js → task-4PIOC4QV.js} +6 -6
  102. package/dist/{teams-J2OOJBL4.js → teams-KUM56BE2.js} +83 -47
  103. package/dist/teams-KUM56BE2.js.map +1 -0
  104. package/dist/{test-suite-CTACGIAZ.js → test-suite-SW25YGJV.js} +138 -96
  105. package/dist/test-suite-SW25YGJV.js.map +1 -0
  106. package/dist/{trace-RWQDYL4K.js → trace-QPXHYBLA.js} +7 -7
  107. package/dist/{triage-6UAXLCGU.js → triage-EZABRZZM.js} +6 -6
  108. package/dist/trigger-7C7KX5KH.js +137 -0
  109. package/dist/trigger-7C7KX5KH.js.map +1 -0
  110. package/dist/{update-check-QRREAM3N.js → update-check-E3X7UIY6.js} +3 -3
  111. package/dist/{upgrade-5Y655TQ6.js → upgrade-EJGTMW44.js} +4 -4
  112. package/dist/{usage-KCXFY46V.js → usage-GZCQDULF.js} +7 -7
  113. package/dist/{utilities-SUON2KZK.js → utilities-RIITD53A.js} +6 -6
  114. package/dist/{visual-GJZVJC32.js → visual-FH67OKS2.js} +5 -5
  115. package/dist/{workflow-R5QAXWBX.js → workflow-34YJZ2QQ.js} +38 -86
  116. package/dist/workflow-34YJZ2QQ.js.map +1 -0
  117. package/dist/{workflow-cache-PFBTWLGM.js → workflow-cache-YQ3BGJIG.js} +17 -17
  118. package/dist/{workflow-cache-convergence-resolve-UZGRPC3B.js → workflow-cache-convergence-resolve-SPLBRSNK.js} +5 -5
  119. package/dist/{workflow-debug-RACNWWOL.js → workflow-debug-HZB7TJGK.js} +10 -10
  120. package/dist/workflow-debug-HZB7TJGK.js.map +1 -0
  121. package/dist/{workflow-feedback-RJIQ5R3R.js → workflow-feedback-6UOTIWIQ.js} +5 -5
  122. package/dist/{workflow-fork-LINDCYJ3.js → workflow-fork-IDYHAHCX.js} +5 -5
  123. package/dist/workflow-promotion-U6WYFY5U.js +62 -0
  124. package/dist/workflow-promotion-U6WYFY5U.js.map +1 -0
  125. package/dist/{workflow-proposals-E4EXKAGM.js → workflow-proposals-MMVNIQT3.js} +5 -5
  126. package/dist/{workflow-revisions-5M6APN6R.js → workflow-revisions-BPUOLCZB.js} +5 -5
  127. package/dist/{workflow-status-7KL73WS2.js → workflow-status-RA3IEMEW.js} +5 -5
  128. package/package.json +3 -2
  129. package/dist/chat-target-IZ7YLLU3.js +0 -502
  130. package/dist/chat-target-IZ7YLLU3.js.map +0 -1
  131. package/dist/chunk-76Z6E7XX.js.map +0 -1
  132. package/dist/chunk-EUVB6Y3C.js.map +0 -1
  133. package/dist/chunk-LL6TSQWV.js.map +0 -1
  134. package/dist/chunk-QTYUM4ZB.js.map +0 -1
  135. package/dist/chunk-ROX7N3RK.js.map +0 -1
  136. package/dist/chunk-UEJ2HTKU.js.map +0 -1
  137. package/dist/proofs-TXJGAP5F.js.map +0 -1
  138. package/dist/sandbox-DYCKLCMY.js.map +0 -1
  139. package/dist/teams-J2OOJBL4.js.map +0 -1
  140. package/dist/test-suite-CTACGIAZ.js.map +0 -1
  141. package/dist/workflow-R5QAXWBX.js.map +0 -1
  142. /package/dist/{account-3ZG24MOE.js.map → account-MRZ54P5P.js.map} +0 -0
  143. /package/dist/{alert-5G7PTAX2.js.map → alert-XBHELHEI.js.map} +0 -0
  144. /package/dist/{api-catalog-IBYAFKKQ.js.map → api-catalog-GWYRX53L.js.map} +0 -0
  145. /package/dist/{api-key-UXC44BDR.js.map → api-key-FH6JN447.js.map} +0 -0
  146. /package/dist/{attachment-T6IRFQW3.js.map → attachment-J7GRVT5F.js.map} +0 -0
  147. /package/dist/{auth-SHOCJE6Z.js.map → auth-VZZQXRDR.js.map} +0 -0
  148. /package/dist/{benchmark-NJ2U6VTC.js.map → benchmark-A3SNDARF.js.map} +0 -0
  149. /package/dist/{blackcat-RQJVFGXQ.js.map → blackcat-UM6TBQBN.js.map} +0 -0
  150. /package/dist/{chunk-M752EUK3.js.map → chunk-3JU4UYYN.js.map} +0 -0
  151. /package/dist/{chunk-G6BCST3G.js.map → chunk-3ZOUNCA5.js.map} +0 -0
  152. /package/dist/{chunk-ABT3BLRC.js.map → chunk-5TKXHS3X.js.map} +0 -0
  153. /package/dist/{chunk-QCYSONXI.js.map → chunk-CRYHWO4M.js.map} +0 -0
  154. /package/dist/{chunk-I5RHTCPY.js.map → chunk-EL6KJ4PO.js.map} +0 -0
  155. /package/dist/{chunk-ZL4O6C42.js.map → chunk-HXBK3AGD.js.map} +0 -0
  156. /package/dist/{chunk-PRERH4DN.js.map → chunk-I2SOHQ2C.js.map} +0 -0
  157. /package/dist/{chunk-CYSPCGO6.js.map → chunk-JEHHEMUL.js.map} +0 -0
  158. /package/dist/{chunk-LIEADTEF.js.map → chunk-LJFVRJCA.js.map} +0 -0
  159. /package/dist/{chunk-PHNH3CEU.js.map → chunk-O4Z44BR7.js.map} +0 -0
  160. /package/dist/{chunk-QA37WVF6.js.map → chunk-OQFCZERZ.js.map} +0 -0
  161. /package/dist/{chunk-Z3MDQSZG.js.map → chunk-PJFFGQSB.js.map} +0 -0
  162. /package/dist/{chunk-IY3ZK46I.js.map → chunk-QOVJUSSL.js.map} +0 -0
  163. /package/dist/{chunk-RPJMQBB5.js.map → chunk-QXU4G4YN.js.map} +0 -0
  164. /package/dist/{chunk-SZSTJIYU.js.map → chunk-RRSUKARV.js.map} +0 -0
  165. /package/dist/{chunk-775FI436.js.map → chunk-RVD6J6IZ.js.map} +0 -0
  166. /package/dist/{chunk-5UUIBY6E.js.map → chunk-TAVBFLCR.js.map} +0 -0
  167. /package/dist/{chunk-3HI6QC4V.js.map → chunk-WRBU6TX7.js.map} +0 -0
  168. /package/dist/{chunk-BF3IPGMP.js.map → chunk-XSSZMG65.js.map} +0 -0
  169. /package/dist/{credential-TWSWV64F.js.map → credential-4RFRU6OH.js.map} +0 -0
  170. /package/dist/{credential-template-XO5D5AI3.js.map → credential-template-36PFUTBN.js.map} +0 -0
  171. /package/dist/{digest-SLEFOLPV.js.map → digest-THMKFMP7.js.map} +0 -0
  172. /package/dist/{docs-IDC4V4WQ.js.map → docs-ZGM53L67.js.map} +0 -0
  173. /package/dist/{doctor-SDAYEA6C.js.map → doctor-Z2XBGBM3.js.map} +0 -0
  174. /package/dist/{environment-VBUIBQ6O.js.map → environment-5YVZXBN7.js.map} +0 -0
  175. /package/dist/{exploration-IREIR5PO.js.map → exploration-GZ4WUJJH.js.map} +0 -0
  176. /package/dist/{exploratory-test-4Q7BMEFT.js.map → exploratory-test-Y7P4ZDLD.js.map} +0 -0
  177. /package/dist/{external-run-S7LULKPT.js.map → external-run-IJGGZOGI.js.map} +0 -0
  178. /package/dist/{feature-flag-IASHTUGU.js.map → feature-flag-UH6Z7774.js.map} +0 -0
  179. /package/dist/{flow-IBEZFZTU.js.map → flow-MRWAQYZZ.js.map} +0 -0
  180. /package/dist/{github-HAEZRULP.js.map → github-VDJU3PU3.js.map} +0 -0
  181. /package/dist/{init-LT2TZMQY.js.map → init-CROSTPA6.js.map} +0 -0
  182. /package/dist/{install-RTEYH6TK.js.map → install-ECR7OLAY.js.map} +0 -0
  183. /package/dist/{issues-5GE277R2.js.map → issues-K5TL2S4Z.js.map} +0 -0
  184. /package/dist/{knobs-AMIWGYUZ.js.map → knobs-OKQFBQLK.js.map} +0 -0
  185. /package/dist/{landing-3VLVVQL5.js.map → landing-XANIBPVM.js.map} +0 -0
  186. /package/dist/{list-GDJR6UY6.js.map → list-64GX47Q4.js.map} +0 -0
  187. /package/dist/{local-4R6GVW7U.js.map → local-QMQY2ZUX.js.map} +0 -0
  188. /package/dist/{login-IXVAWTLO.js.map → login-I7UQ3GTM.js.map} +0 -0
  189. /package/dist/{metrics-SSIP5CEB.js.map → metrics-KBTQ3KGZ.js.map} +0 -0
  190. /package/dist/{monitor-ESZYHXT2.js.map → monitor-UGWY43IU.js.map} +0 -0
  191. /package/dist/{product-VCGUV5TH.js.map → product-KLG2ZTHC.js.map} +0 -0
  192. /package/dist/{product-map-AXKZNQDM.js.map → product-map-AMEZ76EQ.js.map} +0 -0
  193. /package/dist/{prompts-FVPSON2N.js.map → prompts-ZVQNGL7X.js.map} +0 -0
  194. /package/dist/{src-AEWV5HYH.js.map → proofs-QCNSQAPX.js.map} +0 -0
  195. /package/dist/{property-XEPCC7KQ.js.map → property-PJDQFHAL.js.map} +0 -0
  196. /package/dist/{psql-JKF3OYYJ.js.map → psql-AURAN27C.js.map} +0 -0
  197. /package/dist/{record-REQ37S54.js.map → record-SYWBTUOB.js.map} +0 -0
  198. /package/dist/{redis-WGHT2GJB.js.map → redis-2H752SKO.js.map} +0 -0
  199. /package/dist/{release-SNDIVIA6.js.map → release-OSIYUXSC.js.map} +0 -0
  200. /package/dist/{runbook-XFJG2LFC.js.map → runbook-7LVHF6KV.js.map} +0 -0
  201. /package/dist/{scenarios-PVHCKP55.js.map → scenarios-P2ABU4HK.js.map} +0 -0
  202. /package/dist/{schedule-DGC7CX23.js.map → schedule-XLS56NP5.js.map} +0 -0
  203. /package/dist/{session-ERGUFDDI.js.map → session-ACSFC3UB.js.map} +0 -0
  204. /package/dist/{slack-WE7THLLH.js.map → slack-ZEK4GRND.js.map} +0 -0
  205. /package/dist/{spec-SEOY7N3L.js.map → spec-XPIRRSV6.js.map} +0 -0
  206. /package/dist/{src-CCK3TKBX.js.map → src-N7ZCYCXU.js.map} +0 -0
  207. /package/dist/{tag-GIFEWGBL.js.map → src-XSBBMVGW.js.map} +0 -0
  208. /package/dist/{start-EPGLHTND.js.map → start-DKWLOQI6.js.map} +0 -0
  209. /package/dist/{status-DTE2GXM2.js.map → status-K7KH5DI3.js.map} +0 -0
  210. /package/dist/{trace-RWQDYL4K.js.map → tag-2Y3OMQQC.js.map} +0 -0
  211. /package/dist/{task-VLJCHSFB.js.map → task-4PIOC4QV.js.map} +0 -0
  212. /package/dist/{triage-6UAXLCGU.js.map → trace-QPXHYBLA.js.map} +0 -0
  213. /package/dist/{update-check-QRREAM3N.js.map → triage-EZABRZZM.js.map} +0 -0
  214. /package/dist/{upgrade-5Y655TQ6.js.map → update-check-E3X7UIY6.js.map} +0 -0
  215. /package/dist/{utilities-SUON2KZK.js.map → upgrade-EJGTMW44.js.map} +0 -0
  216. /package/dist/{usage-KCXFY46V.js.map → usage-GZCQDULF.js.map} +0 -0
  217. /package/dist/{workflow-debug-RACNWWOL.js.map → utilities-RIITD53A.js.map} +0 -0
  218. /package/dist/{visual-GJZVJC32.js.map → visual-FH67OKS2.js.map} +0 -0
  219. /package/dist/{workflow-cache-PFBTWLGM.js.map → workflow-cache-YQ3BGJIG.js.map} +0 -0
  220. /package/dist/{workflow-cache-convergence-resolve-UZGRPC3B.js.map → workflow-cache-convergence-resolve-SPLBRSNK.js.map} +0 -0
  221. /package/dist/{workflow-feedback-RJIQ5R3R.js.map → workflow-feedback-6UOTIWIQ.js.map} +0 -0
  222. /package/dist/{workflow-fork-LINDCYJ3.js.map → workflow-fork-IDYHAHCX.js.map} +0 -0
  223. /package/dist/{workflow-proposals-E4EXKAGM.js.map → workflow-proposals-MMVNIQT3.js.map} +0 -0
  224. /package/dist/{workflow-revisions-5M6APN6R.js.map → workflow-revisions-BPUOLCZB.js.map} +0 -0
  225. /package/dist/{workflow-status-7KL73WS2.js.map → workflow-status-RA3IEMEW.js.map} +0 -0
@@ -5,17 +5,17 @@ import {
5
5
  fetchList,
6
6
  parseLifecycleStage,
7
7
  toLifecycleLabel
8
- } from "./chunk-LL6TSQWV.js";
8
+ } from "./chunk-VKZOHJCE.js";
9
9
  import "./chunk-S3Q7MDCS.js";
10
- import "./chunk-76Z6E7XX.js";
10
+ import "./chunk-4UZN6TVT.js";
11
11
  import {
12
12
  getArgValue,
13
13
  hasFlag,
14
14
  resolveConfig
15
- } from "./chunk-3HI6QC4V.js";
15
+ } from "./chunk-WRBU6TX7.js";
16
16
  import {
17
17
  writeRawOutput
18
- } from "./chunk-UEJ2HTKU.js";
18
+ } from "./chunk-MJVUMVLO.js";
19
19
  import "./chunk-TOWZAG3I.js";
20
20
 
21
21
  // src/knobs.ts
@@ -295,4 +295,4 @@ async function runKnobs(argv) {
295
295
  export {
296
296
  runKnobs
297
297
  };
298
- //# sourceMappingURL=knobs-AMIWGYUZ.js.map
298
+ //# sourceMappingURL=knobs-OKQFBQLK.js.map
@@ -6,13 +6,13 @@ import {
6
6
  parseSinceFlag,
7
7
  renderStatsTable,
8
8
  runLanding
9
- } from "./chunk-M752EUK3.js";
10
- import "./chunk-ROX7N3RK.js";
11
- import "./chunk-LL6TSQWV.js";
9
+ } from "./chunk-3JU4UYYN.js";
10
+ import "./chunk-V7HB5LAU.js";
11
+ import "./chunk-VKZOHJCE.js";
12
12
  import "./chunk-S3Q7MDCS.js";
13
- import "./chunk-76Z6E7XX.js";
14
- import "./chunk-3HI6QC4V.js";
15
- import "./chunk-UEJ2HTKU.js";
13
+ import "./chunk-4UZN6TVT.js";
14
+ import "./chunk-WRBU6TX7.js";
15
+ import "./chunk-MJVUMVLO.js";
16
16
  import "./chunk-TOWZAG3I.js";
17
17
  export {
18
18
  buildLandingUrl,
@@ -22,4 +22,4 @@ export {
22
22
  renderStatsTable,
23
23
  runLanding
24
24
  };
25
- //# sourceMappingURL=landing-3VLVVQL5.js.map
25
+ //# sourceMappingURL=landing-XANIBPVM.js.map
@@ -2,13 +2,13 @@ import { createRequire as __cr } from "module"; import { fileURLToPath as __fup
2
2
  import {
3
3
  fetchList,
4
4
  fetchProperties
5
- } from "./chunk-LL6TSQWV.js";
5
+ } from "./chunk-VKZOHJCE.js";
6
6
  import "./chunk-S3Q7MDCS.js";
7
- import "./chunk-76Z6E7XX.js";
7
+ import "./chunk-4UZN6TVT.js";
8
8
  import {
9
9
  resolveConfig
10
- } from "./chunk-3HI6QC4V.js";
11
- import "./chunk-UEJ2HTKU.js";
10
+ } from "./chunk-WRBU6TX7.js";
11
+ import "./chunk-MJVUMVLO.js";
12
12
  import "./chunk-TOWZAG3I.js";
13
13
 
14
14
  // src/local/list.ts
@@ -56,4 +56,4 @@ async function runLocalList(argv) {
56
56
  export {
57
57
  runLocalList
58
58
  };
59
- //# sourceMappingURL=list-GDJR6UY6.js.map
59
+ //# sourceMappingURL=list-64GX47Q4.js.map
@@ -1,8 +1,8 @@
1
1
  import { createRequire as __cr } from "module"; import { fileURLToPath as __fup } from "url"; import { dirname as __dn } from "path"; const require = __cr(import.meta.url); const __filename = __fup(import.meta.url); const __dirname = __dn(__filename);
2
2
  import {
3
3
  hasFlag
4
- } from "./chunk-3HI6QC4V.js";
5
- import "./chunk-UEJ2HTKU.js";
4
+ } from "./chunk-WRBU6TX7.js";
5
+ import "./chunk-MJVUMVLO.js";
6
6
  import "./chunk-TOWZAG3I.js";
7
7
 
8
8
  // src/local/index.ts
@@ -70,22 +70,22 @@ async function runLocal(argv) {
70
70
  }
71
71
  switch (subcommand) {
72
72
  case "init": {
73
- const { runLocalInit } = await import("./init-LT2TZMQY.js");
73
+ const { runLocalInit } = await import("./init-CROSTPA6.js");
74
74
  await runLocalInit(rest);
75
75
  break;
76
76
  }
77
77
  case "start": {
78
- const { runLocalStart } = await import("./start-EPGLHTND.js");
78
+ const { runLocalStart } = await import("./start-DKWLOQI6.js");
79
79
  await runLocalStart(rest);
80
80
  break;
81
81
  }
82
82
  case "list": {
83
- const { runLocalList } = await import("./list-GDJR6UY6.js");
83
+ const { runLocalList } = await import("./list-64GX47Q4.js");
84
84
  await runLocalList(rest);
85
85
  break;
86
86
  }
87
87
  case "login": {
88
- const { runLocalLogin } = await import("./login-IXVAWTLO.js");
88
+ const { runLocalLogin } = await import("./login-I7UQ3GTM.js");
89
89
  await runLocalLogin(rest);
90
90
  break;
91
91
  }
@@ -98,4 +98,4 @@ async function runLocal(argv) {
98
98
  export {
99
99
  runLocal
100
100
  };
101
- //# sourceMappingURL=local-4R6GVW7U.js.map
101
+ //# sourceMappingURL=local-QMQY2ZUX.js.map
@@ -11,14 +11,14 @@ import {
11
11
  promptChoice,
12
12
  selectProperty,
13
13
  uploadStorageState
14
- } from "./chunk-LL6TSQWV.js";
14
+ } from "./chunk-VKZOHJCE.js";
15
15
  import "./chunk-S3Q7MDCS.js";
16
- import "./chunk-76Z6E7XX.js";
16
+ import "./chunk-4UZN6TVT.js";
17
17
  import {
18
18
  getArgValue,
19
19
  resolveConfig
20
- } from "./chunk-3HI6QC4V.js";
21
- import "./chunk-UEJ2HTKU.js";
20
+ } from "./chunk-WRBU6TX7.js";
21
+ import "./chunk-MJVUMVLO.js";
22
22
  import "./chunk-TOWZAG3I.js";
23
23
 
24
24
  // src/local/login.ts
@@ -313,4 +313,4 @@ Opening browser at ${args.url}...`);
313
313
  export {
314
314
  runLocalLogin
315
315
  };
316
- //# sourceMappingURL=login-IXVAWTLO.js.map
316
+ //# sourceMappingURL=login-I7UQ3GTM.js.map
@@ -3,16 +3,16 @@ import {
3
3
  COFACTOR_MCP_INSTRUCTIONS,
4
4
  buildRegistry,
5
5
  sharedGroups
6
- } from "./chunk-QTYUM4ZB.js";
6
+ } from "./chunk-EJ3ZPH5U.js";
7
7
  import "./chunk-DEK6B6LX.js";
8
8
  import {
9
9
  LocalBrowserHost,
10
10
  USER_PAUSED_ERROR
11
- } from "./chunk-RPJMQBB5.js";
12
- import "./chunk-DHAGRM2F.js";
11
+ } from "./chunk-QXU4G4YN.js";
12
+ import "./chunk-33U56YGD.js";
13
13
  import {
14
14
  getBrowserToolDefinitionsWithLifecycle
15
- } from "./chunk-IY3ZK46I.js";
15
+ } from "./chunk-QOVJUSSL.js";
16
16
  import {
17
17
  callTool,
18
18
  createSession,
@@ -24,13 +24,13 @@ import {
24
24
  fetchOrgs,
25
25
  openUrl,
26
26
  switchOrg
27
- } from "./chunk-ABT3BLRC.js";
27
+ } from "./chunk-5TKXHS3X.js";
28
28
  import {
29
29
  clearUpdateCache
30
- } from "./chunk-QCYSONXI.js";
30
+ } from "./chunk-CRYHWO4M.js";
31
31
  import "./chunk-W7CFLOEI.js";
32
32
  import "./chunk-S3Q7MDCS.js";
33
- import "./chunk-76Z6E7XX.js";
33
+ import "./chunk-4UZN6TVT.js";
34
34
  import {
35
35
  DEFAULT_API_URL,
36
36
  ENV_URLS,
@@ -38,11 +38,11 @@ import {
38
38
  readStoredToken,
39
39
  resolveAppUrl,
40
40
  saveAuth
41
- } from "./chunk-3HI6QC4V.js";
41
+ } from "./chunk-WRBU6TX7.js";
42
42
  import {
43
43
  packageName,
44
44
  readBrandEnv
45
- } from "./chunk-UEJ2HTKU.js";
45
+ } from "./chunk-MJVUMVLO.js";
46
46
  import "./chunk-AK7WEGGB.js";
47
47
  import "./chunk-NQ7LMSSS.js";
48
48
  import "./chunk-5QHORHJT.js";
@@ -729,7 +729,7 @@ Use \`cofactor_workflow_sync\` for existing workflows or construct the full work
729
729
 
730
730
  ## Managing Workflows
731
731
 
732
- - **cofactor_workflow_list** \u2014 Browse existing tests. Filter by \`status\` (draft = editable, approved = human-verified), \`flowType\` (standard/setup/seed/teardown/eval), or \`search\` by name. Suite inclusion is derived eligibility (approved AND passed at least once), with a separate pause/unpause toggle; reliability is tracked separately by the workflow's \`health\`.
732
+ - **cofactor_workflow_list** \u2014 Browse existing tests. Filter by \`status\` (draft = editable, approved = human-verified), \`flowType\` (standard/setup/seed/teardown), or \`search\` by name. Suite inclusion is derived eligibility (approved AND passed at least once), with a separate pause/unpause toggle; reliability is tracked separately by the workflow's \`health\`.
733
733
  - **cofactor_workflow_get** \u2014 Inspect a test's full definition: nodes, edges, playbook steps, assertions.
734
734
  - **cofactor_workflow_patch** \u2014 Update name, description, preflight, cleanup, status, or flow type. Only provided fields change. Description, preflight and cleanup are read by people: no raw IDs (name the seed, teardown or record), and write preflight and cleanup as short markdown bullet lists.
735
735
  - **cofactor_workflow_run** \u2014 Trigger execution. Returns a \`runId\` \u2014 use it to track progress.
@@ -905,4 +905,4 @@ async function runMcp(argv) {
905
905
  export {
906
906
  runMcp
907
907
  };
908
- //# sourceMappingURL=mcp-BM2MJWX4.js.map
908
+ //# sourceMappingURL=mcp-XZV63DX5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/mcp/index.ts","../src/mcp/api-url.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts","../src/mcp/login-tool.ts","../src/mcp/upgrade-tool.ts","../src/mcp/instructions.ts","../src/mcp/guide-tool.ts"],"sourcesContent":["/**\n * MCP Server for the Cofactor CLI.\n *\n * Combines:\n * - HTTP-only shared tools from @chatsdet/mcp-tools (workflows, runs, suites,\n * credentials, issues, proposals)\n * - CLI-local tools (login, upgrade, browser daemon, cloud-relay sessions)\n * that depend on local state and can't be hosted remotely.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { buildRegistry, sharedGroups } from '@chatsdet/mcp-tools';\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { resolveApiUrl } from './api-url';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\nimport { getLoginToolDefinitions, handleLoginTool } from './login-tool';\nimport { getUpgradeToolDefinitions, handleUpgradeTool } from './upgrade-tool';\nimport { getGuideToolDefinitions, handleGuideTool } from './guide-tool';\nimport { COFACTOR_MCP_INSTRUCTIONS } from './instructions';\n\nasync function resolveCtx() {\n const apiToken = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!apiToken) {\n throw new Error('Missing token. Call the cofactor_login tool or set CANARY_API_TOKEN.');\n }\n return { apiUrl: resolveApiUrl(), apiToken };\n}\n\nexport async function runMcp(argv: string[]) {\n if (argv.includes('--help') || argv.includes('-h')) {\n console.log(\n [\n 'Usage: canary mcp',\n '',\n 'Start the Cofactor MCP server on stdio. Agents launch it themselves; install it',\n 'into Claude, Cursor and others with `canary install`. It uses the session from',\n '`canary login`, or CANARY_API_TOKEN.',\n ].join('\\n')\n );\n return;\n }\n const registry = buildRegistry(sharedGroups);\n\n const server = new Server(\n { name: 'cofactor', version: '0.1.0' },\n {\n capabilities: { tools: {} },\n instructions: COFACTOR_MCP_INSTRUCTIONS,\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...getLoginToolDefinitions(),\n ...getUpgradeToolDefinitions(),\n ...getGuideToolDefinitions(),\n ...getSessionToolDefinitions(),\n ...getBrowserMCPToolDefinitions(),\n ...registry.list(),\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // CLI-local groups try first; each returns null if the tool is not theirs.\n const loginResult = await handleLoginTool(tool, args);\n if (loginResult) return loginResult;\n\n const upgradeResult = await handleUpgradeTool(tool, args);\n if (upgradeResult) return upgradeResult;\n\n const guideResult = await handleGuideTool(tool);\n if (guideResult) return guideResult;\n\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n // Shared HTTP-only tools — provide ctx for this call.\n try {\n const ctx = await resolveCtx();\n return await registry.call(tool, args, ctx);\n } catch (err) {\n return toolText(err instanceof Error ? err.message : String(err));\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","import { readBrandEnv } from '../brand.js';\nimport { DEFAULT_API_URL } from '../default-urls.js';\n\nexport { DEFAULT_API_URL };\n\nexport function resolveApiUrl(): string {\n return readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { DEFAULT_API_URL } from '../default-urls.js';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolJson } from './tool-helpers';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `cofactor login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description:\n \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: \"CDP endpoint URL when mode is 'cdp' (e.g. http://localhost:9222)\",\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson, toolText } from './tool-helpers';\nimport { USER_PAUSED_ERROR } from '../session/types.js';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n // The user is actively driving the browser — the daemon deferred this\n // action and will auto-resume once they go idle. Surface as informational\n // text (not an error) so Claude waits rather than retrying in a loop.\n if (result.errorCode === USER_PAUSED_ERROR) {\n return toolText(\n result.error ?? 'The user is interacting with the browser; deferring until they are idle.'\n );\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : (result.text ?? '');\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n","/**\n * MCP tool for device code OAuth login.\n *\n * Allows AI coding tools to trigger authentication without\n * requiring the user to run `cofactor login` in a separate terminal.\n *\n * @module\n */\n\nimport { ENV_URLS, envToProfile, resolveAppUrl, saveAuth } from '../auth';\nimport { openUrl, fetchOrgs, switchOrg } from '../login';\nimport type { StartResponse, PollResponse } from '../login';\nimport { resolveApiUrl } from './api-url';\nimport { toolJson } from './tool-helpers';\n\nexport function getLoginToolDefinitions() {\n return [\n {\n name: 'cofactor_login',\n description:\n 'Authenticate with Cofactor using the device code OAuth flow. Opens a browser window for the user to approve. ' +\n 'May take 30-120 seconds while waiting for the user to complete login. ' +\n 'Returns the verification URL and user code in case the browser does not open automatically.',\n inputSchema: {\n type: 'object',\n properties: {\n env: {\n type: 'string',\n enum: ['prod', 'dev', 'local'],\n description: 'Target environment (default: prod)',\n },\n org: {\n type: 'string',\n description:\n 'Organization name or ID to select if the user belongs to multiple orgs. If omitted, uses the default org.',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleLoginTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool !== 'cofactor_login') return null;\n\n try {\n const env = args.env as string | undefined;\n const orgFlag = args.org as string | undefined;\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n return toolJson({ ok: false, error: `Unknown environment: ${env}. Valid: prod, dev, local` });\n }\n\n const apiUrl = envUrls?.api ?? resolveApiUrl();\n const appUrl = envUrls?.app ?? resolveAppUrl(apiUrl);\n\n // Step 1: Start device code flow\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n return toolJson({\n ok: false,\n error: `Login start failed: ${startJson.error ?? startRes.statusText}`,\n });\n }\n\n // Step 2: Open browser (non-fatal if it fails)\n if (startJson.verificationUrl) {\n // stdout is the MCP channel, so report a failed launch on stderr.\n openUrl(startJson.verificationUrl, () =>\n process.stderr.write(`Could not open a browser. Open ${startJson.verificationUrl} manually.\\n`)\n );\n }\n\n // Step 3: Poll until approved/rejected/expired\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n return toolJson({\n ok: false,\n error: 'Login code expired. Please try again.',\n userCode: startJson.userCode,\n verificationUrl: startJson.verificationUrl,\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n return toolJson({\n ok: false,\n error: `Login poll failed: ${pollJson.error ?? pollRes.statusText}`,\n });\n }\n\n if (pollJson.status === 'approved' && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === 'rejected') {\n return toolJson({ ok: false, error: 'Login rejected by user.' });\n }\n\n if (pollJson.status === 'expired') {\n return toolJson({ ok: false, error: 'Login expired. Please try again.' });\n }\n }\n\n // Step 4: Handle org selection\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n finalOrgName = orgs[0]?.name;\n } else if (orgFlag) {\n // Match by name (case-insensitive) or ID\n const selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n // Save the default token so they're at least logged in\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: orgs.find((o) => o.id === initialOrgId)?.name }, profileName);\n\n return toolJson({\n ok: false,\n error: `Organization \"${orgFlag}\" not found.`,\n loggedIn: true,\n currentOrg: orgs.find((o) => o.id === initialOrgId)?.name,\n availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })),\n });\n }\n\n if (selectedOrg.id !== initialOrgId) {\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n return toolJson({\n ok: false,\n error: `Failed to switch organization: ${switchRes.error ?? 'Unknown error'}`,\n });\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else {\n finalOrgName = selectedOrg.name;\n }\n } else {\n // Multiple orgs, no flag — use default\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n finalOrgName = defaultOrg?.name;\n }\n\n // Step 5: Save auth\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n\n return toolJson({\n ok: true,\n message: 'Login successful. Token saved.',\n orgName: finalOrgName,\n orgId: finalOrgId,\n ...(orgs.length > 1\n ? { availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })) }\n : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP tool for upgrading the Cofactor CLI to the latest version.\n *\n * Adapts the `cofactor upgrade` command for MCP context where\n * stdio is the transport and process.exit() must be avoided.\n *\n * @module\n */\n\nimport fs from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport process from 'node:process';\nimport { packageName } from '../brand.js';\nimport { clearUpdateCache } from '../update-check.js';\nimport { toolJson } from './tool-helpers';\n\ntype PackageManager = 'bun' | 'pnpm' | 'npm';\n\nfunction detectPackageManager(): PackageManager {\n try {\n const binPath = fs.realpathSync(process.argv[1]).replace(/\\\\/g, '/');\n if (binPath.includes('.bun/') || binPath.includes('/bun/')) return 'bun';\n if (binPath.includes('.pnpm/') || binPath.includes('/pnpm/')) return 'pnpm';\n } catch {\n // realpathSync can fail if symlink is broken\n }\n return 'npm';\n}\n\nconst UPGRADE_COMMANDS: Record<PackageManager, string[]> = {\n bun: ['bun', 'add', '-g', `${packageName}@latest`],\n pnpm: ['pnpm', 'add', '-g', `${packageName}@latest`],\n npm: ['npm', 'install', '-g', `${packageName}@latest`],\n};\n\nexport function getUpgradeToolDefinitions() {\n return [\n {\n name: 'cofactor_upgrade',\n description:\n 'Upgrade the Cofactor CLI to the latest version. ' +\n 'Detects the package manager (npm, bun, pnpm) and runs the appropriate global install command.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n ];\n}\n\nexport async function handleUpgradeTool(\n tool: string,\n _args: Record<string, unknown>\n) {\n if (tool !== 'cofactor_upgrade') return null;\n\n try {\n const pm = detectPackageManager();\n const cmd = UPGRADE_COMMANDS[pm];\n\n const result = spawnSync(cmd[0], cmd.slice(1), {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: process.cwd(),\n timeout: 120_000,\n shell: process.platform === 'win32',\n windowsHide: true,\n });\n\n if (result.error) {\n return toolJson({\n ok: false,\n error: `Failed to run ${pm}: ${result.error.message}`,\n });\n }\n\n const stdout = result.stdout?.toString().trim() ?? '';\n const stderr = result.stderr?.toString().trim() ?? '';\n\n if (result.status !== 0) {\n return toolJson({\n ok: false,\n error: `Upgrade failed (exit code ${result.status}).`,\n output: stderr || stdout,\n });\n }\n\n await clearUpdateCache();\n\n return toolJson({\n ok: true,\n message: `Successfully upgraded ${packageName} to the latest version.`,\n packageManager: pm,\n output: stdout || undefined,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * Server instructions for the stdio server: the shared Cofactor text plus the\n * tools that only exist here (login, upgrade, local browser). Clients cap the\n * whole string at 4,096 chars, so the shared text is length-tested with room left\n * for this addendum (`apps/mcp/test/tools.test.ts`).\n *\n * The long workflow-authoring guide does not fit that cap, so it is served by\n * the cofactor_workflow_authoring_guide tool instead.\n *\n * @module\n */\n\nimport { COFACTOR_MCP_INSTRUCTIONS as SHARED_INSTRUCTIONS } from '@chatsdet/mcp-tools';\n\nconst LOCAL_TOOLS = `\n\nLocal tools (this stdio server only):\n- Call cofactor_login first with env \"prod\" unless the user asks for dev or local; if several organizations are available, ask which one and pass it as org.\n- To explore an app, list credentials (cofactor_credential_list), pick the default one (never one named local or manual), start a browser (browser_start or local_browser_start), then loop browser_snapshot (use its search parameter to find elements, mode \"screenshot\" to see the page), act by ref rather than coordinates, and snapshot again after every action to verify; never assume an action worked.\n- To switch organizations later, call cofactor_login again with org; no re-authentication needed.\n- Before writing or changing a test, call cofactor_workflow_authoring_guide.`;\n\nexport const COFACTOR_MCP_INSTRUCTIONS = SHARED_INSTRUCTIONS + LOCAL_TOOLS;\n\nexport const WORKFLOW_AUTHORING_GUIDE = `\n## Building Tests — Workflow Authoring\n\nAfter exploring an app via browser session, you can persist what you discovered as a reusable test workflow. The flow is: **explore → author → create**.\n\n### Step 1: Gather Credential Info\n\nCall \\`cofactor_credential_list\\` to get the credential UUID. You'll need it for the login node.\n- Always use \\`credentialId\\` (UUID) — never just the credential name\n- Set both \\`credentialId\\` and \\`credentialName\\` in the login node\n\n### Step 2: Design the Workflow\n\nA workflow is a directed graph of **nodes** connected by **edges**.\n\n#### Node Types\n\n| Type | Purpose | Required configJson |\n|------|---------|-------------------|\n| \\`login\\` | Authenticate with a credential | \\`credentialId\\`, \\`credentialName\\` |\n| \\`navigate\\` | Go to a URL | \\`pageUrl\\`, \\`pageTitle\\` |\n| \\`action\\` | Interact with elements | \\`customActionTitle\\`, \\`playbookSteps\\`, optionally \\`inlineAssertions\\` |\n| \\`assertion\\` | Standalone page verification | \\`condition\\` text |\n| \\`end\\` | Terminal node | (none) |\n\n#### Action Node Guidelines\n\n- Every action node **must** have a \\`customActionTitle\\` — a short (3-8 word) human-readable title describing the step (e.g., \"Create a new invoice\", \"Fill registration form\")\n- **Group related actions** into a single action node (one node per logical step, not per click)\n- **Prefer inline assertions** on action nodes over separate assertion nodes. Add \\`inlineAssertions\\` to verify outcomes right after the action. **Do not author an \\`id\\` field** — the server stamps a UUID on persist:\n \\`\\`\\`json\n {\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible\",\n \"severity\": \"fail\"\n }\n ]\n }\n \\`\\`\\`\n- Use separate \\`assertion\\` nodes only for standalone page-level verifications (e.g., initial page state before any action)\n\n#### Playbook Steps (inside action nodes)\n\nPlaybook steps describe what to do within an action node. Each step has:\n- \\`order\\`: sequence number (1, 2, 3...)\n- \\`action\\`: what to do — \\`click\\`, \\`fill\\`, \\`fill_form\\`, \\`select\\`, \\`navigate\\`, \\`wait\\`, \\`scroll\\`, \\`hover\\`, \\`upload\\`, \\`verify\\`, \\`press_key\\`, \\`drag\\`, \\`resize\\`, \\`capture\\`, \\`extract_table\\`, \\`python_execute\\`, \\`verify_download\\`, \\`verify_download_content\\`, \\`screenshot\\`, \\`agent_loop\\`\n- \\`target\\`: **semantic description** from the accessibility tree — button text, field labels, placeholder text. Describe as a human would: \"Submit button\", \"Email input field\", \"Status dropdown\". **Never use refs, CSS selectors, or XPaths.**\n- \\`params\\`: for \\`fill\\` actions, include \\`{ \"value\": \"...\" }\\`\n\nEach playbook step is one atomic intent executed in one browser tool call and maps to at most one recorded call. Draw boundaries at stable page states: fuse actions coupled through ephemeral UI state into that call; split unrelated intents and every stable intermediate into separate steps. Do not use \\`other\\`; if no concrete browser-tool-backed action fits, omit that diagnostic observation from \\`playbookSteps\\`. Use \\`click\\` for switches, checkboxes, and click-to-focus behavior. Use \\`press_key\\` with \\`{ \"key\": \"Escape\" }\\` or an explicit \\`click\\` to close popovers and panels; there is no \\`dismiss\\`, \\`toggle\\`, \\`focus\\`, or \\`handle_native_dialog\\` action.\n\n### Macros — Always Prefer Over Hardcoded Data\n\nMacros generate fresh values each run, preventing flaky tests from stale or colliding data. **Never hardcode emails, names, phone numbers, or dates when a macro exists.**\n\n| Macro | Output | Example |\n|-------|--------|---------|\n| \\`$EMAIL()\\` | Unique test email | \\`test-xk9mq2@example-test.com\\` |\n| \\`$FIRST_NAME()\\` | Random first name | \\`Jordan\\` |\n| \\`$LAST_NAME()\\` | Random last name | \\`Chen\\` |\n| \\`$PHONE()\\` | US phone (555 prefix) | \\`+1-555-382-7491\\` |\n| \\`$UUID()\\` | Random UUID v4 | \\`a1b2c3d4-...\\` |\n| \\`$RANDOM_INT(min, max)\\` | Random integer | \\`$RANDOM_INT(100,999)\\` → \\`427\\` |\n| \\`$RANDOM_STRING(length)\\` | Alphanumeric string | \\`$RANDOM_STRING(8)\\` → \\`xK9mQ3bR\\` |\n| \\`$TODAY()\\` | Current date (YYYY-MM-DD) | \\`2026-04-06\\` |\n| \\`$DATE(days)\\` | Date offset from today | \\`$DATE(-7)\\` → last week |\n| \\`$NOW()\\` | ISO 8601 timestamp | \\`2026-04-06T14:30:00.000Z\\` |\n| \\`$NOW(+5m, 'fmt')\\` | Shifted time (+5m/-2h/30s/1d), optional UTC format (YYYY MM DD HH mm ss, unpadded H m) | \\`$NOW(+5m, 'm H * * *')\\` → \\`35 14 * * *\\` |\n| \\`$TIMESTAMP()\\` | Unix milliseconds | \\`1771520400000\\` |\n| \\`$SEQUENCE(\"name\")\\` | Auto-incrementing per run | \\`1\\`, \\`2\\`, \\`3\\`... |\n\nMacros combine inline: \\`\"QA Test $FIRST_NAME() $LAST_NAME()\"\\`, \\`\"order-$RANDOM_STRING(6)\"\\`\n\n**Prefix test data with \"QA Test\"** for identifiability.\n\n### Step 3: Create the Workflow\n\nUse \\`cofactor_workflow_sync\\` for existing workflows or construct the full workflow JSON and create via the API. Then verify with \\`cofactor_workflow_get\\`.\n\n### Example Workflow JSON\n\n\\`\\`\\`json\n{\n \"name\": \"Verify user can create an invoice\",\n \"description\": \"Tests the invoice creation flow end-to-end\",\n \"nodes\": [\n {\n \"nodeType\": \"login\",\n \"configJson\": {\n \"credentialId\": \"4f6db838-16be-49e8-8887-8d0be1c83a87\",\n \"credentialName\": \"QA User\"\n }\n },\n {\n \"nodeType\": \"navigate\",\n \"configJson\": { \"pageUrl\": \"/invoices\", \"pageTitle\": \"Invoices\" }\n },\n {\n \"nodeType\": \"action\",\n \"configJson\": {\n \"customActionTitle\": \"Create a new invoice\",\n \"actionDescription\": \"Fill out the new invoice form and save\",\n \"playbookSteps\": [\n { \"order\": 1, \"action\": \"click\", \"target\": \"New Invoice button\" },\n { \"order\": 2, \"action\": \"fill\", \"target\": \"Client name field\", \"params\": { \"value\": \"QA Test $FIRST_NAME()\" } },\n { \"order\": 3, \"action\": \"fill\", \"target\": \"Amount field\", \"params\": { \"value\": \"$RANDOM_INT(100,999)\" } },\n { \"order\": 4, \"action\": \"click\", \"target\": \"Save button\" }\n ],\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible and the new invoice appears in the list\",\n \"severity\": \"fail\"\n }\n ]\n }\n }\n ]\n}\n\\`\\`\\`\n\n## Managing Workflows\n\n- **cofactor_workflow_list** — Browse existing tests. Filter by \\`status\\` (draft = editable, approved = human-verified), \\`flowType\\` (standard/setup/seed/teardown/eval), or \\`search\\` by name. Suite inclusion is derived eligibility (approved AND passed at least once), with a separate pause/unpause toggle; reliability is tracked separately by the workflow's \\`health\\`.\n- **cofactor_workflow_get** — Inspect a test's full definition: nodes, edges, playbook steps, assertions.\n- **cofactor_workflow_patch** — Update name, description, preflight, cleanup, status, or flow type. Only provided fields change. Description, preflight and cleanup are read by people: no raw IDs (name the seed, teardown or record), and write preflight and cleanup as short markdown bullet lists.\n- **cofactor_workflow_run** — Trigger execution. Returns a \\`runId\\` — use it to track progress.\n- **cofactor_workflow_sync** — Atomically replace all nodes and edges. Automatically snapshots current state first so changes are reversible. Read the current DAG with \\`cofactor_workflow_get\\` before syncing.\n\n## Monitoring Runs & Debugging Failures\n\nAfter triggering a workflow run, monitor and debug with:\n\n- **cofactor_workflow_runs_list** — Recent runs for a workflow with status and duration.\n- **cofactor_workflow_runs_get** — Detailed run view: step-by-step status, duration, errors. Also works for in-progress runs to check status.\n- **cofactor_workflow_runs_diagnostics** — AI-generated failure analysis. Returns root cause and recommendations. Falls back to raw console logs and network requests if no AI analysis is available.\n\n### Regression Suite\n\n- **cofactor_test_suite_run** — Trigger a regression suite execution. Returns suiteId for tracking. Use cofactor_test_suite_list or cofactor_test_suite_get to check results.\n- **cofactor_test_suite_list** — Recent regression suite executions with pass/fail counts.\n- **cofactor_test_suite_get** — Individual test results within a suite execution.\n- **cofactor_test_suite_diagnostics** — Failure diagnostics for a specific test in a suite run.\n- **cofactor_test_suite_steps** — Step-by-step breakdown of a test run within a suite.\n\n## Investigating Issues\n\nIssues are bugs discovered by Cofactor during test runs.\n\n- **cofactor_issues_list** — Search and filter issues by severity (\\`low\\`/\\`medium\\`/\\`high\\`), status (\\`open\\`/\\`closed\\`/\\`not_a_bug\\`), or property. Supports full-text search.\n- **cofactor_issues_get** — Full issue detail including console errors and network failures from the latest occurrence, plus every evidence item on recent occurrences with signed screenshot/clip links (the first screenshots come back inline as images), and the issue's comments. Use this to understand what went wrong.\n- **cofactor_issues_comment** — Add a comment to an issue (\\`get\\` returns the comments).\n- **cofactor_issues_update** — Edit an occurrence's summary, repro steps, or evidence items (add, replace, or remove by the numbers cofactor_issues_get shows; screenshots as base64 image data).\n\n## Product Map (what the app does, and what covers it)\n\nAreas → capabilities, with flows linked to capabilities so coverage is showable. Available to every organization.\n\nCapabilities have **natural codes** — \\`CAP-CMM-001\\`, areas \\`ARE-CMM\\` — which are stable and safe to carry between a ticket, a spec, and a tool call. Prefer them over prefixed ids when writing anything a human will read.\n\n- **cofactor_product_map_get** — The whole map for an application. Call this before proposing a new capability so you reuse an existing one by code instead of creating a near-duplicate.\n- **cofactor_product_map_coverage** — Linked/covered rollup. Always report the unmapped-flow count beside any coverage figure; coverage is always coverage of the *known* map.\n- **cofactor_product_map_resolve_code** — Resolve a code, including one retired by a move. Use this before reporting that a code \"does not exist\" — it may just have been renumbered.\n- **cofactor_product_map_get_capability** — One capability in full: body, linked flows by name, previous codes.\n- **cofactor_product_map_link_flows** / **cofactor_product_map_unlink_flows** — Record that a flow covers a capability. Additive/subtractive; other links are preserved.\n\n## API Sequences (API-only workflows)\n\nFor APIs that need deterministic, browser-free smoke testing — composed of ordered HTTP calls that chain outputs into inputs.\n\n- **Create** with the same command as any workflow, with \\`--api-only\\`:\n \\`cofactor workflow create --api-only --name \"<n>\" --sequence-from-file seq.json\\`\n Returns \\`{ workflowId, apiSequenceId, nodeId }\\`. No \\`--property\\` — api-sequences are org-scoped.\n- **Inspect runs** with the same command as any runs, with \\`--side api\\` (or \\`--side all\\` for both):\n \\`cofactor workflow runs list <wf> --side api\\`\n \\`cofactor workflow runs get <wf> <runId>\\`\n- **Edit the sequence itself** via \\`cofactor workflow api-sequence <verb>\\`:\n - \\`get <wf>\\` — dump config + steps\n - \\`update <wf> --from-file seq.json\\` — replace config\n - \\`execute <wf>\\` — run it\n - \\`generate <wf> [--prompt \"...\"]\\` — AI-draft a config, then refine with \\`update\\`\n- **Discover endpoints** before composing steps:\n \\`cofactor api-catalog sources list\\`\n \\`cofactor api-catalog endpoints list --search <q>\\`\n \\`cofactor api-catalog endpoints create --from-file ep.json\\` (add a one-off)\n- **Read the reference first** for the config/step shape and template syntax:\n \\`cofactor workflow guide api-sequences\\`\n\nTemplates in step fields use \\`{{stepId.response.path}}\\` to reference prior-step outputs and \\`$MACRO()\\` for dynamic test data (same macros as browser workflows).\n\n## Common Workflows\n\n### \"Let's explore the app\"\n1. \\`cofactor_login\\` (env: prod) → switch to the right org\n2. \\`cofactor_credential_list\\` → find the right credential\n3. \\`browser_start\\` → launch browser\n4. Load credential and navigate to the app\n5. Snapshot, interact, explore\n\n### \"Write a test for this feature\"\n1. Explore the feature via browser (above workflow)\n2. \\`cofactor_credential_list\\` → get credentialId\n3. Construct workflow JSON with nodes, edges, playbook steps, macros\n4. Create or sync the workflow\n5. \\`cofactor_workflow_run\\` → execute it\n6. \\`cofactor_workflow_runs_get\\` → verify it passes\n\n### \"Why did this test fail?\"\n1. \\`cofactor_workflow_runs_list\\` → find the failed run\n2. \\`cofactor_workflow_runs_get\\` → see which step failed\n3. \\`cofactor_workflow_runs_diagnostics\\` → AI analysis of the failure\n4. If needed, open a browser session to reproduce and investigate\n\n### \"What issues have been found?\"\n1. \\`cofactor_issues_list\\` → browse open issues\n2. \\`cofactor_issues_get\\` → deep dive with console/network errors\n`.trim();\n","/**\n * MCP tool that returns the workflow-authoring guide. It lives in a tool rather\n * than the server instructions because clients cap instructions at 4,096 chars.\n *\n * @module\n */\n\nimport { WORKFLOW_AUTHORING_GUIDE } from './instructions';\nimport { toolText } from './tool-helpers';\n\nconst GUIDE_TOOL = 'cofactor_workflow_authoring_guide';\n\nexport function getGuideToolDefinitions() {\n return [\n {\n name: GUIDE_TOOL,\n description:\n 'How to author a Cofactor test (workflow): node types, playbook steps, macros, example workflow JSON, running and debugging. Read it before creating or syncing a workflow.',\n inputSchema: { type: 'object', properties: {} },\n },\n ];\n}\n\nexport async function handleGuideTool(tool: string) {\n return tool === GUIDE_TOOL ? toolText(WORKFLOW_AUTHORING_GUIDE) : null;\n}\n"],"mappings":"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","names":["resolveApiUrl","profileName","process","process","COFACTOR_MCP_INSTRUCTIONS","COFACTOR_MCP_INSTRUCTIONS"]}
1
+ {"version":3,"sources":["../src/mcp/index.ts","../src/mcp/api-url.ts","../src/mcp/tool-helpers.ts","../src/mcp/session-tools.ts","../src/mcp/browser-tools.ts","../src/mcp/login-tool.ts","../src/mcp/upgrade-tool.ts","../src/mcp/instructions.ts","../src/mcp/guide-tool.ts"],"sourcesContent":["/**\n * MCP Server for the Cofactor CLI.\n *\n * Combines:\n * - HTTP-only shared tools from @chatsdet/mcp-tools (workflows, runs, suites,\n * credentials, issues, proposals)\n * - CLI-local tools (login, upgrade, browser daemon, cloud-relay sessions)\n * that depend on local state and can't be hosted remotely.\n *\n * @module\n */\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { buildRegistry, sharedGroups } from '@chatsdet/mcp-tools';\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { resolveApiUrl } from './api-url';\nimport { toolText } from './tool-helpers';\nimport { getSessionToolDefinitions, handleSessionTool } from './session-tools';\nimport { getBrowserMCPToolDefinitions, handleBrowserTool } from './browser-tools';\nimport { getLoginToolDefinitions, handleLoginTool } from './login-tool';\nimport { getUpgradeToolDefinitions, handleUpgradeTool } from './upgrade-tool';\nimport { getGuideToolDefinitions, handleGuideTool } from './guide-tool';\nimport { COFACTOR_MCP_INSTRUCTIONS } from './instructions';\n\nasync function resolveCtx() {\n const apiToken = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!apiToken) {\n throw new Error('Missing token. Call the cofactor_login tool or set CANARY_API_TOKEN.');\n }\n return { apiUrl: resolveApiUrl(), apiToken };\n}\n\nexport async function runMcp(argv: string[]) {\n if (argv.includes('--help') || argv.includes('-h')) {\n console.log(\n [\n 'Usage: canary mcp',\n '',\n 'Start the Cofactor MCP server on stdio. Agents launch it themselves; install it',\n 'into Claude, Cursor and others with `canary install`. It uses the session from',\n '`canary login`, or CANARY_API_TOKEN.',\n ].join('\\n')\n );\n return;\n }\n const registry = buildRegistry(sharedGroups);\n\n const server = new Server(\n { name: 'cofactor', version: '0.1.0' },\n {\n capabilities: { tools: {} },\n instructions: COFACTOR_MCP_INSTRUCTIONS,\n }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n ...getLoginToolDefinitions(),\n ...getUpgradeToolDefinitions(),\n ...getGuideToolDefinitions(),\n ...getSessionToolDefinitions(),\n ...getBrowserMCPToolDefinitions(),\n ...registry.list(),\n ],\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (req) => {\n const tool = req.params.name;\n const args = (req.params.arguments ?? {}) as Record<string, unknown>;\n\n // CLI-local groups try first; each returns null if the tool is not theirs.\n const loginResult = await handleLoginTool(tool, args);\n if (loginResult) return loginResult;\n\n const upgradeResult = await handleUpgradeTool(tool, args);\n if (upgradeResult) return upgradeResult;\n\n const guideResult = await handleGuideTool(tool);\n if (guideResult) return guideResult;\n\n const browserResult = await handleBrowserTool(tool, args);\n if (browserResult) return browserResult;\n\n const sessionResult = await handleSessionTool(tool, args);\n if (sessionResult) return sessionResult;\n\n // Shared HTTP-only tools — provide ctx for this call.\n try {\n const ctx = await resolveCtx();\n return await registry.call(tool, args, ctx);\n } catch (err) {\n return toolText(err instanceof Error ? err.message : String(err));\n }\n });\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n return new Promise<void>(() => undefined);\n}\n","import { readBrandEnv } from '../brand.js';\nimport { DEFAULT_API_URL } from '../default-urls.js';\n\nexport { DEFAULT_API_URL };\n\nexport function resolveApiUrl(): string {\n return readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n","/**\n * MCP tool response helpers.\n *\n * @module\n */\n\nimport type { ToolResult } from '@chatsdet/browser-core';\n\nexport function toolText(text: string) {\n return { content: [{ type: 'text' as const, text }] };\n}\n\nexport function toolJson(data: unknown) {\n return { content: [{ type: 'text' as const, text: JSON.stringify(data, null, 2) }] };\n}\n\n/**\n * Convert a BrowserToolExecutor result to MCP SDK content blocks.\n */\nexport function formatMCPContent(result: ToolResult) {\n if (typeof result === 'string') {\n return { content: [{ type: 'text' as const, text: result }] };\n }\n\n // MCPContentResult with text and optional images\n const content: Array<{ type: 'text'; text: string } | { type: 'image'; data: string; mimeType: string }> = [];\n\n if (result.text) {\n content.push({ type: 'text', text: result.text });\n }\n\n for (const img of result.images ?? []) {\n content.push({ type: 'image', data: img.data, mimeType: img.mimeType });\n }\n\n return { content };\n}\n","/**\n * Cloud-relay session tools for the MCP server.\n *\n * These tools proxy browser control through the cloud API via WebSocket.\n *\n * @module\n */\n\nimport { readStoredToken } from '../auth';\nimport { readBrandEnv } from '../brand.js';\nimport { DEFAULT_API_URL } from '../default-urls.js';\nimport { LocalBrowserHost } from '../local-browser/host';\nimport type { LocalBrowserMode } from '../local-browser/protocol';\nimport { toolJson } from './tool-helpers';\n\ntype LocalBrowserStartInput = {\n mode?: LocalBrowserMode;\n cdpUrl?: string;\n headless?: boolean;\n storageStatePath?: string;\n instructions?: string;\n};\n\ntype LocalBrowserStopInput = {\n sessionId: string;\n};\n\ntype LocalBrowserStatusInput = {\n sessionId: string;\n};\n\ninterface BrowserSession {\n sessionId: string;\n host: LocalBrowserHost;\n startedAt: number;\n mode: LocalBrowserMode;\n}\n\n// Global browser sessions managed by MCP\nconst browserSessions = new Map<string, BrowserSession>();\n\nfunction resolveApiUrl(input?: string): string {\n return input ?? readBrandEnv('CANARY_API_URL') ?? DEFAULT_API_URL;\n}\n\nasync function resolveToken(): Promise<string> {\n const token = readBrandEnv('CANARY_API_TOKEN') ?? (await readStoredToken());\n if (!token) {\n throw new Error('Missing token. Run `cofactor login` first or set CANARY_API_TOKEN.');\n }\n return token;\n}\n\nexport function getSessionToolDefinitions() {\n return [\n {\n name: 'local_browser_start',\n description:\n 'Start a local browser session that connects to the cloud agent. The cloud agent can then control this browser to test local applications. Returns sessionId for tracking.',\n inputSchema: {\n type: 'object',\n properties: {\n mode: {\n type: 'string',\n enum: ['playwright', 'cdp'],\n description:\n \"Browser mode: 'playwright' for fresh browser, 'cdp' to connect to existing Chrome\",\n },\n cdpUrl: {\n type: 'string',\n description: \"CDP endpoint URL when mode is 'cdp' (e.g. http://localhost:9222)\",\n },\n headless: {\n type: 'boolean',\n description: 'Run browser headless (default: true for playwright mode)',\n },\n storageStatePath: {\n type: 'string',\n description: 'Path to Playwright storage state JSON for pre-authenticated sessions',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n },\n },\n },\n {\n name: 'local_browser_status',\n description: 'Check the status of a local browser session.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_stop',\n description: 'Stop a local browser session and close the browser.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: { type: 'string' },\n },\n required: ['sessionId'],\n },\n },\n {\n name: 'local_browser_list',\n description: 'List all active local browser sessions.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n {\n name: 'local_browser_run',\n description:\n 'Start a test run on an active local browser session. The cloud agent will control the local browser according to the instructions.',\n inputSchema: {\n type: 'object',\n properties: {\n sessionId: {\n type: 'string',\n description: 'The session ID from local_browser_start',\n },\n instructions: {\n type: 'string',\n description: 'Instructions for the cloud agent on what to test',\n },\n startUrl: {\n type: 'string',\n description: 'Optional URL to navigate to before starting',\n },\n },\n required: ['sessionId', 'instructions'],\n },\n },\n ];\n}\n\nexport async function handleSessionTool(tool: string, args: Record<string, unknown>) {\n const token = await resolveToken();\n\n if (tool === 'local_browser_start') {\n const input = args as unknown as LocalBrowserStartInput;\n const apiUrl = resolveApiUrl();\n const mode = input.mode ?? 'playwright';\n\n const sessionResponse = await fetch(`${apiUrl}/local-browser/sessions`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n browserMode: mode,\n instructions: input.instructions ?? null,\n }),\n });\n\n if (!sessionResponse.ok) {\n const text = await sessionResponse.text();\n return toolJson({ ok: false, error: `Failed to create session: ${text}` });\n }\n\n const session = (await sessionResponse.json()) as {\n ok: boolean;\n sessionId: string;\n wsToken: string;\n expiresAt: string;\n };\n\n const host = new LocalBrowserHost({\n apiUrl,\n wsToken: session.wsToken,\n sessionId: session.sessionId,\n browserMode: mode,\n cdpUrl: input.cdpUrl,\n headless: input.headless ?? true,\n storageStatePath: input.storageStatePath,\n onLog: (level, message) => {\n if (level === 'error') {\n console.error(`[LocalBrowser] ${message}`);\n }\n },\n });\n\n host.start().catch((err) => {\n console.error('Failed to start local browser:', err);\n browserSessions.delete(session.sessionId);\n });\n\n browserSessions.set(session.sessionId, {\n sessionId: session.sessionId,\n host,\n startedAt: Date.now(),\n mode,\n });\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode,\n expiresAt: session.expiresAt,\n note: 'Browser session started. The cloud agent can now control this browser. Use local_browser_stop to end the session.',\n });\n }\n\n if (tool === 'local_browser_status') {\n const input = args as unknown as LocalBrowserStatusInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n return toolJson({\n ok: true,\n sessionId: session.sessionId,\n mode: session.mode,\n startedAt: new Date(session.startedAt).toISOString(),\n uptimeMs: Date.now() - session.startedAt,\n });\n }\n\n if (tool === 'local_browser_stop') {\n const input = args as unknown as LocalBrowserStopInput;\n const session = browserSessions.get(input.sessionId);\n\n if (!session) {\n return toolJson({ ok: false, error: 'Session not found', sessionId: input.sessionId });\n }\n\n await session.host.stop();\n browserSessions.delete(input.sessionId);\n\n return toolJson({\n ok: true,\n sessionId: input.sessionId,\n note: 'Browser session stopped and browser closed.',\n });\n }\n\n if (tool === 'local_browser_list') {\n const sessions = Array.from(browserSessions.values()).map((s) => ({\n sessionId: s.sessionId,\n mode: s.mode,\n startedAt: new Date(s.startedAt).toISOString(),\n uptimeMs: Date.now() - s.startedAt,\n }));\n\n return toolJson({\n ok: true,\n count: sessions.length,\n sessions,\n });\n }\n\n if (tool === 'local_browser_run') {\n const input = args as unknown as {\n sessionId: string;\n instructions: string;\n startUrl?: string;\n };\n const apiUrl = resolveApiUrl();\n\n const session = browserSessions.get(input.sessionId);\n if (!session) {\n return toolJson({\n ok: false,\n error: 'Session not found locally. Make sure you started it with local_browser_start.',\n sessionId: input.sessionId,\n });\n }\n\n const response = await fetch(`${apiUrl}/local-browser/sessions/${input.sessionId}/run`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({\n instructions: input.instructions,\n startUrl: input.startUrl ?? null,\n }),\n });\n\n if (!response.ok) {\n const text = await response.text();\n return toolJson({ ok: false, error: `Failed to start run: ${text}` });\n }\n\n const result = (await response.json()) as { ok: boolean; jobId: string; sessionId: string };\n\n return toolJson({\n ok: true,\n jobId: result.jobId,\n sessionId: result.sessionId,\n note: 'Test run started. The cloud agent is now controlling your local browser. You can watch the browser to see the test in action.',\n });\n }\n\n return null; // Not handled\n}\n","/**\n * Browser MCP tool registration — daemon adapter.\n *\n * Thin layer that maps MCP tool calls to the session daemon,\n * ensuring the CLI gets the SAME semantic diff, snapshot formatting,\n * click validation, and recovery notices as the cloud agent.\n *\n * The daemon owns all browser sessions. MCP is just a protocol adapter.\n *\n * @module\n */\n\nimport { getBrowserToolDefinitionsWithLifecycle } from '@chatsdet/browser-core';\nimport {\n createSession,\n deleteSession,\n deleteAllSessions,\n callTool,\n resolveTargetSession,\n} from '../session/daemon-client.js';\nimport { formatMCPContent, toolJson, toolText } from './tool-helpers';\nimport { USER_PAUSED_ERROR } from '../session/types.js';\nimport type { ToolResult } from '@chatsdet/browser-core';\n\n/** Track the active session ID within this MCP server instance */\nlet activeSessionId: string | null = null;\n\n/**\n * Get tool definitions for browser MCP tools (including lifecycle).\n */\nexport function getBrowserMCPToolDefinitions() {\n return getBrowserToolDefinitionsWithLifecycle();\n}\n\n/**\n * Handle a browser tool call.\n * Returns null if the tool name is not a browser tool.\n */\nexport async function handleBrowserTool(name: string, args: Record<string, unknown>) {\n // Lifecycle tools\n if (name === 'browser_start') {\n try {\n const result = await createSession({\n headless: (args.headless as boolean) ?? false,\n storageStatePath: args.storageStatePath as string | undefined,\n });\n\n if (!result.ok) {\n return toolJson({ ok: false, error: result.error });\n }\n\n activeSessionId = result.data!.id;\n return toolJson({\n ok: true,\n sessionId: activeSessionId,\n note: 'Browser started. You can now use browser_navigate, browser_click, and other browser tools.',\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n if (name === 'browser_stop') {\n try {\n if (activeSessionId) {\n await deleteSession(activeSessionId);\n activeSessionId = null;\n } else {\n // Stop all sessions if no specific one tracked\n await deleteAllSessions();\n }\n return toolJson({ ok: true, note: 'Browser stopped and cleaned up.' });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n }\n\n // All other browser_* tools require an active session\n if (!name.startsWith('browser_')) return null;\n\n try {\n // Resolve target session: prefer tracked MCP session, then auto-resolve\n let sessionId = activeSessionId;\n if (!sessionId) {\n try {\n const target = await resolveTargetSession();\n sessionId = target.id;\n activeSessionId = sessionId;\n } catch {\n return toolJson({\n ok: false,\n error: 'No active browser session. Start one with browser_start first.',\n });\n }\n }\n\n // Strip 'browser_' prefix for the daemon tool name\n const toolName = name.replace(/^browser_/, '');\n const result = await callTool(sessionId, toolName, args);\n\n if (!result.ok) {\n // If session not found, clear tracking and report error\n if (result.error?.includes('not found')) {\n activeSessionId = null;\n }\n // The user is actively driving the browser — the daemon deferred this\n // action and will auto-resume once they go idle. Surface as informational\n // text (not an error) so Claude waits rather than retrying in a loop.\n if (result.errorCode === USER_PAUSED_ERROR) {\n return toolText(\n result.error ?? 'The user is interacting with the browser; deferring until they are idle.'\n );\n }\n return toolJson({ ok: false, error: result.error, tool: name });\n }\n\n // Convert daemon response back to ToolResult format for MCP formatting\n const toolResult: ToolResult = result.images?.length\n ? { text: result.text ?? '', images: result.images }\n : (result.text ?? '');\n\n return formatMCPContent(toolResult);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n return toolJson({ ok: false, error: message, tool: name });\n }\n}\n","/**\n * MCP tool for device code OAuth login.\n *\n * Allows AI coding tools to trigger authentication without\n * requiring the user to run `cofactor login` in a separate terminal.\n *\n * @module\n */\n\nimport { ENV_URLS, envToProfile, resolveAppUrl, saveAuth } from '../auth';\nimport { openUrl, fetchOrgs, switchOrg } from '../login';\nimport type { StartResponse, PollResponse } from '../login';\nimport { resolveApiUrl } from './api-url';\nimport { toolJson } from './tool-helpers';\n\nexport function getLoginToolDefinitions() {\n return [\n {\n name: 'cofactor_login',\n description:\n 'Authenticate with Cofactor using the device code OAuth flow. Opens a browser window for the user to approve. ' +\n 'May take 30-120 seconds while waiting for the user to complete login. ' +\n 'Returns the verification URL and user code in case the browser does not open automatically.',\n inputSchema: {\n type: 'object',\n properties: {\n env: {\n type: 'string',\n enum: ['prod', 'dev', 'local'],\n description: 'Target environment (default: prod)',\n },\n org: {\n type: 'string',\n description:\n 'Organization name or ID to select if the user belongs to multiple orgs. If omitted, uses the default org.',\n },\n },\n },\n },\n ];\n}\n\nexport async function handleLoginTool(\n tool: string,\n args: Record<string, unknown>\n) {\n if (tool !== 'cofactor_login') return null;\n\n try {\n const env = args.env as string | undefined;\n const orgFlag = args.org as string | undefined;\n const envUrls = env ? ENV_URLS[env] : undefined;\n\n if (env && !envUrls) {\n return toolJson({ ok: false, error: `Unknown environment: ${env}. Valid: prod, dev, local` });\n }\n\n const apiUrl = envUrls?.api ?? resolveApiUrl();\n const appUrl = envUrls?.app ?? resolveAppUrl(apiUrl);\n\n // Step 1: Start device code flow\n const startRes = await fetch(`${apiUrl}/cli-login/start`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ appUrl }),\n });\n\n const startJson = (await startRes.json()) as StartResponse;\n if (!startRes.ok || !startJson.ok || !startJson.deviceCode || !startJson.userCode) {\n return toolJson({\n ok: false,\n error: `Login start failed: ${startJson.error ?? startRes.statusText}`,\n });\n }\n\n // Step 2: Open browser (non-fatal if it fails)\n if (startJson.verificationUrl) {\n // stdout is the MCP channel, so report a failed launch on stderr.\n openUrl(startJson.verificationUrl, () =>\n process.stderr.write(`Could not open a browser. Open ${startJson.verificationUrl} manually.\\n`)\n );\n }\n\n // Step 3: Poll until approved/rejected/expired\n const intervalMs = (startJson.intervalSeconds ?? 3) * 1000;\n const expiresAt = startJson.expiresAt ? new Date(startJson.expiresAt).getTime() : null;\n\n let token: string | undefined;\n let initialOrgId: string | undefined;\n\n while (true) {\n if (expiresAt && Date.now() > expiresAt) {\n return toolJson({\n ok: false,\n error: 'Login code expired. Please try again.',\n userCode: startJson.userCode,\n verificationUrl: startJson.verificationUrl,\n });\n }\n\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n\n const pollRes = await fetch(`${apiUrl}/cli-login/poll`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ deviceCode: startJson.deviceCode }),\n });\n\n const pollJson = (await pollRes.json()) as PollResponse;\n if (!pollRes.ok || !pollJson.ok) {\n return toolJson({\n ok: false,\n error: `Login poll failed: ${pollJson.error ?? pollRes.statusText}`,\n });\n }\n\n if (pollJson.status === 'approved' && pollJson.accessToken) {\n token = pollJson.accessToken;\n initialOrgId = pollJson.orgId;\n break;\n }\n\n if (pollJson.status === 'rejected') {\n return toolJson({ ok: false, error: 'Login rejected by user.' });\n }\n\n if (pollJson.status === 'expired') {\n return toolJson({ ok: false, error: 'Login expired. Please try again.' });\n }\n }\n\n // Step 4: Handle org selection\n const orgsData = await fetchOrgs(apiUrl, token);\n const orgs = orgsData?.organizations ?? [];\n\n let finalToken = token;\n let finalOrgId = initialOrgId;\n let finalOrgName: string | undefined;\n\n if (orgs.length <= 1) {\n finalOrgName = orgs[0]?.name;\n } else if (orgFlag) {\n // Match by name (case-insensitive) or ID\n const selectedOrg = orgs.find(\n (o) => o.name.toLowerCase() === orgFlag.toLowerCase() || o.id === orgFlag\n );\n if (!selectedOrg) {\n // Save the default token so they're at least logged in\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: orgs.find((o) => o.id === initialOrgId)?.name }, profileName);\n\n return toolJson({\n ok: false,\n error: `Organization \"${orgFlag}\" not found.`,\n loggedIn: true,\n currentOrg: orgs.find((o) => o.id === initialOrgId)?.name,\n availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })),\n });\n }\n\n if (selectedOrg.id !== initialOrgId) {\n const switchRes = await switchOrg(apiUrl, token, selectedOrg.id);\n if (!switchRes.ok || !switchRes.accessToken) {\n return toolJson({\n ok: false,\n error: `Failed to switch organization: ${switchRes.error ?? 'Unknown error'}`,\n });\n }\n finalToken = switchRes.accessToken;\n finalOrgId = switchRes.orgId;\n finalOrgName = switchRes.orgName;\n } else {\n finalOrgName = selectedOrg.name;\n }\n } else {\n // Multiple orgs, no flag — use default\n const defaultOrg = orgs.find((o) => o.id === initialOrgId);\n finalOrgName = defaultOrg?.name;\n }\n\n // Step 5: Save auth\n const profileName = env ? envToProfile(env) : undefined;\n await saveAuth({ token: finalToken, apiUrl, orgId: finalOrgId, orgName: finalOrgName }, profileName);\n\n return toolJson({\n ok: true,\n message: 'Login successful. Token saved.',\n orgName: finalOrgName,\n orgId: finalOrgId,\n ...(orgs.length > 1\n ? { availableOrgs: orgs.map((o) => ({ id: o.id, name: o.name, role: o.role })) }\n : {}),\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * MCP tool for upgrading the Cofactor CLI to the latest version.\n *\n * Adapts the `cofactor upgrade` command for MCP context where\n * stdio is the transport and process.exit() must be avoided.\n *\n * @module\n */\n\nimport fs from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport process from 'node:process';\nimport { packageName } from '../brand.js';\nimport { clearUpdateCache } from '../update-check.js';\nimport { toolJson } from './tool-helpers';\n\ntype PackageManager = 'bun' | 'pnpm' | 'npm';\n\nfunction detectPackageManager(): PackageManager {\n try {\n const binPath = fs.realpathSync(process.argv[1]).replace(/\\\\/g, '/');\n if (binPath.includes('.bun/') || binPath.includes('/bun/')) return 'bun';\n if (binPath.includes('.pnpm/') || binPath.includes('/pnpm/')) return 'pnpm';\n } catch {\n // realpathSync can fail if symlink is broken\n }\n return 'npm';\n}\n\nconst UPGRADE_COMMANDS: Record<PackageManager, string[]> = {\n bun: ['bun', 'add', '-g', `${packageName}@latest`],\n pnpm: ['pnpm', 'add', '-g', `${packageName}@latest`],\n npm: ['npm', 'install', '-g', `${packageName}@latest`],\n};\n\nexport function getUpgradeToolDefinitions() {\n return [\n {\n name: 'cofactor_upgrade',\n description:\n 'Upgrade the Cofactor CLI to the latest version. ' +\n 'Detects the package manager (npm, bun, pnpm) and runs the appropriate global install command.',\n inputSchema: {\n type: 'object',\n properties: {},\n },\n },\n ];\n}\n\nexport async function handleUpgradeTool(\n tool: string,\n _args: Record<string, unknown>\n) {\n if (tool !== 'cofactor_upgrade') return null;\n\n try {\n const pm = detectPackageManager();\n const cmd = UPGRADE_COMMANDS[pm];\n\n const result = spawnSync(cmd[0], cmd.slice(1), {\n stdio: ['pipe', 'pipe', 'pipe'],\n cwd: process.cwd(),\n timeout: 120_000,\n shell: process.platform === 'win32',\n windowsHide: true,\n });\n\n if (result.error) {\n return toolJson({\n ok: false,\n error: `Failed to run ${pm}: ${result.error.message}`,\n });\n }\n\n const stdout = result.stdout?.toString().trim() ?? '';\n const stderr = result.stderr?.toString().trim() ?? '';\n\n if (result.status !== 0) {\n return toolJson({\n ok: false,\n error: `Upgrade failed (exit code ${result.status}).`,\n output: stderr || stdout,\n });\n }\n\n await clearUpdateCache();\n\n return toolJson({\n ok: true,\n message: `Successfully upgraded ${packageName} to the latest version.`,\n packageManager: pm,\n output: stdout || undefined,\n });\n } catch (err) {\n return toolJson({ ok: false, error: err instanceof Error ? err.message : String(err) });\n }\n}\n","/**\n * Server instructions for the stdio server: the shared Cofactor text plus the\n * tools that only exist here (login, upgrade, local browser). Clients cap the\n * whole string at 4,096 chars, so the shared text is length-tested with room left\n * for this addendum (`apps/mcp/test/tools.test.ts`).\n *\n * The long workflow-authoring guide does not fit that cap, so it is served by\n * the cofactor_workflow_authoring_guide tool instead.\n *\n * @module\n */\n\nimport { COFACTOR_MCP_INSTRUCTIONS as SHARED_INSTRUCTIONS } from '@chatsdet/mcp-tools';\n\nconst LOCAL_TOOLS = `\n\nLocal tools (this stdio server only):\n- Call cofactor_login first with env \"prod\" unless the user asks for dev or local; if several organizations are available, ask which one and pass it as org.\n- To explore an app, list credentials (cofactor_credential_list), pick the default one (never one named local or manual), start a browser (browser_start or local_browser_start), then loop browser_snapshot (use its search parameter to find elements, mode \"screenshot\" to see the page), act by ref rather than coordinates, and snapshot again after every action to verify; never assume an action worked.\n- To switch organizations later, call cofactor_login again with org; no re-authentication needed.\n- Before writing or changing a test, call cofactor_workflow_authoring_guide.`;\n\nexport const COFACTOR_MCP_INSTRUCTIONS = SHARED_INSTRUCTIONS + LOCAL_TOOLS;\n\nexport const WORKFLOW_AUTHORING_GUIDE = `\n## Building Tests — Workflow Authoring\n\nAfter exploring an app via browser session, you can persist what you discovered as a reusable test workflow. The flow is: **explore → author → create**.\n\n### Step 1: Gather Credential Info\n\nCall \\`cofactor_credential_list\\` to get the credential UUID. You'll need it for the login node.\n- Always use \\`credentialId\\` (UUID) — never just the credential name\n- Set both \\`credentialId\\` and \\`credentialName\\` in the login node\n\n### Step 2: Design the Workflow\n\nA workflow is a directed graph of **nodes** connected by **edges**.\n\n#### Node Types\n\n| Type | Purpose | Required configJson |\n|------|---------|-------------------|\n| \\`login\\` | Authenticate with a credential | \\`credentialId\\`, \\`credentialName\\` |\n| \\`navigate\\` | Go to a URL | \\`pageUrl\\`, \\`pageTitle\\` |\n| \\`action\\` | Interact with elements | \\`customActionTitle\\`, \\`playbookSteps\\`, optionally \\`inlineAssertions\\` |\n| \\`assertion\\` | Standalone page verification | \\`condition\\` text |\n| \\`end\\` | Terminal node | (none) |\n\n#### Action Node Guidelines\n\n- Every action node **must** have a \\`customActionTitle\\` — a short (3-8 word) human-readable title describing the step (e.g., \"Create a new invoice\", \"Fill registration form\")\n- **Group related actions** into a single action node (one node per logical step, not per click)\n- **Prefer inline assertions** on action nodes over separate assertion nodes. Add \\`inlineAssertions\\` to verify outcomes right after the action. **Do not author an \\`id\\` field** — the server stamps a UUID on persist:\n \\`\\`\\`json\n {\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible\",\n \"severity\": \"fail\"\n }\n ]\n }\n \\`\\`\\`\n- Use separate \\`assertion\\` nodes only for standalone page-level verifications (e.g., initial page state before any action)\n\n#### Playbook Steps (inside action nodes)\n\nPlaybook steps describe what to do within an action node. Each step has:\n- \\`order\\`: sequence number (1, 2, 3...)\n- \\`action\\`: what to do — \\`click\\`, \\`fill\\`, \\`fill_form\\`, \\`select\\`, \\`navigate\\`, \\`wait\\`, \\`scroll\\`, \\`hover\\`, \\`upload\\`, \\`verify\\`, \\`press_key\\`, \\`drag\\`, \\`resize\\`, \\`capture\\`, \\`extract_table\\`, \\`python_execute\\`, \\`verify_download\\`, \\`verify_download_content\\`, \\`screenshot\\`, \\`agent_loop\\`\n- \\`target\\`: **semantic description** from the accessibility tree — button text, field labels, placeholder text. Describe as a human would: \"Submit button\", \"Email input field\", \"Status dropdown\". **Never use refs, CSS selectors, or XPaths.**\n- \\`params\\`: for \\`fill\\` actions, include \\`{ \"value\": \"...\" }\\`\n\nEach playbook step is one atomic intent executed in one browser tool call and maps to at most one recorded call. Draw boundaries at stable page states: fuse actions coupled through ephemeral UI state into that call; split unrelated intents and every stable intermediate into separate steps. Do not use \\`other\\`; if no concrete browser-tool-backed action fits, omit that diagnostic observation from \\`playbookSteps\\`. Use \\`click\\` for switches, checkboxes, and click-to-focus behavior. Use \\`press_key\\` with \\`{ \"key\": \"Escape\" }\\` or an explicit \\`click\\` to close popovers and panels; there is no \\`dismiss\\`, \\`toggle\\`, \\`focus\\`, or \\`handle_native_dialog\\` action.\n\n### Macros — Always Prefer Over Hardcoded Data\n\nMacros generate fresh values each run, preventing flaky tests from stale or colliding data. **Never hardcode emails, names, phone numbers, or dates when a macro exists.**\n\n| Macro | Output | Example |\n|-------|--------|---------|\n| \\`$EMAIL()\\` | Unique test email | \\`test-xk9mq2@example-test.com\\` |\n| \\`$FIRST_NAME()\\` | Random first name | \\`Jordan\\` |\n| \\`$LAST_NAME()\\` | Random last name | \\`Chen\\` |\n| \\`$PHONE()\\` | US phone (555 prefix) | \\`+1-555-382-7491\\` |\n| \\`$UUID()\\` | Random UUID v4 | \\`a1b2c3d4-...\\` |\n| \\`$RANDOM_INT(min, max)\\` | Random integer | \\`$RANDOM_INT(100,999)\\` → \\`427\\` |\n| \\`$RANDOM_STRING(length)\\` | Alphanumeric string | \\`$RANDOM_STRING(8)\\` → \\`xK9mQ3bR\\` |\n| \\`$TODAY()\\` | Current date (YYYY-MM-DD) | \\`2026-04-06\\` |\n| \\`$DATE(days)\\` | Date offset from today | \\`$DATE(-7)\\` → last week |\n| \\`$NOW()\\` | ISO 8601 timestamp | \\`2026-04-06T14:30:00.000Z\\` |\n| \\`$NOW(+5m, 'fmt')\\` | Shifted time (+5m/-2h/30s/1d), optional UTC format (YYYY MM DD HH mm ss, unpadded H m) | \\`$NOW(+5m, 'm H * * *')\\` → \\`35 14 * * *\\` |\n| \\`$TIMESTAMP()\\` | Unix milliseconds | \\`1771520400000\\` |\n| \\`$SEQUENCE(\"name\")\\` | Auto-incrementing per run | \\`1\\`, \\`2\\`, \\`3\\`... |\n\nMacros combine inline: \\`\"QA Test $FIRST_NAME() $LAST_NAME()\"\\`, \\`\"order-$RANDOM_STRING(6)\"\\`\n\n**Prefix test data with \"QA Test\"** for identifiability.\n\n### Step 3: Create the Workflow\n\nUse \\`cofactor_workflow_sync\\` for existing workflows or construct the full workflow JSON and create via the API. Then verify with \\`cofactor_workflow_get\\`.\n\n### Example Workflow JSON\n\n\\`\\`\\`json\n{\n \"name\": \"Verify user can create an invoice\",\n \"description\": \"Tests the invoice creation flow end-to-end\",\n \"nodes\": [\n {\n \"nodeType\": \"login\",\n \"configJson\": {\n \"credentialId\": \"4f6db838-16be-49e8-8887-8d0be1c83a87\",\n \"credentialName\": \"QA User\"\n }\n },\n {\n \"nodeType\": \"navigate\",\n \"configJson\": { \"pageUrl\": \"/invoices\", \"pageTitle\": \"Invoices\" }\n },\n {\n \"nodeType\": \"action\",\n \"configJson\": {\n \"customActionTitle\": \"Create a new invoice\",\n \"actionDescription\": \"Fill out the new invoice form and save\",\n \"playbookSteps\": [\n { \"order\": 1, \"action\": \"click\", \"target\": \"New Invoice button\" },\n { \"order\": 2, \"action\": \"fill\", \"target\": \"Client name field\", \"params\": { \"value\": \"QA Test $FIRST_NAME()\" } },\n { \"order\": 3, \"action\": \"fill\", \"target\": \"Amount field\", \"params\": { \"value\": \"$RANDOM_INT(100,999)\" } },\n { \"order\": 4, \"action\": \"click\", \"target\": \"Save button\" }\n ],\n \"inlineAssertions\": [\n {\n \"condition\": \"Success message 'Invoice created' is visible and the new invoice appears in the list\",\n \"severity\": \"fail\"\n }\n ]\n }\n }\n ]\n}\n\\`\\`\\`\n\n## Managing Workflows\n\n- **cofactor_workflow_list** — Browse existing tests. Filter by \\`status\\` (draft = editable, approved = human-verified), \\`flowType\\` (standard/setup/seed/teardown), or \\`search\\` by name. Suite inclusion is derived eligibility (approved AND passed at least once), with a separate pause/unpause toggle; reliability is tracked separately by the workflow's \\`health\\`.\n- **cofactor_workflow_get** — Inspect a test's full definition: nodes, edges, playbook steps, assertions.\n- **cofactor_workflow_patch** — Update name, description, preflight, cleanup, status, or flow type. Only provided fields change. Description, preflight and cleanup are read by people: no raw IDs (name the seed, teardown or record), and write preflight and cleanup as short markdown bullet lists.\n- **cofactor_workflow_run** — Trigger execution. Returns a \\`runId\\` — use it to track progress.\n- **cofactor_workflow_sync** — Atomically replace all nodes and edges. Automatically snapshots current state first so changes are reversible. Read the current DAG with \\`cofactor_workflow_get\\` before syncing.\n\n## Monitoring Runs & Debugging Failures\n\nAfter triggering a workflow run, monitor and debug with:\n\n- **cofactor_workflow_runs_list** — Recent runs for a workflow with status and duration.\n- **cofactor_workflow_runs_get** — Detailed run view: step-by-step status, duration, errors. Also works for in-progress runs to check status.\n- **cofactor_workflow_runs_diagnostics** — AI-generated failure analysis. Returns root cause and recommendations. Falls back to raw console logs and network requests if no AI analysis is available.\n\n### Regression Suite\n\n- **cofactor_test_suite_run** — Trigger a regression suite execution. Returns suiteId for tracking. Use cofactor_test_suite_list or cofactor_test_suite_get to check results.\n- **cofactor_test_suite_list** — Recent regression suite executions with pass/fail counts.\n- **cofactor_test_suite_get** — Individual test results within a suite execution.\n- **cofactor_test_suite_diagnostics** — Failure diagnostics for a specific test in a suite run.\n- **cofactor_test_suite_steps** — Step-by-step breakdown of a test run within a suite.\n\n## Investigating Issues\n\nIssues are bugs discovered by Cofactor during test runs.\n\n- **cofactor_issues_list** — Search and filter issues by severity (\\`low\\`/\\`medium\\`/\\`high\\`), status (\\`open\\`/\\`closed\\`/\\`not_a_bug\\`), or property. Supports full-text search.\n- **cofactor_issues_get** — Full issue detail including console errors and network failures from the latest occurrence, plus every evidence item on recent occurrences with signed screenshot/clip links (the first screenshots come back inline as images), and the issue's comments. Use this to understand what went wrong.\n- **cofactor_issues_comment** — Add a comment to an issue (\\`get\\` returns the comments).\n- **cofactor_issues_update** — Edit an occurrence's summary, repro steps, or evidence items (add, replace, or remove by the numbers cofactor_issues_get shows; screenshots as base64 image data).\n\n## Product Map (what the app does, and what covers it)\n\nAreas → capabilities, with flows linked to capabilities so coverage is showable. Available to every organization.\n\nCapabilities have **natural codes** — \\`CAP-CMM-001\\`, areas \\`ARE-CMM\\` — which are stable and safe to carry between a ticket, a spec, and a tool call. Prefer them over prefixed ids when writing anything a human will read.\n\n- **cofactor_product_map_get** — The whole map for an application. Call this before proposing a new capability so you reuse an existing one by code instead of creating a near-duplicate.\n- **cofactor_product_map_coverage** — Linked/covered rollup. Always report the unmapped-flow count beside any coverage figure; coverage is always coverage of the *known* map.\n- **cofactor_product_map_resolve_code** — Resolve a code, including one retired by a move. Use this before reporting that a code \"does not exist\" — it may just have been renumbered.\n- **cofactor_product_map_get_capability** — One capability in full: body, linked flows by name, previous codes.\n- **cofactor_product_map_link_flows** / **cofactor_product_map_unlink_flows** — Record that a flow covers a capability. Additive/subtractive; other links are preserved.\n\n## API Sequences (API-only workflows)\n\nFor APIs that need deterministic, browser-free smoke testing — composed of ordered HTTP calls that chain outputs into inputs.\n\n- **Create** with the same command as any workflow, with \\`--api-only\\`:\n \\`cofactor workflow create --api-only --name \"<n>\" --sequence-from-file seq.json\\`\n Returns \\`{ workflowId, apiSequenceId, nodeId }\\`. No \\`--property\\` — api-sequences are org-scoped.\n- **Inspect runs** with the same command as any runs, with \\`--side api\\` (or \\`--side all\\` for both):\n \\`cofactor workflow runs list <wf> --side api\\`\n \\`cofactor workflow runs get <wf> <runId>\\`\n- **Edit the sequence itself** via \\`cofactor workflow api-sequence <verb>\\`:\n - \\`get <wf>\\` — dump config + steps\n - \\`update <wf> --from-file seq.json\\` — replace config\n - \\`execute <wf>\\` — run it\n - \\`generate <wf> [--prompt \"...\"]\\` — AI-draft a config, then refine with \\`update\\`\n- **Discover endpoints** before composing steps:\n \\`cofactor api-catalog sources list\\`\n \\`cofactor api-catalog endpoints list --search <q>\\`\n \\`cofactor api-catalog endpoints create --from-file ep.json\\` (add a one-off)\n- **Read the reference first** for the config/step shape and template syntax:\n \\`cofactor workflow guide api-sequences\\`\n\nTemplates in step fields use \\`{{stepId.response.path}}\\` to reference prior-step outputs and \\`$MACRO()\\` for dynamic test data (same macros as browser workflows).\n\n## Common Workflows\n\n### \"Let's explore the app\"\n1. \\`cofactor_login\\` (env: prod) → switch to the right org\n2. \\`cofactor_credential_list\\` → find the right credential\n3. \\`browser_start\\` → launch browser\n4. Load credential and navigate to the app\n5. Snapshot, interact, explore\n\n### \"Write a test for this feature\"\n1. Explore the feature via browser (above workflow)\n2. \\`cofactor_credential_list\\` → get credentialId\n3. Construct workflow JSON with nodes, edges, playbook steps, macros\n4. Create or sync the workflow\n5. \\`cofactor_workflow_run\\` → execute it\n6. \\`cofactor_workflow_runs_get\\` → verify it passes\n\n### \"Why did this test fail?\"\n1. \\`cofactor_workflow_runs_list\\` → find the failed run\n2. \\`cofactor_workflow_runs_get\\` → see which step failed\n3. \\`cofactor_workflow_runs_diagnostics\\` → AI analysis of the failure\n4. If needed, open a browser session to reproduce and investigate\n\n### \"What issues have been found?\"\n1. \\`cofactor_issues_list\\` → browse open issues\n2. \\`cofactor_issues_get\\` → deep dive with console/network errors\n`.trim();\n","/**\n * MCP tool that returns the workflow-authoring guide. It lives in a tool rather\n * than the server instructions because clients cap instructions at 4,096 chars.\n *\n * @module\n */\n\nimport { WORKFLOW_AUTHORING_GUIDE } from './instructions';\nimport { toolText } from './tool-helpers';\n\nconst GUIDE_TOOL = 'cofactor_workflow_authoring_guide';\n\nexport function getGuideToolDefinitions() {\n return [\n {\n name: GUIDE_TOOL,\n description:\n 'How to author a Cofactor test (workflow): node types, playbook steps, macros, example workflow JSON, running and debugging. Read it before creating or syncing a workflow.',\n inputSchema: { type: 'object', properties: {} },\n },\n ];\n}\n\nexport async function handleGuideTool(tool: string) {\n return tool === GUIDE_TOOL ? toolText(WORKFLOW_AUTHORING_GUIDE) : null;\n}\n"],"mappings":"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","names":["resolveApiUrl","profileName","process","process","COFACTOR_MCP_INSTRUCTIONS","COFACTOR_MCP_INSTRUCTIONS"]}
@@ -2,17 +2,17 @@ import { createRequire as __cr } from "module"; import { fileURLToPath as __fup
2
2
  import {
3
3
  apiRequest,
4
4
  fetchList
5
- } from "./chunk-LL6TSQWV.js";
5
+ } from "./chunk-VKZOHJCE.js";
6
6
  import "./chunk-S3Q7MDCS.js";
7
- import "./chunk-76Z6E7XX.js";
7
+ import "./chunk-4UZN6TVT.js";
8
8
  import {
9
9
  getArgValue,
10
10
  hasFlag,
11
11
  resolveConfig
12
- } from "./chunk-3HI6QC4V.js";
12
+ } from "./chunk-WRBU6TX7.js";
13
13
  import {
14
14
  writeRawOutput
15
- } from "./chunk-UEJ2HTKU.js";
15
+ } from "./chunk-MJVUMVLO.js";
16
16
  import "./chunk-TOWZAG3I.js";
17
17
 
18
18
  // src/metrics.ts
@@ -371,4 +371,4 @@ async function runMetrics(argv) {
371
371
  export {
372
372
  runMetrics
373
373
  };
374
- //# sourceMappingURL=metrics-SSIP5CEB.js.map
374
+ //# sourceMappingURL=metrics-KBTQ3KGZ.js.map
@@ -2,16 +2,16 @@ import { createRequire as __cr } from "module"; import { fileURLToPath as __fup
2
2
  import {
3
3
  apiRequest,
4
4
  getApplicationIdArg
5
- } from "./chunk-LL6TSQWV.js";
5
+ } from "./chunk-VKZOHJCE.js";
6
6
  import "./chunk-S3Q7MDCS.js";
7
- import "./chunk-76Z6E7XX.js";
7
+ import "./chunk-4UZN6TVT.js";
8
8
  import {
9
9
  hasFlag,
10
10
  resolveConfig
11
- } from "./chunk-3HI6QC4V.js";
11
+ } from "./chunk-WRBU6TX7.js";
12
12
  import {
13
13
  writeRawOutput
14
- } from "./chunk-UEJ2HTKU.js";
14
+ } from "./chunk-MJVUMVLO.js";
15
15
  import "./chunk-TOWZAG3I.js";
16
16
 
17
17
  // src/monitor.ts
@@ -119,4 +119,4 @@ async function runMonitor(argv) {
119
119
  export {
120
120
  runMonitor
121
121
  };
122
- //# sourceMappingURL=monitor-ESZYHXT2.js.map
122
+ //# sourceMappingURL=monitor-UGWY43IU.js.map