@ken-jo/agent-connector 0.4.95 → 0.4.98

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 (385) hide show
  1. package/LICENSE +202 -202
  2. package/NOTICE +6 -6
  3. package/README.md +605 -599
  4. package/dist/{action-Q7GGO4PA.js → action-5JM23CFJ.js} +16 -16
  5. package/dist/action-5JM23CFJ.js.map +1 -0
  6. package/dist/{amazon-q-ETMAGY3D.js → amazon-q-LFZNGN27.js} +6 -6
  7. package/dist/amazon-q-LFZNGN27.js.map +1 -0
  8. package/dist/{amp-BQZOL5GR.js → amp-CEWOSWQO.js} +4 -4
  9. package/dist/amp-CEWOSWQO.js.map +1 -0
  10. package/dist/{amp-67BZONGF.js → amp-S22XTPEQ.js} +7 -7
  11. package/dist/amp-S22XTPEQ.js.map +1 -0
  12. package/dist/{antigravity-EA4L225L.js → antigravity-LHFEFNMC.js} +5 -5
  13. package/dist/antigravity-LHFEFNMC.js.map +1 -0
  14. package/dist/antigravity-PZXYAO3X.js +18 -0
  15. package/dist/{antigravity-cli-B2HXZFYQ.js → antigravity-cli-MOKFSWOU.js} +5 -5
  16. package/dist/antigravity-cli-MOKFSWOU.js.map +1 -0
  17. package/dist/{antigravity-cli-OM6SC3PE.js → antigravity-cli-PN474FXM.js} +9 -9
  18. package/dist/antigravity-cli-PN474FXM.js.map +1 -0
  19. package/dist/audit-2H7E3Z4N.js +311 -0
  20. package/dist/audit-2H7E3Z4N.js.map +1 -0
  21. package/dist/{chunk-KHO5WNTP.js → chunk-4GH2KA7V.js} +1 -1
  22. package/dist/chunk-4GH2KA7V.js.map +1 -0
  23. package/dist/{chunk-7F5KHLEP.js → chunk-6XWORQM6.js} +4 -4
  24. package/dist/chunk-6XWORQM6.js.map +1 -0
  25. package/dist/{chunk-2Y2MZRLP.js → chunk-7C2IPIIB.js} +3 -3
  26. package/dist/chunk-7C2IPIIB.js.map +1 -0
  27. package/dist/{chunk-NLE2J5P4.js → chunk-7HHW23AC.js} +29 -29
  28. package/dist/chunk-7HHW23AC.js.map +1 -0
  29. package/dist/{chunk-XD7MY6HB.js → chunk-7PSNXUFK.js} +1 -1
  30. package/dist/chunk-7PSNXUFK.js.map +1 -0
  31. package/dist/{chunk-YPAXJ7EW.js → chunk-7VSZXOXJ.js} +13 -13
  32. package/dist/chunk-7VSZXOXJ.js.map +1 -0
  33. package/dist/{chunk-ISEJWBFF.js → chunk-B6PKHS5I.js} +2 -2
  34. package/dist/chunk-B6PKHS5I.js.map +1 -0
  35. package/dist/{chunk-UM5S7DKK.js → chunk-C747DYNT.js} +1 -1
  36. package/dist/chunk-C747DYNT.js.map +1 -0
  37. package/dist/{chunk-PW42ZXCB.js → chunk-DOPFBUCX.js} +3 -3
  38. package/dist/chunk-DOPFBUCX.js.map +1 -0
  39. package/dist/{chunk-I5UXHIDT.js → chunk-DWZ5IWF4.js} +8 -8
  40. package/dist/chunk-DWZ5IWF4.js.map +1 -0
  41. package/dist/{chunk-6WZODR3Z.js → chunk-FJ6F5U3W.js} +5 -5
  42. package/dist/chunk-FJ6F5U3W.js.map +1 -0
  43. package/dist/{chunk-H33M77DD.js → chunk-HATCOSQT.js} +22 -19
  44. package/dist/chunk-HATCOSQT.js.map +1 -0
  45. package/dist/{chunk-UMQ6NBQR.js → chunk-ILWHLGIC.js} +2 -2
  46. package/dist/chunk-ILWHLGIC.js.map +1 -0
  47. package/dist/{chunk-IVAWP6HH.js → chunk-IOJDZJ72.js} +2 -2
  48. package/dist/chunk-IOJDZJ72.js.map +1 -0
  49. package/dist/{chunk-NBYKLUF6.js → chunk-KFPSJRHR.js} +2 -2
  50. package/dist/chunk-KFPSJRHR.js.map +1 -0
  51. package/dist/{chunk-O7SDRBVB.js → chunk-KM2YXO6V.js} +1 -1
  52. package/dist/chunk-KM2YXO6V.js.map +1 -0
  53. package/dist/{chunk-3NH2ARIS.js → chunk-KTBAB556.js} +6 -6
  54. package/dist/chunk-KTBAB556.js.map +1 -0
  55. package/dist/{chunk-5IOTP7LQ.js → chunk-KWC5DQ5Z.js} +7 -5
  56. package/dist/chunk-KWC5DQ5Z.js.map +1 -0
  57. package/dist/{chunk-JKKU2WKG.js → chunk-LD5HAN6O.js} +4 -4
  58. package/dist/chunk-LD5HAN6O.js.map +1 -0
  59. package/dist/{chunk-OP4KBXUO.js → chunk-LFWYYWLV.js} +1 -1
  60. package/dist/chunk-LFWYYWLV.js.map +1 -0
  61. package/dist/{chunk-APZDTY76.js → chunk-LZL2YITN.js} +7 -7
  62. package/dist/chunk-LZL2YITN.js.map +1 -0
  63. package/dist/{chunk-H53QZQJI.js → chunk-PSGTHJQU.js} +1 -1
  64. package/dist/chunk-PSGTHJQU.js.map +1 -0
  65. package/dist/{chunk-FBJQGRET.js → chunk-Q4ISQHUQ.js} +1 -1
  66. package/dist/chunk-Q4ISQHUQ.js.map +1 -0
  67. package/dist/{chunk-6TF7MHG5.js → chunk-Q7PR2WGT.js} +2 -2
  68. package/dist/chunk-Q7PR2WGT.js.map +1 -0
  69. package/dist/{chunk-GZGLCCEE.js → chunk-QYOUQCC6.js} +1 -1
  70. package/dist/chunk-QYOUQCC6.js.map +1 -0
  71. package/dist/{chunk-Z2MRSS2I.js → chunk-RNVIK5YJ.js} +2 -2
  72. package/dist/chunk-RNVIK5YJ.js.map +1 -0
  73. package/dist/{chunk-XC5SJ35F.js → chunk-RPWD5H6Y.js} +5 -5
  74. package/dist/chunk-RPWD5H6Y.js.map +1 -0
  75. package/dist/{chunk-PAPMUAR5.js → chunk-S25MVWBP.js} +12 -12
  76. package/dist/chunk-S25MVWBP.js.map +1 -0
  77. package/dist/{chunk-FJCUKXGX.js → chunk-THI4PI4H.js} +2 -2
  78. package/dist/chunk-THI4PI4H.js.map +1 -0
  79. package/dist/{chunk-D4ELPBB5.js → chunk-TOSNS2BY.js} +43 -43
  80. package/dist/chunk-TOSNS2BY.js.map +1 -0
  81. package/dist/{chunk-MGTDQLJJ.js → chunk-UNU2KPYJ.js} +11 -9
  82. package/dist/chunk-UNU2KPYJ.js.map +1 -0
  83. package/dist/{chunk-MQPNU2CY.js → chunk-UZZTWWGG.js} +1 -1
  84. package/dist/chunk-UZZTWWGG.js.map +1 -0
  85. package/dist/{chunk-4NHXLXSD.js → chunk-W7AGWAMH.js} +2 -2
  86. package/dist/chunk-W7AGWAMH.js.map +1 -0
  87. package/dist/{chunk-OPXAP3AC.js → chunk-XN7S44U4.js} +1 -1
  88. package/dist/chunk-XN7S44U4.js.map +1 -0
  89. package/dist/{chunk-BEFVJ2OE.js → chunk-XXLCMSD3.js} +1 -1
  90. package/dist/chunk-XXLCMSD3.js.map +1 -0
  91. package/dist/{chunk-YT43MUSJ.js → chunk-XZWMJLIT.js} +1 -1
  92. package/dist/chunk-XZWMJLIT.js.map +1 -0
  93. package/dist/{chunk-RK6VBLXP.js → chunk-ZSOS2KOR.js} +1 -1
  94. package/dist/chunk-ZSOS2KOR.js.map +1 -0
  95. package/dist/{claude-code-NMRKTAP7.js → claude-code-FS42PXZO.js} +4 -4
  96. package/dist/claude-code-FS42PXZO.js.map +1 -0
  97. package/dist/{claude-code-GRWO6XBZ.js → claude-code-TA53454O.js} +13 -13
  98. package/dist/claude-code-TA53454O.js.map +1 -0
  99. package/dist/cli/sdk.js +9 -8
  100. package/dist/cli/sdk.js.map +1 -1
  101. package/dist/cli.js +1 -1
  102. package/dist/cli.js.map +1 -1
  103. package/dist/{cline-25KW25IN.js → cline-GZFN32BM.js} +6 -6
  104. package/dist/cline-GZFN32BM.js.map +1 -0
  105. package/dist/{codebuddy-ZNYQACMF.js → codebuddy-IYS3TQZ3.js} +7 -7
  106. package/dist/codebuddy-IYS3TQZ3.js.map +1 -0
  107. package/dist/{codebuff-ETYT5UBL.js → codebuff-6KWBW6CT.js} +4 -4
  108. package/dist/codebuff-6KWBW6CT.js.map +1 -0
  109. package/dist/{codebuff-VR6JUDIY.js → codebuff-D3MIKJHC.js} +6 -6
  110. package/dist/codebuff-D3MIKJHC.js.map +1 -0
  111. package/dist/{codex-YAORPCOD.js → codex-DKBAAUCO.js} +4 -4
  112. package/dist/codex-DKBAAUCO.js.map +1 -0
  113. package/dist/{codex-CPNKTXG3.js → codex-ZKLP5IXZ.js} +9 -9
  114. package/dist/codex-ZKLP5IXZ.js.map +1 -0
  115. package/dist/{continue-WU2IB5KS.js → continue-I34FNSTJ.js} +8 -8
  116. package/dist/continue-I34FNSTJ.js.map +1 -0
  117. package/dist/{copilot-cli-MZTAWMPW.js → copilot-cli-CLBJACQ5.js} +4 -4
  118. package/dist/copilot-cli-CLBJACQ5.js.map +1 -0
  119. package/dist/{copilot-cli-PAP377OM.js → copilot-cli-NWPM5GE6.js} +7 -7
  120. package/dist/copilot-cli-NWPM5GE6.js.map +1 -0
  121. package/dist/{crush-QBXLNN7T.js → crush-A5C5USRL.js} +4 -4
  122. package/dist/crush-A5C5USRL.js.map +1 -0
  123. package/dist/{crush-3AVQA4YU.js → crush-MDGPZSZU.js} +7 -7
  124. package/dist/crush-MDGPZSZU.js.map +1 -0
  125. package/dist/{cursor-DIW43TRZ.js → cursor-D5SWDVSW.js} +3 -3
  126. package/dist/cursor-D5SWDVSW.js.map +1 -0
  127. package/dist/cursor-JRVK56QA.js +22 -0
  128. package/dist/{define-connector-DTWb46UB.d.ts → define-connector-B7tLHVnx.d.ts} +1 -1
  129. package/dist/{detect-6V4LC3MA.js → detect-FKJC36P4.js} +4 -4
  130. package/dist/detect-FKJC36P4.js.map +1 -0
  131. package/dist/{devin-QMEM3OFA.js → devin-TZMRC57O.js} +7 -7
  132. package/dist/devin-TZMRC57O.js.map +1 -0
  133. package/dist/{doctor-2YDUVSAU.js → doctor-PGVYUQYG.js} +26 -26
  134. package/dist/doctor-PGVYUQYG.js.map +1 -0
  135. package/dist/{droid-U3ZBLQFO.js → droid-PFQ2PZSF.js} +4 -4
  136. package/dist/droid-PFQ2PZSF.js.map +1 -0
  137. package/dist/{droid-MOKV53J4.js → droid-SCFWDJR4.js} +7 -7
  138. package/dist/droid-SCFWDJR4.js.map +1 -0
  139. package/dist/{gemini-cli-47ZHCOZR.js → gemini-cli-MLDGOR2L.js} +8 -8
  140. package/dist/gemini-cli-MLDGOR2L.js.map +1 -0
  141. package/dist/{gemini-cli-NMVVBO3K.js → gemini-cli-Y6RJMU24.js} +4 -4
  142. package/dist/gemini-cli-Y6RJMU24.js.map +1 -0
  143. package/dist/{goose-4EI5MYTI.js → goose-5DBHDSJW.js} +9 -9
  144. package/dist/goose-5DBHDSJW.js.map +1 -0
  145. package/dist/{goose-64V46Y2W.js → goose-K2HKUTBK.js} +4 -4
  146. package/dist/goose-K2HKUTBK.js.map +1 -0
  147. package/dist/{grok-cli-QYQPDSVB.js → grok-cli-LX6Q6RUY.js} +7 -7
  148. package/dist/grok-cli-LX6Q6RUY.js.map +1 -0
  149. package/dist/{hermes-F75OSK3Y.js → hermes-LJB3SJKB.js} +7 -7
  150. package/dist/hermes-LJB3SJKB.js.map +1 -0
  151. package/dist/{hermes-F3EGTK6N.js → hermes-MF3NX4ZY.js} +4 -4
  152. package/dist/hermes-MF3NX4ZY.js.map +1 -0
  153. package/dist/{hook-OEVRDMXD.js → hook-PVGBQUQI.js} +16 -16
  154. package/dist/hook-PVGBQUQI.js.map +1 -0
  155. package/dist/index.d.ts +3 -3
  156. package/dist/index.js +5 -5
  157. package/dist/{install-5NMCUDG5.js → install-HPDIK7F6.js} +192 -28
  158. package/dist/install-HPDIK7F6.js.map +1 -0
  159. package/dist/{introspect-dNekqPDY.d.ts → introspect-DWCu0Krk.d.ts} +1 -1
  160. package/dist/{jetbrains-copilot-ZGIWI6YV.js → jetbrains-copilot-2DSVAJMJ.js} +6 -6
  161. package/dist/jetbrains-copilot-2DSVAJMJ.js.map +1 -0
  162. package/dist/{junie-DIFN2P22.js → junie-GUBDRADP.js} +6 -6
  163. package/dist/junie-GUBDRADP.js.map +1 -0
  164. package/dist/{kilo-EMZJBEBB.js → kilo-HRLWMENX.js} +8 -8
  165. package/dist/kilo-HRLWMENX.js.map +1 -0
  166. package/dist/{kilo-SW7BH6EG.js → kilo-SMHPOHJ5.js} +4 -4
  167. package/dist/kilo-SMHPOHJ5.js.map +1 -0
  168. package/dist/{kilo-cli-S3GXBPAE.js → kilo-cli-IQMFMYZF.js} +8 -8
  169. package/dist/kilo-cli-IQMFMYZF.js.map +1 -0
  170. package/dist/{kilo-cli-ZF272ZHN.js → kilo-cli-T2SRRRJS.js} +5 -5
  171. package/dist/kilo-cli-T2SRRRJS.js.map +1 -0
  172. package/dist/{kimi-IQJOIY6B.js → kimi-EPD46UJK.js} +7 -7
  173. package/dist/kimi-EPD46UJK.js.map +1 -0
  174. package/dist/{kimi-5FHEXGZD.js → kimi-MSIDEMCI.js} +4 -4
  175. package/dist/kimi-MSIDEMCI.js.map +1 -0
  176. package/dist/{kiro-BYX4HEAJ.js → kiro-A7DL52FX.js} +7 -7
  177. package/dist/kiro-A7DL52FX.js.map +1 -0
  178. package/dist/{kiro-WGOI5CGT.js → kiro-NYRRBIKW.js} +4 -4
  179. package/dist/kiro-NYRRBIKW.js.map +1 -0
  180. package/dist/{leaderboard-XEKS7B3H.js → leaderboard-KCT7XPCI.js} +7 -7
  181. package/dist/leaderboard-KCT7XPCI.js.map +1 -0
  182. package/dist/{mimo-code-7R53QDHB.js → mimo-code-NDGLBXNC.js} +7 -7
  183. package/dist/mimo-code-NDGLBXNC.js.map +1 -0
  184. package/dist/{mistral-vibe-LHJ55FSB.js → mistral-vibe-LLWASF5X.js} +6 -6
  185. package/dist/mistral-vibe-LLWASF5X.js.map +1 -0
  186. package/dist/{mux-XM6AP35L.js → mux-7PIJ7HUQ.js} +4 -4
  187. package/dist/mux-7PIJ7HUQ.js.map +1 -0
  188. package/dist/{mux-NYCNGL43.js → mux-ON4QK3OC.js} +6 -6
  189. package/dist/mux-ON4QK3OC.js.map +1 -0
  190. package/dist/{nemoclaw-WSIPSE7U.js → nemoclaw-45R5MFBF.js} +7 -7
  191. package/dist/nemoclaw-45R5MFBF.js.map +1 -0
  192. package/dist/{omp-562NK5BJ.js → omp-ROCTFV3A.js} +7 -7
  193. package/dist/omp-ROCTFV3A.js.map +1 -0
  194. package/dist/{open-interpreter-I2CNOEXY.js → open-interpreter-V6CN542J.js} +6 -6
  195. package/dist/open-interpreter-V6CN542J.js.map +1 -0
  196. package/dist/openclaw-AOKFJGRQ.js +17 -0
  197. package/dist/{openclaw-5EQFGOWL.js → openclaw-KAFTNLR2.js} +4 -4
  198. package/dist/openclaw-KAFTNLR2.js.map +1 -0
  199. package/dist/{opencode-YS4WX2E2.js → opencode-YYWQ45LF.js} +7 -7
  200. package/dist/opencode-YYWQ45LF.js.map +1 -0
  201. package/dist/{opencode-QGP4ALQY.js → opencode-Z65JYILL.js} +4 -4
  202. package/dist/opencode-Z65JYILL.js.map +1 -0
  203. package/dist/{openhands-QMYIKNOS.js → openhands-OFFMWCQW.js} +7 -7
  204. package/dist/openhands-OFFMWCQW.js.map +1 -0
  205. package/dist/{package-G25GVTH2.js → package-TALOSRQ4.js} +15 -15
  206. package/dist/package-TALOSRQ4.js.map +1 -0
  207. package/dist/{pi-644FIN3A.js → pi-4W74ETTI.js} +6 -6
  208. package/dist/pi-4W74ETTI.js.map +1 -0
  209. package/dist/{pi-GGDQREVG.js → pi-DLKCPOJE.js} +4 -4
  210. package/dist/pi-DLKCPOJE.js.map +1 -0
  211. package/dist/{qwen-code-GQILBJ5B.js → qwen-code-26CSFDX6.js} +4 -4
  212. package/dist/qwen-code-26CSFDX6.js.map +1 -0
  213. package/dist/{qwen-code-STDMX7EM.js → qwen-code-JOBFNEVT.js} +16 -16
  214. package/dist/qwen-code-JOBFNEVT.js.map +1 -0
  215. package/dist/{roo-code-SUWI4BBN.js → roo-code-HSAE2CJU.js} +4 -4
  216. package/dist/roo-code-HSAE2CJU.js.map +1 -0
  217. package/dist/{roo-code-DLPIHHQ6.js → roo-code-RHIGJZNY.js} +6 -6
  218. package/dist/roo-code-RHIGJZNY.js.map +1 -0
  219. package/dist/runtime/index.d.ts +9 -8
  220. package/dist/runtime/index.js +14 -14
  221. package/dist/sdk/index.d.ts +4 -4
  222. package/dist/sdk/index.js +6 -6
  223. package/dist/sdk/index.js.map +1 -1
  224. package/dist/sdk/test.d.ts +2 -2
  225. package/dist/sdk/test.js +11 -11
  226. package/dist/{serve-XTMIUHKK.js → serve-4TEHK726.js} +16 -16
  227. package/dist/serve-4TEHK726.js.map +1 -0
  228. package/dist/{status-VJAGO4Z7.js → status-DVD4EHMX.js} +11 -11
  229. package/dist/status-DVD4EHMX.js.map +1 -0
  230. package/dist/{statusline-EY2E2UGF.js → statusline-ZVNH7XBK.js} +15 -15
  231. package/dist/statusline-ZVNH7XBK.js.map +1 -0
  232. package/dist/{synthetic-6FRA7P5Q.js → synthetic-LUT6V6SD.js} +4 -4
  233. package/dist/synthetic-LUT6V6SD.js.map +1 -0
  234. package/dist/{telemetry-OLZQBADT.js → telemetry-NWUJPIK3.js} +10 -10
  235. package/dist/telemetry-NWUJPIK3.js.map +1 -0
  236. package/dist/{trae-CPPYASR2.js → trae-SIQI3C66.js} +4 -4
  237. package/dist/trae-SIQI3C66.js.map +1 -0
  238. package/dist/{trae-UOYD6JZZ.js → trae-TLAFSQRQ.js} +6 -6
  239. package/dist/trae-TLAFSQRQ.js.map +1 -0
  240. package/dist/{types-JyhpJHJa.d.ts → types-C6j18a6R.d.ts} +13 -14
  241. package/dist/{uninstall-AZEUPAND.js → uninstall-DZVFV7KE.js} +21 -21
  242. package/dist/uninstall-DZVFV7KE.js.map +1 -0
  243. package/dist/{upgrade-CAUUHSSC.js → upgrade-OUE4ED52.js} +21 -21
  244. package/dist/upgrade-OUE4ED52.js.map +1 -0
  245. package/dist/{usage-3KHZ4RYZ.js → usage-NT3ZXALZ.js} +4 -4
  246. package/dist/usage-NT3ZXALZ.js.map +1 -0
  247. package/dist/{usage-event-TZWOZPRJ.js → usage-event-IELZE6WO.js} +15 -15
  248. package/dist/usage-event-IELZE6WO.js.map +1 -0
  249. package/dist/{vscode-copilot-NIMH2DGU.js → vscode-copilot-VZ5XYSTK.js} +7 -7
  250. package/dist/vscode-copilot-VZ5XYSTK.js.map +1 -0
  251. package/dist/{warp-NRBBJQR2.js → warp-5YBSP7FP.js} +4 -4
  252. package/dist/warp-5YBSP7FP.js.map +1 -0
  253. package/dist/{warp-QYJGKURM.js → warp-P2HWXIKT.js} +6 -6
  254. package/dist/warp-P2HWXIKT.js.map +1 -0
  255. package/dist/{windsurf-75LLZ37C.js → windsurf-3JC73GZK.js} +6 -6
  256. package/dist/windsurf-3JC73GZK.js.map +1 -0
  257. package/dist/{zed-HKAZXEJW.js → zed-6CMUKXLI.js} +7 -7
  258. package/dist/zed-6CMUKXLI.js.map +1 -0
  259. package/dist/{zed-XJFOOKCO.js → zed-XXCNYOIN.js} +4 -4
  260. package/dist/zed-XXCNYOIN.js.map +1 -0
  261. package/package.json +92 -88
  262. package/dist/action-Q7GGO4PA.js.map +0 -1
  263. package/dist/amazon-q-ETMAGY3D.js.map +0 -1
  264. package/dist/amp-67BZONGF.js.map +0 -1
  265. package/dist/amp-BQZOL5GR.js.map +0 -1
  266. package/dist/antigravity-EA4L225L.js.map +0 -1
  267. package/dist/antigravity-VXLDLTO7.js +0 -18
  268. package/dist/antigravity-cli-B2HXZFYQ.js.map +0 -1
  269. package/dist/antigravity-cli-OM6SC3PE.js.map +0 -1
  270. package/dist/chunk-2Y2MZRLP.js.map +0 -1
  271. package/dist/chunk-3NH2ARIS.js.map +0 -1
  272. package/dist/chunk-4NHXLXSD.js.map +0 -1
  273. package/dist/chunk-5IOTP7LQ.js.map +0 -1
  274. package/dist/chunk-6TF7MHG5.js.map +0 -1
  275. package/dist/chunk-6WZODR3Z.js.map +0 -1
  276. package/dist/chunk-7F5KHLEP.js.map +0 -1
  277. package/dist/chunk-APZDTY76.js.map +0 -1
  278. package/dist/chunk-BEFVJ2OE.js.map +0 -1
  279. package/dist/chunk-D4ELPBB5.js.map +0 -1
  280. package/dist/chunk-FBJQGRET.js.map +0 -1
  281. package/dist/chunk-FJCUKXGX.js.map +0 -1
  282. package/dist/chunk-GZGLCCEE.js.map +0 -1
  283. package/dist/chunk-H33M77DD.js.map +0 -1
  284. package/dist/chunk-H53QZQJI.js.map +0 -1
  285. package/dist/chunk-I5UXHIDT.js.map +0 -1
  286. package/dist/chunk-ISEJWBFF.js.map +0 -1
  287. package/dist/chunk-IVAWP6HH.js.map +0 -1
  288. package/dist/chunk-JKKU2WKG.js.map +0 -1
  289. package/dist/chunk-KHO5WNTP.js.map +0 -1
  290. package/dist/chunk-MGTDQLJJ.js.map +0 -1
  291. package/dist/chunk-MQPNU2CY.js.map +0 -1
  292. package/dist/chunk-NBYKLUF6.js.map +0 -1
  293. package/dist/chunk-NLE2J5P4.js.map +0 -1
  294. package/dist/chunk-O7SDRBVB.js.map +0 -1
  295. package/dist/chunk-OP4KBXUO.js.map +0 -1
  296. package/dist/chunk-OPXAP3AC.js.map +0 -1
  297. package/dist/chunk-PAPMUAR5.js.map +0 -1
  298. package/dist/chunk-PW42ZXCB.js.map +0 -1
  299. package/dist/chunk-RK6VBLXP.js.map +0 -1
  300. package/dist/chunk-UM5S7DKK.js.map +0 -1
  301. package/dist/chunk-UMQ6NBQR.js.map +0 -1
  302. package/dist/chunk-XC5SJ35F.js.map +0 -1
  303. package/dist/chunk-XD7MY6HB.js.map +0 -1
  304. package/dist/chunk-YPAXJ7EW.js.map +0 -1
  305. package/dist/chunk-YT43MUSJ.js.map +0 -1
  306. package/dist/chunk-Z2MRSS2I.js.map +0 -1
  307. package/dist/claude-code-GRWO6XBZ.js.map +0 -1
  308. package/dist/claude-code-NMRKTAP7.js.map +0 -1
  309. package/dist/cline-25KW25IN.js.map +0 -1
  310. package/dist/codebuddy-ZNYQACMF.js.map +0 -1
  311. package/dist/codebuff-ETYT5UBL.js.map +0 -1
  312. package/dist/codebuff-VR6JUDIY.js.map +0 -1
  313. package/dist/codex-CPNKTXG3.js.map +0 -1
  314. package/dist/codex-YAORPCOD.js.map +0 -1
  315. package/dist/continue-WU2IB5KS.js.map +0 -1
  316. package/dist/copilot-cli-MZTAWMPW.js.map +0 -1
  317. package/dist/copilot-cli-PAP377OM.js.map +0 -1
  318. package/dist/crush-3AVQA4YU.js.map +0 -1
  319. package/dist/crush-QBXLNN7T.js.map +0 -1
  320. package/dist/cursor-DIW43TRZ.js.map +0 -1
  321. package/dist/cursor-GSLUET3V.js +0 -22
  322. package/dist/detect-6V4LC3MA.js.map +0 -1
  323. package/dist/devin-QMEM3OFA.js.map +0 -1
  324. package/dist/doctor-2YDUVSAU.js.map +0 -1
  325. package/dist/droid-MOKV53J4.js.map +0 -1
  326. package/dist/droid-U3ZBLQFO.js.map +0 -1
  327. package/dist/gemini-cli-47ZHCOZR.js.map +0 -1
  328. package/dist/gemini-cli-NMVVBO3K.js.map +0 -1
  329. package/dist/goose-4EI5MYTI.js.map +0 -1
  330. package/dist/goose-64V46Y2W.js.map +0 -1
  331. package/dist/grok-cli-QYQPDSVB.js.map +0 -1
  332. package/dist/hermes-F3EGTK6N.js.map +0 -1
  333. package/dist/hermes-F75OSK3Y.js.map +0 -1
  334. package/dist/hook-OEVRDMXD.js.map +0 -1
  335. package/dist/install-5NMCUDG5.js.map +0 -1
  336. package/dist/jetbrains-copilot-ZGIWI6YV.js.map +0 -1
  337. package/dist/junie-DIFN2P22.js.map +0 -1
  338. package/dist/kilo-EMZJBEBB.js.map +0 -1
  339. package/dist/kilo-SW7BH6EG.js.map +0 -1
  340. package/dist/kilo-cli-S3GXBPAE.js.map +0 -1
  341. package/dist/kilo-cli-ZF272ZHN.js.map +0 -1
  342. package/dist/kimi-5FHEXGZD.js.map +0 -1
  343. package/dist/kimi-IQJOIY6B.js.map +0 -1
  344. package/dist/kiro-BYX4HEAJ.js.map +0 -1
  345. package/dist/kiro-WGOI5CGT.js.map +0 -1
  346. package/dist/leaderboard-XEKS7B3H.js.map +0 -1
  347. package/dist/mimo-code-7R53QDHB.js.map +0 -1
  348. package/dist/mistral-vibe-LHJ55FSB.js.map +0 -1
  349. package/dist/mux-NYCNGL43.js.map +0 -1
  350. package/dist/mux-XM6AP35L.js.map +0 -1
  351. package/dist/nemoclaw-WSIPSE7U.js.map +0 -1
  352. package/dist/omp-562NK5BJ.js.map +0 -1
  353. package/dist/open-interpreter-I2CNOEXY.js.map +0 -1
  354. package/dist/openclaw-5EQFGOWL.js.map +0 -1
  355. package/dist/openclaw-7EYBQS4R.js +0 -17
  356. package/dist/opencode-QGP4ALQY.js.map +0 -1
  357. package/dist/opencode-YS4WX2E2.js.map +0 -1
  358. package/dist/openhands-QMYIKNOS.js.map +0 -1
  359. package/dist/package-G25GVTH2.js.map +0 -1
  360. package/dist/pi-644FIN3A.js.map +0 -1
  361. package/dist/pi-GGDQREVG.js.map +0 -1
  362. package/dist/qwen-code-GQILBJ5B.js.map +0 -1
  363. package/dist/qwen-code-STDMX7EM.js.map +0 -1
  364. package/dist/roo-code-DLPIHHQ6.js.map +0 -1
  365. package/dist/roo-code-SUWI4BBN.js.map +0 -1
  366. package/dist/serve-XTMIUHKK.js.map +0 -1
  367. package/dist/status-VJAGO4Z7.js.map +0 -1
  368. package/dist/statusline-EY2E2UGF.js.map +0 -1
  369. package/dist/synthetic-6FRA7P5Q.js.map +0 -1
  370. package/dist/telemetry-OLZQBADT.js.map +0 -1
  371. package/dist/trae-CPPYASR2.js.map +0 -1
  372. package/dist/trae-UOYD6JZZ.js.map +0 -1
  373. package/dist/uninstall-AZEUPAND.js.map +0 -1
  374. package/dist/upgrade-CAUUHSSC.js.map +0 -1
  375. package/dist/usage-3KHZ4RYZ.js.map +0 -1
  376. package/dist/usage-event-TZWOZPRJ.js.map +0 -1
  377. package/dist/vscode-copilot-NIMH2DGU.js.map +0 -1
  378. package/dist/warp-NRBBJQR2.js.map +0 -1
  379. package/dist/warp-QYJGKURM.js.map +0 -1
  380. package/dist/windsurf-75LLZ37C.js.map +0 -1
  381. package/dist/zed-HKAZXEJW.js.map +0 -1
  382. package/dist/zed-XJFOOKCO.js.map +0 -1
  383. /package/dist/{antigravity-VXLDLTO7.js.map → antigravity-PZXYAO3X.js.map} +0 -0
  384. /package/dist/{cursor-GSLUET3V.js.map → cursor-JRVK56QA.js.map} +0 -0
  385. /package/dist/{openclaw-7EYBQS4R.js.map → openclaw-AOKFJGRQ.js.map} +0 -0
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  normalizeSessionSource
4
- } from "./chunk-H53QZQJI.js";
4
+ } from "./chunk-PSGTHJQU.js";
5
5
  import {
6
6
  rewriteEnvRefs
7
- } from "./chunk-BEFVJ2OE.js";
7
+ } from "./chunk-XXLCMSD3.js";
8
8
  import {
9
9
  BaseAdapter,
10
10
  renderSkillMd
11
- } from "./chunk-MGTDQLJJ.js";
11
+ } from "./chunk-UNU2KPYJ.js";
12
12
  import {
13
13
  buildWrappedStdio,
14
14
  isHomeBinHookCommand
15
- } from "./chunk-4NHXLXSD.js";
15
+ } from "./chunk-W7AGWAMH.js";
16
16
 
17
17
  // src/adapters/cursor/index.ts
18
18
  import { existsSync } from "fs";
@@ -650,4 +650,4 @@ export {
650
650
  adapter,
651
651
  cursor_default
652
652
  };
653
- //# sourceMappingURL=chunk-6WZODR3Z.js.map
653
+ //# sourceMappingURL=chunk-FJ6F5U3W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/cursor/index.ts"],"sourcesContent":["/**\r\n * adapters/cursor — Cursor platform adapter for agent-connector.\r\n *\r\n * Generalized from context-mode's proven Cursor adapter: the served identity is\r\n * now `ctx.connector` (not a hardcoded \"context-mode\"), and every hook command\r\n * points at the single stable home binary (the shared hook-merge engine builds\r\n * the command) so one framework update propagates everywhere.\r\n *\r\n * Cursor is a json-stdio host:\r\n * - MCP servers: user scope → ~/.cursor/mcp.json (\"mcpServers\"); project scope\r\n * → <projectDir>/.cursor/mcp.json (\"mcpServers\").\r\n * - Hooks: <configDir>/hooks.json with shape `{ version, hooks: { <cursorEvent>:\r\n * [ { command, matcher? } ] } }`. Unlike Claude, each entry is a FLAT command\r\n * object (no `{ matcher, hooks:[...] }` wrapper).\r\n * - Reply: a JSON object on stdout (exit 0). deny/ask carry `permission` +\r\n * `user_message`; modify carries `updated_input`; context injects via\r\n * `agent_message` (PreToolUse) or `additional_context` (Post/SessionStart).\r\n *\r\n * Cursor supports its own `${env:VAR}` native interpolation, so env/header/url\r\n * values are rewritten to that native token rather than baked into the file.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type { Adapter, HookReply, InstallContext, NormalizedEvent } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n CommandDef,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostToolUseEvent,\r\n PostToolUseFailureEvent,\r\n PreCompactEvent,\r\n PreToolUseEvent,\r\n ServerDef,\r\n SessionEndEvent,\r\n SessionStartEvent,\r\n StopEvent,\r\n SubagentDef,\r\n SubagentStartEvent,\r\n SubagentStopEvent,\r\n Transport,\r\n UserPromptSubmitEvent,\r\n} from \"../../core/types.js\";\r\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\r\nimport {\r\n buildWrappedStdio,\r\n isHomeBinHookCommand,\r\n} from \"../../core/spawn.js\";\r\nimport { renderSkillMd } from \"../claude-code/render.js\";\r\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\r\n\r\nconst HOST: PlatformId = \"cursor\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * Native hooks.json version Cursor expects. Exported as the SINGLE source of\r\n * truth for Cursor's hooks-file version, shared with the `cursor-plugin`\r\n * package emitter so the live install + the packaged bundle can never stamp\r\n * different versions (see core/package-formats/cursor.ts).\r\n */\r\nexport const CURSOR_HOOKS_VERSION = 1;\r\n\r\n/**\r\n * Cursor-native hook event names, in the lower-camel form Cursor reads from\r\n * hooks.json. The first four are the events the proven context-mode adapter\r\n * registers; postToolUseFailure / subagentStart / subagentStop are Cursor's\r\n * documented \"Subagent (Task tool) lifecycle\" + tool-failure hooks.\r\n */\r\nconst CURSOR_EVENT = {\r\n PreToolUse: \"preToolUse\",\r\n PostToolUse: \"postToolUse\",\r\n SessionStart: \"sessionStart\",\r\n Stop: \"stop\",\r\n PostToolUseFailure: \"postToolUseFailure\",\r\n SubagentStart: \"subagentStart\",\r\n SubagentStop: \"subagentStop\",\r\n // Lifecycle/prompt events Cursor 1.7+ documents (cursor.com/docs/hooks):\r\n // sessionEnd is fire-and-forget; preCompact is observational (cannot block);\r\n // beforeSubmitPrompt fires before a prompt is sent and CAN prevent submission\r\n // (Cursor itself matches beforeSubmitPrompt against the value \"UserPromptSubmit\").\r\n SessionEnd: \"sessionEnd\",\r\n PreCompact: \"preCompact\",\r\n UserPromptSubmit: \"beforeSubmitPrompt\",\r\n} as const;\r\n\r\n/**\r\n * Map our normalized event names to Cursor's native hook event names. Only the\r\n * events Cursor actually supports are present; everything else has no Cursor\r\n * equivalent and is reported as a skip/warn at install time.\r\n *\r\n * PermissionRequest is deliberately ABSENT: Cursor has no permission-dialog\r\n * event — its permission gate is the OUTPUT field `permission: \"allow\"|\"deny\"|\r\n * \"ask\"` of the before* hooks (beforeShellExecution / beforeMCPExecution /\r\n * beforeReadFile / preToolUse), not an observable event. Install reports the\r\n * standard skip-warn for it.\r\n *\r\n * Exported as the SINGLE source of truth for canonical→Cursor-native event\r\n * mapping, shared with the `cursor-plugin` package emitter (see\r\n * core/package-formats/cursor.ts) so the packaged bundle's hooks.json keys can\r\n * never silently diverge from the live install adapter's.\r\n */\r\nexport const CURSOR_EVENT_MAP: Partial<Record<HookEventName, string>> = {\r\n PreToolUse: CURSOR_EVENT.PreToolUse,\r\n PostToolUse: CURSOR_EVENT.PostToolUse,\r\n SessionStart: CURSOR_EVENT.SessionStart,\r\n Stop: CURSOR_EVENT.Stop,\r\n PostToolUseFailure: CURSOR_EVENT.PostToolUseFailure,\r\n SubagentStart: CURSOR_EVENT.SubagentStart,\r\n SubagentStop: CURSOR_EVENT.SubagentStop,\r\n SessionEnd: CURSOR_EVENT.SessionEnd,\r\n PreCompact: CURSOR_EVENT.PreCompact,\r\n UserPromptSubmit: CURSOR_EVENT.UserPromptSubmit,\r\n};\r\n\r\n/** A single Cursor native hook entry — a flat command object. */\r\ninterface CursorHookEntry {\r\n command: string;\r\n matcher?: string;\r\n}\r\n\r\n/** Native MCP server entry shapes Cursor accepts under `mcpServers`. */\r\ninterface CursorStdioServer {\r\n command: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\ninterface CursorHttpServer {\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/** Raw Cursor hook stdin payload (snake_case wire fields). */\r\ninterface CursorWireInput {\r\n connector?: unknown;\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n tool_output?: string;\r\n error_message?: string;\r\n cwd?: string;\r\n workspace_roots?: string[];\r\n conversation_id?: string;\r\n session_id?: string;\r\n generation_id?: string;\r\n trigger?: string;\r\n status?: string;\r\n loop_count?: number;\r\n stop_hook_active?: boolean;\r\n\r\n // sessionStart — Cursor's stdin is EXACTLY { session_id, is_background_agent,\r\n // composer_mode } (cursor.com/docs/hooks ~1278-1297): there is NO source/trigger\r\n // start-source discriminator. composer_mode is the editor MODE (agent|ask|edit),\r\n // NOT our normalized SessionStart.source enum (startup|compact|resume|clear), so\r\n // it does not map; surfaced here only so the host shape is documented (no\r\n // normalized field exists for either — see core/types.ts SessionStartEvent).\r\n is_background_agent?: boolean;\r\n composer_mode?: string;\r\n\r\n // beforeSubmitPrompt (UserPromptSubmit) — the submitted prompt text.\r\n // sessionEnd — the documented end reason. Both field names are taken\r\n // verbatim from cursor.com/docs/hooks (snake_case wire).\r\n prompt?: string;\r\n reason?: string;\r\n\r\n // postToolUseFailure — Cursor's existing error vocabulary is error_message;\r\n // the Claude-compatible names are accepted defensively (unverified wire).\r\n error?: string;\r\n tool_use_id?: string;\r\n is_interrupt?: boolean;\r\n // postToolUse / postToolUseFailure carry a BARE `duration` (ms), not\r\n // `duration_ms` (cursor.com/docs/hooks ~870,883,904,918). `duration_ms` is the\r\n // distinct field on sessionEnd (~1315) and subagentStop (~973,994), kept below.\r\n duration?: number;\r\n duration_ms?: number;\r\n\r\n // subagentStart / subagentStop (Task-tool lifecycle). Both name families are\r\n // parsed defensively: agent_* (Claude-compatible) and subagent_* (Cursor-ish).\r\n agent_id?: string;\r\n agent_type?: string;\r\n subagent_id?: string;\r\n subagent_type?: string;\r\n // subagentStop carries the subagent's output text under `summary`, NOT\r\n // last_assistant_message (cursor.com/docs/hooks ~972,993). This is read into\r\n // the normalized lastAssistantMessage.\r\n summary?: string;\r\n}\r\n\r\nexport class CursorAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Cursor\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\r\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\r\n supportsMemory: true,\r\n // Cursor natively supports pre/post tool-use, session start/end, prompt\r\n // submission, context compaction, and stop (cursor.com/docs/hooks, v1.7+).\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n sessionStart: true,\r\n sessionEnd: true,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: false,\r\n // Newer events: Cursor has dedicated postToolUseFailure + subagentStart/\r\n // subagentStop hooks. permissionRequest stays unset — Cursor's permission\r\n // gate is an OUTPUT field of its before* hooks, not an observable event\r\n // (see the EVENT_MAP note).\r\n postToolUseFailure: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // Cursor's preToolUse can rewrite tool input (updated_input) but cannot\r\n // rewrite already-emitted tool output.\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n transports: [\"stdio\", \"http\"],\r\n // Server env/url use Cursor's NATIVE ${env:VAR} interpolation (rewriteEnvRefs)\r\n // — the token survives into mcp.json, never a baked literal — so the\r\n // installer's unset-env-ref bake warn does not apply here.\r\n nativeServerEnvInterpolation: true,\r\n // Content surfaces: Cursor supports all three (commands, skills, subagents).\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n // Native passthrough hooks: Cursor documents many granular hooks with NO\r\n // canonical analog — beforeShellExecution / afterShellExecution /\r\n // beforeMCPExecution / afterMCPExecution / beforeReadFile / afterFileEdit /\r\n // beforeTabFileRead / afterTabFileEdit / workspaceOpen / afterAgentResponse /\r\n // afterAgentThought (cursor.com/docs/hooks). They are\r\n // host-specific (below the >=3-host core bar; see\r\n // docs/research/host-specific-hook-events-design.md). A connector reaches them\r\n // by declaring platforms[\"cursor\"].nativeHooks; installHooks writes those\r\n // event-name keys verbatim into hooks.json, and the generic uninstall reverses\r\n // them.\r\n supportsNativeHooks: true,\r\n // Cursor has a command-driven status line (`/statusline` → `statusLine` in\r\n // ~/.cursor/cli-config.json, GLOBAL scope only) per the Cursor changelog, but\r\n // the config-key shape + the Claude-parity stdin payload are sourced from a\r\n // community tool (agent-status-pills), not first-party Cursor docs — payload\r\n // field names unverified. Deferred pending a live cursor-agent capture; not a\r\n // permanent gap; user-scope only when wired.\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".cursor\");\r\n const userMcp = join(userDir, \"mcp.json\");\r\n const userHooks = join(userDir, \"hooks.json\");\r\n const projectDirCursor = join(projectDir, \".cursor\");\r\n const installed =\r\n existsSync(userDir) ||\r\n existsSync(userMcp) ||\r\n existsSync(userHooks) ||\r\n existsSync(projectDirCursor);\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath: userMcp,\r\n scope: \"user\",\r\n reason: installed\r\n ? `found Cursor config under ${userDir}`\r\n : `no Cursor config at ${userDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".cursor\")\r\n : join(homedir(), \".cursor\");\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"mcp.json\");\r\n }\r\n\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"hooks.json\");\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for cursor\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n // Shallow-merge any per-platform server override into the base ServerDef.\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /** Render a normalized ServerDef into Cursor's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): CursorStdioServer | CursorHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n const entry: CursorStdioServer = { command: this.rewrite(command) };\r\n if (args.length > 0) entry.args = args.map((a) => this.rewrite(a));\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = this.rewrite(server.cwd);\r\n return entry;\r\n }\r\n\r\n // http (and any other remote transport we surface) — Cursor registers a URL.\r\n const entry: CursorHttpServer = { url: this.rewrite(server.url ?? \"\") };\r\n const headers = this.renderEnv(server.headers);\r\n if (headers) entry.headers = headers;\r\n return entry;\r\n }\r\n\r\n /**\r\n * Render env/header values. Cursor supports its own `${env:VAR}` native\r\n * interpolation, so translate `${env:VAR}` refs to that native token rather\r\n * than baking secrets into the file. Literals pass through unchanged.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n const out: Record<string, string> = {};\r\n for (const [k, v] of Object.entries(env)) out[k] = this.rewrite(v);\r\n return out;\r\n }\r\n\r\n /** Translate `${env:VAR(:-default)}` to Cursor's native `${env:VAR}` token. */\r\n private rewrite(value: string): string {\r\n return rewriteEnvRefs(value, cursorEnvToken);\r\n }\r\n\r\n // ── Hook install / uninstall ─────────────────────────────────────────────\r\n\r\n installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST];\r\n\r\n // `hooks: false` disables only the NORMALIZED events. nativeHooks is a\r\n // sibling, cursor-scoped declaration on the same override and installs\r\n // regardless.\r\n const normalizedEvents = override?.hooks === false ? [] : connector.hookEvents;\r\n const nativeHooks = override?.nativeHooks ?? {};\r\n const nativeEvents = Object.keys(nativeHooks);\r\n\r\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: override?.hooks === false ? \"hooks disabled for cursor\" : \"connector declares no hooks\",\r\n },\r\n ];\r\n }\r\n\r\n // Normalized events go through the engine's mapEvent/warn path; native\r\n // event-name keys ride the separate `native` pass (verbatim keys, EXACT\r\n // command, the `(native)` detail) — see the descriptor + base.upsertHookEntries.\r\n const pending = normalizedEvents.map((event) => ({\r\n event,\r\n matcher: connector.hooks[event]?.matcher ?? \"\",\r\n }));\r\n const native = nativeEvents.map((event) => ({\r\n event,\r\n matcher: nativeHooks[event]?.matcher ?? \"\",\r\n }));\r\n return this.upsertHookEntries(\r\n ctx,\r\n this.getHookConfigPath(ctx),\r\n pending,\r\n this.hookDescriptor(ctx),\r\n native,\r\n );\r\n }\r\n\r\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\r\n }\r\n\r\n /**\r\n * Cursor's hook-merge descriptor (FLAT shape `{ command, matcher? }`):\r\n * - mapEvent renames canonical → Cursor's lower-camel native key\r\n * (CURSOR_EVENT_MAP); an unmapped event warn-skips (no Cursor equivalent).\r\n * - renderEntry omits the `matcher` key when the matcher is falsy — this\r\n * `{command}` vs `{command,matcher}` distinction is load-bearing on-disk\r\n * bytes (Cursor's flat entry shape), reproduced exactly here.\r\n * - install find is connector-generic (ANY of our commands at the flat\r\n * `entry.command`); uninstall drops whole owned entries (flat — NO\r\n * stripInner). The version stamp is install-only via onMutate.\r\n * - the native pass uses EXACT-command ownership so a native key coinciding\r\n * with a normalized event's mapped key adds a SECOND distinct command\r\n * rather than clobbering the normalized entry.\r\n */\r\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<CursorHookEntry> {\r\n return {\r\n mapEvent: (e) => CURSOR_EVENT_MAP[e as HookEventName],\r\n unmappedWarnDetail: (e) => `${e} has no Cursor hook equivalent — skipped`,\r\n renderEntry: (_event, matcher, command) =>\r\n matcher ? { command, matcher } : { command },\r\n entryOwnsCommand: (entry, _command) => this.isOurCommand(entry.command, ctx),\r\n ownsEntryForRemove: (c) => (entry) => this.isOurCommand(entry.command, c),\r\n skipDetail: (e) => `hooks.${e} already registered`,\r\n removeDetail: (e, n) => `hooks.${e} (${n})`,\r\n absentDetail: \"no hooks section present\",\r\n noMatchDetail: \"no matching hook entries\",\r\n onMutate: (file) => {\r\n (file as { version?: number }).version = CURSOR_HOOKS_VERSION;\r\n },\r\n nativeOwnsCommand: (entry, command) => entry.command === command,\r\n nativeSkipDetail: (e) => `hooks.${e} (native) already registered`,\r\n nativeMutateDetail: (e) => `hooks.${e} (native)`,\r\n };\r\n }\r\n\r\n /** True when a hook command references our home binary AND this connector id\r\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\r\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\r\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\r\n }\r\n\r\n // ── Content surfaces: commands / skills / subagents ──────────────────────\r\n // CONTENT-ONLY: pure native-file writers under <configDir>/{commands,skills,\r\n // agents}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\r\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\r\n // and reversible via removeContentFile. Honors platforms[\"cursor\"] per-surface\r\n // false to skip. Cursor commands are BODY-ONLY markdown (no frontmatter);\r\n // skills are the uniform <name>/SKILL.md + resources; subagents are md+fm.\r\n\r\n private commandsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"commands\");\r\n }\r\n private skillsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"skills\");\r\n }\r\n private agentsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"agents\");\r\n }\r\n\r\n /** Native command file path: <configDir>/commands/<name>.md. */\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.commandsDir(ctx), `${name}.md`);\r\n }\r\n /** Native skill dir: <configDir>/skills/<name>. */\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.skillsDir(ctx), name);\r\n }\r\n /** Native subagent file path: <configDir>/agents/<name>.md. */\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.agentsDir(ctx), `${name}.md`);\r\n }\r\n\r\n // ── Commands ──────────────────────────────────────────────────────────────\r\n\r\n override installCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for cursor\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(\r\n this.commandPath(ctx, cmd.name),\r\n this.renderCommand(cmd),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /**\r\n * Render a Cursor command: BODY-ONLY markdown (no frontmatter). Cursor reads\r\n * the file as the command prompt verbatim. We prepend the one-line description\r\n * as an HTML comment header when present so authoring intent survives the\r\n * round-trip without leaking into the rendered prompt. A description containing\r\n * \"-->\" would prematurely CLOSE the HTML comment and leak the remainder into\r\n * the prompt, so we neutralize that sequence before embedding it.\r\n */\r\n private renderCommand(cmd: CommandDef): string {\r\n if (!cmd.description) return `${cmd.prompt}\\n`;\r\n // Break any literal comment-close so it cannot terminate our header early.\r\n const safe = cmd.description.replace(/--+>/g, (m) => m.replace(/>/g, \"&gt;\"));\r\n return `<!-- ${safe} -->\\n\\n${cmd.prompt}\\n`;\r\n }\r\n\r\n // ── Skills ────────────────────────────────────────────────────────────────\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for cursor\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(\r\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\r\n );\r\n // Bundle any resource files beside SKILL.md (relative path → contents).\r\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\r\n // (config-time validation already rejects these, but never trust input).\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n // Remove only the files we wrote (SKILL.md + declared resources), then the\r\n // skill dir itself when we own its full contents.\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue; // never delete outside the skill dir\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n // Only remove the skill dir when WE own its full contents — never rm -rf a\r\n // dir that still holds user-added / sibling-tool / shared files.\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n // ── Subagents ───────────────────────────────────────────────────────────────\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for cursor\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(\r\n this.subagentPath(ctx, agent.name),\r\n this.renderSubagent(agent),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /** Render a Cursor subagent to md+frontmatter (name, description, model, readonly) + prompt body. */\r\n private renderSubagent(agent: SubagentDef): string {\r\n const frontmatter: Record<string, unknown> = {\r\n name: agent.name,\r\n description: agent.description,\r\n };\r\n if (agent.model !== undefined) frontmatter.model = agent.model;\r\n if (agent.readonly !== undefined) frontmatter.readonly = agent.readonly;\r\n if (agent.extra) Object.assign(frontmatter, agent.extra);\r\n return this.renderFrontmatterMd(frontmatter, agent.prompt);\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const mcpPath = this.getServerConfigPath(ctx);\r\n const hooksPath = this.getHookConfigPath(ctx);\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: mcp.json present`,\r\n check: () =>\r\n existsSync(mcpPath)\r\n ? { status: \"OK\", detail: mcpPath }\r\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\r\n },\r\n {\r\n name: `${this.name}: hooks.json present`,\r\n check: () => {\r\n // Same \"only assert what the connector declares\" rule as the\r\n // content-surface checks below: a hookless connector never writes\r\n // hooks.json, so its absence is healthy, not a failure.\r\n if (ctx.connector.hookEvents.length === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n return existsSync(hooksPath)\r\n ? { status: \"OK\", detail: hooksPath }\r\n : { status: \"FAIL\", detail: `not found: ${hooksPath}` };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: only assert presence of the files this connector\r\n // declares (skip silently for surfaces it never asked for).\r\n for (const cmd of ctx.connector.commands) {\r\n const p = this.commandPath(ctx, cmd.name);\r\n checks.push({\r\n name: `${this.name}: command ${cmd.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse Cursor stdin JSON → normalized event ──────────────────\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as CursorWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n const sessionId = extractSessionId(input);\r\n const projectDir = this.getProjectDir(input);\r\n\r\n const base = {\r\n hostPlatform: HOST,\r\n connectorId,\r\n sessionId,\r\n raw,\r\n ...(projectDir !== undefined ? { projectDir } : {}),\r\n } as const;\r\n\r\n switch (event) {\r\n case \"PreToolUse\": {\r\n const ev: PreToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUse\": {\r\n const toolOutput = input.tool_output ?? input.error_message;\r\n const ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolOutput !== undefined ? { toolOutput } : {}),\r\n ...(input.error_message ? { isError: true } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n // Cursor's sessionStart stdin is exactly { session_id, is_background_agent,\r\n // composer_mode } — there is NO source/trigger start-source discriminator\r\n // (cursor.com/docs/hooks ~1278-1297). composer_mode is the editor MODE\r\n // (agent|ask|edit), a different concept from our normalized source enum\r\n // (startup|compact|resume|clear), so it does NOT map. With no discriminator\r\n // available, the normalized source stays at its 'startup' default (via\r\n // normalizeSessionSource(undefined)). is_background_agent / composer_mode\r\n // ride along on base.raw; there is no normalized field for either.\r\n const ev: SessionStartEvent = {\r\n ...base,\r\n source: normalizeSessionSource(undefined),\r\n };\r\n return ev;\r\n }\r\n case \"Stop\": {\r\n const ev: StopEvent = {\r\n ...base,\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionEnd\": {\r\n // Cursor sessionEnd: { session_id, reason, duration_ms, ... }. session_id\r\n // is already folded into base.sessionId via extractSessionId; only the\r\n // documented `reason` enum maps onto the normalized SessionEnd shape.\r\n const ev: SessionEndEvent = {\r\n ...base,\r\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"UserPromptSubmit\": {\r\n // Cursor beforeSubmitPrompt: { prompt, attachments }. attachments has no\r\n // normalized field and is preserved via base.raw; only `prompt` maps.\r\n const ev: UserPromptSubmitEvent = {\r\n ...base,\r\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PreCompact\": {\r\n // Cursor preCompact: { trigger: \"auto\"|\"manual\", context_*… }. Only the\r\n // documented `trigger` enum maps onto the normalized PreCompact shape.\r\n const ev: PreCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUseFailure\": {\r\n // Cursor's established error field is error_message; fall back to the\r\n // Claude-compatible `error` defensively.\r\n const error = input.error_message ?? input.error ?? \"\";\r\n const ev: PostToolUseFailureEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error,\r\n ...(typeof input.tool_use_id === \"string\"\r\n ? { toolUseId: input.tool_use_id }\r\n : {}),\r\n ...(typeof input.is_interrupt === \"boolean\"\r\n ? { isInterrupt: input.is_interrupt }\r\n : {}),\r\n // postToolUseFailure reports a BARE `duration` (ms), not `duration_ms`\r\n // (cursor.com/docs/hooks ~904,918). duration_ms only exists on\r\n // sessionEnd/subagentStop.\r\n ...(typeof input.duration === \"number\"\r\n ? { durationMs: input.duration }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStart\": {\r\n const agentId = input.agent_id ?? input.subagent_id;\r\n const agentType = input.agent_type ?? input.subagent_type;\r\n const ev: SubagentStartEvent = {\r\n ...base,\r\n ...(typeof agentId === \"string\" ? { agentId } : {}),\r\n ...(typeof agentType === \"string\" ? { agentType } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStop\": {\r\n const agentId = input.agent_id ?? input.subagent_id;\r\n const agentType = input.agent_type ?? input.subagent_type;\r\n const ev: SubagentStopEvent = {\r\n ...base,\r\n ...(typeof agentId === \"string\" ? { agentId } : {}),\r\n ...(typeof agentType === \"string\" ? { agentType } : {}),\r\n // Cursor's subagentStop carries the subagent's output text under\r\n // `summary`, NOT last_assistant_message (cursor.com/docs/hooks ~972,993).\r\n ...(typeof input.summary === \"string\"\r\n ? { lastAssistantMessage: input.summary }\r\n : {}),\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n default: {\r\n // Cursor never delivers Notification / PermissionRequest (no native\r\n // equivalent — permission is an OUTPUT field of its before* hooks, not\r\n // an event). If the runtime dispatches one anyway, fail loudly.\r\n throw new Error(`unsupported cursor hook event: ${String(event)}`);\r\n }\r\n }\r\n }\r\n\r\n private getProjectDir(input: CursorWireInput): string | undefined {\r\n return input.cwd ?? input.workspace_roots?.[0] ?? undefined;\r\n }\r\n\r\n // ── Runtime: normalized response → Cursor native hook reply ──────────────\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const decision = response.decision ?? \"allow\";\r\n\r\n // postToolUseFailure (feedback beside the error) and subagentStart (context\r\n // injected into the SUBAGENT's conversation) are observe/context-only on\r\n // Cursor: \"context\" emits additional_context, and a \"deny\" DEGRADES to the\r\n // same shape carrying the reason (the tool already failed / the spawn is\r\n // not blockable). Everything else is a minimal no-op payload (Cursor\r\n // rejects empty stdout as \"no valid response\").\r\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\r\n const context =\r\n decision === \"context\"\r\n ? response.additionalContext\r\n : decision === \"deny\"\r\n ? response.reason ?? response.additionalContext\r\n : undefined;\r\n return this.stdout({ additional_context: context ?? \"\" });\r\n }\r\n\r\n // beforeSubmitPrompt (UserPromptSubmit) is a BLOCK gate, not a permission/\r\n // context surface: its only documented output is { continue, user_message }\r\n // (cursor.com/docs/hooks). A \"deny\" prevents submission (continue:false +\r\n // reason); it cannot inject context (no additional_context/agent_message\r\n // field), so every non-deny decision is a no-op continue:true.\r\n if (event === \"UserPromptSubmit\") {\r\n if (decision === \"deny\") {\r\n return this.stdout({\r\n continue: false,\r\n user_message: response.reason ?? \"Blocked by hook\",\r\n });\r\n }\r\n return this.stdout({ continue: true });\r\n }\r\n\r\n // sessionEnd is fire-and-forget (the response is logged but not used) and\r\n // preCompact is observational (cannot block or modify compaction) per\r\n // cursor.com/docs/hooks — neither carries a decision Cursor honors, so both\r\n // are an unconditional no-op passthrough (mirrors Stop).\r\n if (event === \"SessionEnd\" || event === \"PreCompact\") {\r\n return { exitCode: 0 };\r\n }\r\n\r\n // deny → block the action with a user-facing message. (On SubagentStop\r\n // this follows the adapter's Stop idiom — the deny carries Stop semantics.)\r\n if (decision === \"deny\") {\r\n return this.stdout({\r\n permission: \"deny\",\r\n user_message: response.reason ?? \"Blocked by hook\",\r\n });\r\n }\r\n\r\n // ask → prompt the user to confirm.\r\n if (decision === \"ask\") {\r\n return this.stdout({\r\n permission: \"ask\",\r\n user_message: response.reason ?? \"Confirmation required by hook\",\r\n });\r\n }\r\n\r\n // modify → rewrite PreToolUse input (only where Cursor supports it).\r\n if (decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return this.stdout({ updated_input: response.updatedInput });\r\n }\r\n // Output rewrite is unsupported on Cursor; fall through to allow.\r\n }\r\n\r\n // context → inject soft guidance. PreToolUse uses `agent_message`; Post and\r\n // SessionStart use `additional_context`.\r\n if (decision === \"context\" && response.additionalContext) {\r\n return event === \"PreToolUse\"\r\n ? this.stdout({ agent_message: response.additionalContext })\r\n : this.stdout({ additional_context: response.additionalContext });\r\n }\r\n\r\n // SessionStart always emits valid JSON even on a no-op (Cursor rejects empty\r\n // stdout as \"no valid response\").\r\n if (event === \"SessionStart\") {\r\n return this.stdout({ additional_context: response.additionalContext ?? \"\" });\r\n }\r\n\r\n // allow / void → minimal no-op payload (Cursor rejects empty stdout).\r\n if (event === \"PreToolUse\") return this.stdout({ agent_message: \"\" });\r\n if (event === \"PostToolUse\") return this.stdout({ additional_context: \"\" });\r\n return { exitCode: 0 };\r\n }\r\n\r\n private stdout(payload: unknown): HookReply {\r\n return { exitCode: 0, stdout: JSON.stringify(payload) };\r\n }\r\n}\r\n\r\n/** Cursor native interpolation token: `${env:VAR}` → `${env:VAR}` (passthrough). */\r\nfunction cursorEnvToken(name: string): string {\r\n return `\\${env:${name}}`;\r\n}\r\n\r\nfunction extractSessionId(input: CursorWireInput): string {\r\n if (typeof input.conversation_id === \"string\") return input.conversation_id;\r\n if (typeof input.session_id === \"string\") return input.session_id;\r\n return \"\";\r\n}\r\n\r\nexport const adapter = new CursorAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry"]}
@@ -460,46 +460,48 @@ function renderInstallResult(result, verb) {
460
460
  return lines.join("\n");
461
461
  }
462
462
  var COMMANDS = {
463
- detect: () => import("./detect-6V4LC3MA.js"),
464
- install: () => import("./install-5NMCUDG5.js"),
465
- uninstall: () => import("./uninstall-AZEUPAND.js"),
463
+ detect: () => import("./detect-FKJC36P4.js"),
464
+ install: () => import("./install-HPDIK7F6.js"),
465
+ uninstall: () => import("./uninstall-DZVFV7KE.js"),
466
466
  // `upgrade` is the single "bring everything current" verb (re-render host
467
467
  // config + refresh the home pointer + managed channel guidance). `sync` and
468
468
  // `update` are kept as back-compat aliases that route to the same module so
469
469
  // existing scripts/docs keep working without a second concept to learn.
470
- upgrade: () => import("./upgrade-CAUUHSSC.js"),
471
- sync: () => import("./upgrade-CAUUHSSC.js"),
472
- update: () => import("./upgrade-CAUUHSSC.js"),
473
- package: () => import("./package-G25GVTH2.js"),
474
- doctor: () => import("./doctor-2YDUVSAU.js"),
475
- status: () => import("./status-VJAGO4Z7.js"),
476
- telemetry: () => import("./telemetry-OLZQBADT.js"),
477
- usage: () => import("./usage-3KHZ4RYZ.js"),
478
- leaderboard: () => import("./leaderboard-XEKS7B3H.js"),
479
- hook: () => import("./hook-OEVRDMXD.js"),
470
+ upgrade: () => import("./upgrade-OUE4ED52.js"),
471
+ sync: () => import("./upgrade-OUE4ED52.js"),
472
+ update: () => import("./upgrade-OUE4ED52.js"),
473
+ package: () => import("./package-TALOSRQ4.js"),
474
+ audit: () => import("./audit-2H7E3Z4N.js"),
475
+ doctor: () => import("./doctor-PGVYUQYG.js"),
476
+ status: () => import("./status-DVD4EHMX.js"),
477
+ telemetry: () => import("./telemetry-NWUJPIK3.js"),
478
+ usage: () => import("./usage-NT3ZXALZ.js"),
479
+ leaderboard: () => import("./leaderboard-KCT7XPCI.js"),
480
+ hook: () => import("./hook-PVGBQUQI.js"),
480
481
  // Internal (omitted from USAGE): the statusline (HUD) entrypoint a host's
481
482
  // status line config points at. Fail-safe: always exits 0 with at most a
482
483
  // rendered line. See cli/commands/statusline.ts.
483
- statusline: () => import("./statusline-EY2E2UGF.js"),
484
+ statusline: () => import("./statusline-ZVNH7XBK.js"),
484
485
  // Internal (omitted from USAGE): the user-invokable action entrypoint a future
485
486
  // host affordance points at. USER-TRIGGERED: surfaces errors (exit 1 + stderr),
486
487
  // unlike the fail-open hook / fail-safe statusline. See cli/commands/action.ts.
487
- action: () => import("./action-Q7GGO4PA.js"),
488
- serve: () => import("./serve-XTMIUHKK.js"),
488
+ action: () => import("./action-5JM23CFJ.js"),
489
+ serve: () => import("./serve-4TEHK726.js"),
489
490
  // Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an
490
491
  // AfterModel / PostInvocation hook points at. Always exits 0; records a
491
492
  // distinct `model_turn` row. See cli/commands/usage-event.ts.
492
- "usage-event": () => import("./usage-event-TZWOZPRJ.js")
493
+ "usage-event": () => import("./usage-event-IELZE6WO.js")
493
494
  };
494
495
  var DEFAULT_PROGRAM_NAME = "agent-connector";
495
496
  var COMMAND_USAGE = {
496
497
  detect: "detect [--json] [--project <dir>]",
497
- install: "install [<source>] [--method direct|marketplace] [--connector <source>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force] [--quiet]\n <source> a local path OR a remote GitHub connector: owner/repo[/subpath][#ref], a github.com URL (incl. /tree/<ref>/<sub>), git@github.com:owner/repo, or github:owner/repo. Remote sources are fetched to ~/.agent-connector/sources/ and must be an agent-connector package (have an agent-connector.config.{mjs,js,json}).",
498
+ install: "install [<source>] [--method direct|marketplace] [--connector <source>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force] [--quiet]\n <source> a local path OR a remote connector source: owner/repo[/subpath][#ref], a github.com URL (incl. /tree/<ref>/<sub>), git@github.com:owner/repo, github:owner/repo, npm:<package>[@version], archive:<path-or-url>, or a direct .tgz/.tar.gz URL/path. Remote sources are fetched to ~/.agent-connector/sources/ and must be an agent-connector package (have an agent-connector.config.{mjs,js,json}).",
498
499
  uninstall: "uninstall [--method auto|direct|marketplace] [--connector <path>] [--connector-id <id>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--purge] [--quiet]",
499
500
  upgrade: "upgrade [--method direct|marketplace] [--channel stable|latest] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--quiet]",
500
501
  sync: "sync \u2014 alias of upgrade (see `upgrade --help`)",
501
502
  update: "update \u2014 alias of upgrade (see `upgrade --help`)",
502
503
  package: "package [--connector <path>] [--format <fmt>|all] [--out <dir>] [--project <dir>] [--dry-run]",
504
+ audit: "audit [--connector <path>] [--package-json <path>] [--project <dir>] [--json] [--strict]",
503
505
  doctor: "doctor [--targets a,b] [--connector <path>] [--scope user|project] [--project <dir>] [--probe] [--explain] [--json] [--heal] [--dry-run] [--quiet]\n --explain per-(host,event) hook honor matrix (honored/degraded/dropped). Exit non-zero ONLY when an explicitly-targeted host DEGRADES a declared event (fires it but silently won't honor the reply); dropped/mcp-only hosts and fleet-wide (targets:auto) gaps are informational (exit 0).",
504
506
  status: "status [--connector <path>] [--scope user|project] [--project <dir>] [--json]",
505
507
  telemetry: "telemetry report|export|leaderboard [--by <dim>] [--since <dur>] [--connector <id>] [--scope <slice>] [--format csv|json] [--out <file>] [--json]",
@@ -521,6 +523,7 @@ commands:
521
523
  uninstall Remove a connector's registrations (--method auto reverses whichever method is actually installed).
522
524
  upgrade Bring everything current: re-render host config + heal the home pointer + managed update guidance (alias: update, sync).
523
525
  package Emit a marketplace/extension bundle (10 host formats, or the standard artifacts mcp-server-json | mcpb).
526
+ audit Check branded package identity before install/publish.
524
527
  doctor Health-check every detected platform; non-zero exit on any failure.
525
528
  status Light install-state summary: which connectors are present on which hosts (always exits 0).
526
529
  telemetry Inspect local per-tool token telemetry (report | export | leaderboard).
@@ -587,4 +590,4 @@ export {
587
590
  renderInstallResult,
588
591
  main
589
592
  };
590
- //# sourceMappingURL=chunk-H33M77DD.js.map
593
+ //# sourceMappingURL=chunk-HATCOSQT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/app.ts","../src/cli/banner.ts"],"sourcesContent":["/**\r\n * cli/app — shared CLI helpers + command dispatch (NO side effects).\r\n *\r\n * Command modules import the shared helpers (print, fail, parse-flags,\r\n * renderInstallResult) from here, and main() dispatches the first positional to a\r\n * command module.\r\n * This module never auto-runs — `cli/index.ts` is the thin bin entry that calls\r\n * `main()`. Keeping the auto-run out of here is what prevents a dispatch recursion\r\n * (a command module importing a helper must not re-trigger the program) and makes\r\n * it robust to bundler entry-splitting (the old import.meta.url entry-guard broke\r\n * once tsup hoisted this code into a shared chunk).\r\n */\r\n\r\nimport { createRequire } from \"node:module\";\r\nimport { homedir } from \"node:os\";\r\n\r\nimport { PALETTES, renderBrandBanner, resolveColorMode, shouldShowBanner } from \"./banner.js\";\r\nimport type {\r\n ChangeRecord,\r\n ConnectorSummary,\r\n InstallResult,\r\n InstallScope,\r\n PlatformId,\r\n ResolvedConnector,\r\n} from \"../core/types.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Shared helpers (imported by the command modules)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Print a line to stdout (machine-readable payloads must stay on stdout). */\r\nexport function print(line: string): void {\r\n process.stdout.write(`${line}\\n`);\r\n}\r\n\r\n/**\r\n * The brand active for THIS invocation. main() sets it from\r\n * {@link MainOptions.programName} before dispatch, so error messages printed by\r\n * command modules via {@link fail} read as the embedding tool (e.g. `acme-db:`)\r\n * instead of always `agent-connector:`.\r\n */\r\nlet activeProgramName = \"agent-connector\";\r\n\r\n/** Print an error to stderr (branded) and return a non-zero exit code (default 2). */\r\nexport function fail(message: string, code = 2): number {\r\n process.stderr.write(`${activeProgramName}: ${message}\\n`);\r\n return code;\r\n}\r\n\r\n/**\r\n * The brand active for THIS invocation (what the banner renders in ASCII art).\r\n * main() sets it from {@link MainOptions.programName} before dispatch; reading it\r\n * here keeps the banner branded for an embedding SDK CLI without each command\r\n * module needing the program name threaded through.\r\n */\r\nexport function getActiveProgramName(): string {\r\n return activeProgramName;\r\n}\r\n\r\n/**\r\n * Print the branded ASCII banner once, atop install / uninstall / upgrade /\r\n * doctor — but ONLY for an interactive TTY (suppressed when piped/redirected,\r\n * under --json, or under --quiet) so scripts and pipelines see byte-identical\r\n * command output. The pure render lives in cli/banner; this thin wrapper reads\r\n * the real stdout/env and feeds it in.\r\n */\r\nexport function maybePrintBanner(flags: { json?: boolean; quiet?: boolean }): void {\r\n const isTTY = process.stdout.isTTY === true;\r\n const noColor = process.env.NO_COLOR != null && process.env.NO_COLOR !== \"\";\r\n if (!shouldShowBanner({ isTTY, noColor, json: flags.json === true, quiet: flags.quiet === true })) {\r\n return;\r\n }\r\n const color = resolveColorMode({\r\n noColor,\r\n colorterm: process.env.COLORTERM,\r\n term: process.env.TERM,\r\n });\r\n // Coerce an unknown/zero width to a conservative 80 so an unknown-width TTY\r\n // shows the safe one-line title rather than the 129-col block art.\r\n const c = process.stdout.columns;\r\n const columns = typeof c === \"number\" && c > 0 ? c : 80;\r\n // Rotate the gradient per run so each real invocation reads differently. The\r\n // random pick lives HERE (the impure wrapper) so the pure renderer stays\r\n // deterministic for tests/direct callers.\r\n const palette = PALETTES[Math.floor(Math.random() * PALETTES.length)]!;\r\n print(renderBrandBanner(activeProgramName, { color, columns, palette }));\r\n print(\"\");\r\n}\r\n\r\n/**\r\n * Resolve agent-connector's own package version at runtime. Works from both the\r\n * bundled dist layout (dist/*.js → ../package.json) and the src layout under\r\n * tsx/vitest (src/cli/ → ../../package.json); the name check guards against\r\n * accidentally reading some other package.json on the walk.\r\n */\r\nexport function resolveOwnVersion(): string {\r\n const req = createRequire(import.meta.url);\r\n for (const rel of [\"../package.json\", \"../../package.json\", \"../../../package.json\"]) {\r\n try {\r\n const pkg = req(rel) as { name?: string; version?: string };\r\n if (pkg.name === \"@ken-jo/agent-connector\" && typeof pkg.version === \"string\") {\r\n return pkg.version;\r\n }\r\n } catch {\r\n /* keep walking */\r\n }\r\n }\r\n return \"0.0.0\";\r\n}\r\n\r\n/** Parse a --scope value the CLI accepts (user|project) into an InstallScope. */\r\nexport function parseScope(value: string | undefined): InstallScope | null {\r\n if (value === \"user\" || value === \"project\") return value;\r\n return null;\r\n}\r\n\r\n/**\r\n * Parse a comma-separated --targets value into PlatformId[]. Returns undefined\r\n * when the flag is absent/empty so callers can fall back to connector/detection.\r\n */\r\nexport function parseTargets(value: string | undefined): PlatformId[] | undefined {\r\n if (value == null || value.trim() === \"\") return undefined;\r\n const ids = value\r\n .split(\",\")\r\n .map((s) => s.trim())\r\n .filter((s) => s !== \"\") as PlatformId[];\r\n return ids.length > 0 ? ids : undefined;\r\n}\r\n\r\n/**\r\n * Build the render-only {@link ConnectorSummary} from a resolved connector. The\r\n * command modules call this on the {@link ResolvedConnector} they already loaded\r\n * and attach the result to {@link InstallResult.connector}, so the friendly\r\n * renderer can print a header describing WHAT was deployed without importing the\r\n * heavyweight connector type or its live handlers.\r\n */\r\nexport function buildConnectorSummary(connector: ResolvedConnector): ConnectorSummary {\r\n let server: ConnectorSummary[\"server\"];\r\n if (connector.server) {\r\n const s = connector.server;\r\n // stdio → \"node server.mjs\"; remote → the URL (best-effort one-liner).\r\n // HOME-relativize each part so a bundled absolute server path reads short.\r\n const cmd =\r\n s.transport === \"stdio\"\r\n ? [s.command, ...(s.args ?? [])]\r\n .filter((p): p is string => p != null && p !== \"\")\r\n .map((p) => tildify(p))\r\n .join(\" \")\r\n : (s.url ?? \"\");\r\n server = { transport: s.transport, command: cmd };\r\n }\r\n return {\r\n id: connector.id,\r\n version: connector.version,\r\n displayName: connector.displayName,\r\n server,\r\n hookEvents: [...connector.hookEvents],\r\n telemetryEnabled: connector.telemetry.enabled,\r\n commands: connector.commands.length,\r\n skills: connector.skills.length,\r\n subagents: connector.subagents.length,\r\n memory: connector.memory.length,\r\n hasStatusline: connector.statusline != null,\r\n actions: connector.actions.length,\r\n };\r\n}\r\n\r\n/**\r\n * Rewrite an absolute path under the user's home dir to a leading `~/…` so the\r\n * per-host paths read short. Leaves non-home and relative paths untouched.\r\n */\r\nfunction tildify(path: string): string {\r\n // Normalize both to forward slashes so the home-prefix check is separator-\r\n // robust (Windows mixes `\\` and `/`) and the displayed path reads `~/…`\r\n // consistently on every platform (Windows terminals accept `/` fine).\r\n const home = homedir().replace(/\\\\/g, \"/\");\r\n const np = path.replace(/\\\\/g, \"/\");\r\n if (home && (np === home || np.startsWith(home + \"/\"))) {\r\n return \"~\" + np.slice(home.length);\r\n }\r\n return np;\r\n}\r\n\r\n/** Truncate a long single-line command for the header (keeps it scannable). */\r\nfunction truncateCommand(cmd: string, max = 64): string {\r\n if (cmd.length <= max) return cmd;\r\n return cmd.slice(0, max - 1) + \"…\";\r\n}\r\n\r\n/**\r\n * The surface a ChangeRecord touched, derived from its detail (primary signal)\r\n * then its path (fallback for content files whose detail is a bare basename).\r\n */\r\ntype Surface = \"mcp\" | \"hooks\" | \"commands\" | \"skills\" | \"subagents\" | \"memory\" | \"statusline\" | \"actions\" | \"backup\" | \"other\";\r\n\r\nfunction classifySurface(c: ChangeRecord): Surface {\r\n const detail = c.detail.toLowerCase();\r\n // A safety backup the installer wrote before a destructive change.\r\n if (detail.startsWith(\"backed up\") || detail.includes(\"backup\")) return \"backup\";\r\n // MCP server entry: mcpServers.<id> / mcp_servers.<id> / mcp.servers.<id>.\r\n if (/^mcp[._]?servers?\\./.test(detail) || detail.startsWith(\"mcp.\")) return \"mcp\";\r\n // Normalized + native hook entries: hooks.<Event> (case varies per host).\r\n if (detail.startsWith(\"hooks.\") || detail.startsWith(\"hook \")) return \"hooks\";\r\n if (detail.includes(\"nativehooks\")) return \"hooks\";\r\n if (detail.startsWith(\"memory\")) return \"memory\";\r\n if (detail.startsWith(\"statusline\")) return \"statusline\";\r\n if (detail.startsWith(\"actions\") || detail.startsWith(\"action \")) return \"actions\";\r\n if (detail.includes(\"configpatch\")) return \"other\";\r\n // Path-based fallback for content-file surfaces (detail is a bare basename).\r\n const p = (c.path ?? \"\").replace(/\\\\/g, \"/\").toLowerCase();\r\n if (/\\/commands?\\//.test(p)) return \"commands\";\r\n if (/\\/skills?\\//.test(p)) return \"skills\";\r\n if (/\\/(subagents?|agents?)\\//.test(p)) return \"subagents\";\r\n // Detail mentions a surface noun (skip/warn lines like \"no skills\").\r\n if (/\\bcommands?\\b/.test(detail)) return \"commands\";\r\n if (/\\bskills?\\b/.test(detail)) return \"skills\";\r\n if (/\\bsubagents?\\b/.test(detail)) return \"subagents\";\r\n return \"other\";\r\n}\r\n\r\nconst SURFACE_LABEL_SINGULAR: Record<Surface, string> = {\r\n mcp: \"MCP server\",\r\n hooks: \"hook\",\r\n commands: \"command\",\r\n skills: \"skill\",\r\n subagents: \"subagent\",\r\n memory: \"memory block\",\r\n statusline: \"status line\",\r\n actions: \"action\",\r\n backup: \"backup\",\r\n other: \"change\",\r\n};\r\n\r\n/** Pluralize a surface count, e.g. (2,\"hooks\") → \"2 hooks\". */\r\nfunction countLabel(n: number, surface: Surface): string {\r\n const base = SURFACE_LABEL_SINGULAR[surface];\r\n if (surface === \"mcp\") return \"MCP server\"; // singular by construction\r\n return n === 1 ? `1 ${base}` : `${n} ${base}s`;\r\n}\r\n\r\n/** Verb-appropriate glyph for a host's NET status. */\r\nfunction hostGlyph(status: \"ok\" | \"skip\" | \"warn\"): string {\r\n return status === \"warn\" ? \"!\" : status === \"skip\" ? \"=\" : \"✓\";\r\n}\r\n\r\n/**\r\n * One host's collapsed view: its net status, a surface summary line, the\r\n * deduped HOME-relativized paths it touched, and any inline warnings.\r\n */\r\ninterface HostGroup {\r\n platform: PlatformId;\r\n status: \"ok\" | \"skip\" | \"warn\";\r\n summary: string;\r\n paths: string[];\r\n warnings: string[];\r\n}\r\n\r\n/**\r\n * Collapse the per-(host,surface) ChangeRecords into ONE entry per host:\r\n * - status: warn if any record warned; ok if any created/updated/removed;\r\n * else skip (everything was a no-op).\r\n * - summary: the active (non-skip) surfaces, joined (\"MCP server + 2 hooks\").\r\n * When every record skipped, the reason is surfaced instead.\r\n */\r\nfunction groupByHost(changes: ChangeRecord[], verb: Verb): HostGroup[] {\r\n const order: PlatformId[] = [];\r\n const byHost = new Map<PlatformId, ChangeRecord[]>();\r\n for (const c of changes) {\r\n if (!byHost.has(c.platform)) {\r\n byHost.set(c.platform, []);\r\n order.push(c.platform);\r\n }\r\n byHost.get(c.platform)!.push(c);\r\n }\r\n\r\n const groups: HostGroup[] = [];\r\n for (const platform of order) {\r\n const recs = byHost.get(platform)!;\r\n // A safety backup the installer wrote is INCIDENTAL, not an installed\r\n // surface: it must not flip an otherwise-no-op host to \"changed\" (an\r\n // idempotent re-install that only re-backs-up should still read \"already\r\n // current\"). It is shown only ALONGSIDE a real surface change.\r\n const written = recs.filter((c) => c.action !== \"skip\" && c.action !== \"warn\");\r\n const realChanges = written.filter((c) => classifySurface(c) !== \"backup\");\r\n const warned = recs.filter((c) => c.action === \"warn\");\r\n const status: HostGroup[\"status\"] =\r\n warned.length > 0 ? \"warn\" : realChanges.length > 0 ? \"ok\" : \"skip\";\r\n\r\n // Surface summary from the written records (created/updated/removed),\r\n // preserving a stable surface order and collapsing per-surface counts. The\r\n // incidental `backup` surface is included ONLY when a real surface changed.\r\n const SURFACE_ORDER: Surface[] = [\r\n \"mcp\",\r\n \"hooks\",\r\n \"commands\",\r\n \"skills\",\r\n \"subagents\",\r\n \"memory\",\r\n \"statusline\",\r\n \"actions\",\r\n \"backup\",\r\n \"other\",\r\n ];\r\n const counts = new Map<Surface, number>();\r\n const summarySource = realChanges.length > 0 ? written : realChanges;\r\n for (const c of summarySource) {\r\n const s = classifySurface(c);\r\n counts.set(s, (counts.get(s) ?? 0) + 1);\r\n }\r\n const parts = SURFACE_ORDER.filter((s) => counts.has(s)).map((s) =>\r\n countLabel(counts.get(s)!, s),\r\n );\r\n\r\n let summary: string;\r\n if (parts.length > 0) {\r\n summary = parts.join(\" + \");\r\n } else if (status === \"warn\") {\r\n // No real surface change but a warning — the warning line carries detail.\r\n summary = \"\";\r\n } else {\r\n // Nothing real changed: surface a skip reason (or note the incidental\r\n // backup) for context.\r\n const reason =\r\n recs.find((c) => c.action === \"skip\")?.detail ??\r\n (written.length > 0 ? \"already current (re-backed-up only)\" : \"no changes\");\r\n summary = verb === \"uninstall\" ? `nothing to remove (${reason})` : `unchanged (${reason})`;\r\n }\r\n\r\n const paths = [\r\n ...new Set(\r\n recs\r\n .filter((c) => c.path != null && c.path !== \"\")\r\n .map((c) => tildify(c.path!)),\r\n ),\r\n ];\r\n const warnings = warned.map((c) => c.detail);\r\n\r\n groups.push({ platform, status, summary, paths, warnings });\r\n }\r\n return groups;\r\n}\r\n\r\ntype Verb = \"install\" | \"upgrade\" | \"uninstall\";\r\n\r\n/**\r\n * Render an InstallResult as a friendly, grouped report (the DEFAULT output):\r\n * 1. a connector header (id/version/displayName + server/hooks/telemetry +\r\n * one line per shipped content surface), when the summary is threaded in;\r\n * 2. one line per host (net glyph + surface summary + deduped ~/… paths),\r\n * with any host warnings inline beneath it;\r\n * 3. a friendly closing line + restart hint + doctor/uninstall next steps.\r\n *\r\n * Used by install / upgrade / uninstall. The exit-non-zero-on-warn convention\r\n * is enforced by the callers (this function only renders).\r\n */\r\nexport function renderInstallResult(result: InstallResult, verb: Verb): string {\r\n const lines: string[] = [];\r\n const summary = result.connector;\r\n\r\n // ── 1. Connector header ───────────────────────────────────────────────────\r\n if (summary) {\r\n const head = [`${summary.id} v${summary.version}`];\r\n if (summary.displayName && summary.displayName !== summary.id) {\r\n head.push(summary.displayName);\r\n }\r\n lines.push(head.join(\" · \"));\r\n\r\n if (summary.server) {\r\n lines.push(\r\n ` server ${summary.server.transport} · ${truncateCommand(summary.server.command)}`,\r\n );\r\n } else {\r\n lines.push(\" server (hooks-only)\");\r\n }\r\n if (summary.hookEvents.length > 0) {\r\n lines.push(` hooks ${summary.hookEvents.join(\", \")}`);\r\n }\r\n lines.push(` telemetry ${summary.telemetryEnabled ? \"on\" : \"off\"}`);\r\n if (summary.commands > 0)\r\n lines.push(` commands ${summary.commands}`);\r\n if (summary.skills > 0) lines.push(` skills ${summary.skills}`);\r\n if (summary.subagents > 0)\r\n lines.push(` subagents ${summary.subagents}`);\r\n if (summary.memory > 0) lines.push(` memory ${summary.memory}`);\r\n if (summary.hasStatusline) lines.push(` statusline 1`);\r\n if (summary.actions > 0) lines.push(` actions ${summary.actions}`);\r\n lines.push(\"\");\r\n } else {\r\n // No summary threaded (back-compat): keep a minimal verb header.\r\n const mode = result.dryRun ? \" (dry-run — nothing written)\" : \"\";\r\n lines.push(`${verb} \"${result.connectorId}\"${mode}`);\r\n }\r\n\r\n // ── 2. Per-host grouping ──────────────────────────────────────────────────\r\n const groups = groupByHost(result.changes, verb);\r\n if (groups.length === 0) {\r\n lines.push(\"(no changes)\");\r\n } else {\r\n const verbed = verb === \"uninstall\" ? \"removed from\" : verb === \"upgrade\" ? \"synced to\" : \"detected\";\r\n lines.push(`→ ${groups.length} agent ${groups.length === 1 ? \"CLI\" : \"CLIs\"} ${verbed}:`);\r\n // Width-align the platform column for a scannable table; the summary column\r\n // gets a fixed min width but always keeps a 2-space gap before the paths\r\n // even when an unusually long summary overflows it.\r\n const pad = Math.max(...groups.map((g) => g.platform.length));\r\n for (const g of groups) {\r\n const glyph = hostGlyph(g.status);\r\n const name = g.platform.padEnd(pad);\r\n const pathsCol = g.paths.join(\", \");\r\n const gap = pathsCol === \"\" ? \"\" : \" \";\r\n const summaryCol = pathsCol === \"\" ? g.summary : g.summary.padEnd(26) + gap;\r\n lines.push(` ${glyph} ${name} ${summaryCol}${pathsCol}`.trimEnd());\r\n for (const w of g.warnings) lines.push(` ! ${w}`);\r\n }\r\n }\r\n\r\n // ── 3. Closing summary + next steps ───────────────────────────────────────\r\n // The headline file tally counts only REAL surface writes — an incidental\r\n // safety backup must not masquerade as an installed file, so a re-install\r\n // whose only write was a backup honestly reports 0 files / \"already current\".\r\n const tally = result.changes.reduce(\r\n (acc, c) => {\r\n const isWrite = c.action === \"create\" || c.action === \"update\" || c.action === \"remove\";\r\n if (isWrite && classifySurface(c) !== \"backup\") acc.files += 1;\r\n if (c.action === \"warn\") acc.warns += 1;\r\n return acc;\r\n },\r\n { files: 0, warns: 0 },\r\n );\r\n const cliCount = groups.length;\r\n const cliWord = cliCount === 1 ? \"CLI\" : \"CLIs\";\r\n const fileWord = tally.files === 1 ? \"file\" : \"files\";\r\n\r\n lines.push(\"\");\r\n if (verb === \"uninstall\") {\r\n if (result.dryRun) {\r\n lines.push(`✓ Would remove ${summary?.id ?? result.connectorId} from ${cliCount} ${cliWord} · ${tally.files} ${fileWord} (dry-run — nothing written).`);\r\n } else if (tally.files === 0 && tally.warns === 0) {\r\n lines.push(`✓ Nothing to remove — ${summary?.id ?? result.connectorId} was not installed (zero residue).`);\r\n } else {\r\n lines.push(`✓ Removed ${summary?.id ?? result.connectorId} from ${cliCount} ${cliWord} · ${tally.files} ${fileWord} cleaned${tally.warns === 0 ? \" (zero residue)\" : \"\"}.`);\r\n }\r\n } else {\r\n const what = verb === \"upgrade\" ? \"Synced\" : \"Installed\";\r\n const wouldWhat = verb === \"upgrade\" ? \"sync\" : \"install\";\r\n if (result.dryRun) {\r\n lines.push(`✓ Would ${wouldWhat} ${summary?.id ?? result.connectorId} to ${cliCount} ${cliWord} · ${tally.files} ${fileWord} (dry-run — nothing written).`);\r\n } else if (tally.files === 0) {\r\n lines.push(`✓ ${summary?.id ?? result.connectorId}: already current on ${cliCount} ${cliWord} — nothing to write.`);\r\n } else {\r\n lines.push(`✓ ${what} ${summary?.id ?? result.connectorId} to ${cliCount} ${cliWord} · ${tally.files} ${fileWord}. Restart each CLI to load it.`);\r\n }\r\n }\r\n\r\n // Warnings block (kept explicit — callers exit non-zero on any warn). A\r\n // remote-transport connector pushes the SAME string to both a warn\r\n // ChangeRecord (already shown inline on its host line) and result.warnings, so\r\n // skip any bottom-block entry already surfaced inline to show each warning ONCE.\r\n const inlineWarnings = new Set(groups.flatMap((g) => g.warnings));\r\n const blockWarnings = result.warnings.filter((w) => !inlineWarnings.has(w));\r\n if (blockWarnings.length > 0) {\r\n lines.push(\"\");\r\n lines.push(\"warnings:\");\r\n for (const w of blockWarnings) lines.push(` ! ${w}`);\r\n }\r\n\r\n // Next-step hints (the verbs read as the active brand).\r\n if (verb === \"uninstall\") {\r\n lines.push(` Verify it's gone: ${activeProgramName} doctor`);\r\n } else {\r\n lines.push(\r\n ` Verify: ${activeProgramName} doctor · Remove: ${activeProgramName} uninstall`,\r\n );\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Command dispatch\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** A command module: takes the post-command argv slice, returns an exit code. */\r\ntype CommandModule = { run: (argv: string[]) => Promise<number> | number };\r\n\r\n/** Lazy command loaders — keyed by the first positional. Imported on demand. */\r\nconst COMMANDS: Record<string, () => Promise<CommandModule>> = {\r\n detect: () => import(\"./commands/detect.js\"),\r\n install: () => import(\"./commands/install.js\"),\r\n uninstall: () => import(\"./commands/uninstall.js\"),\r\n // `upgrade` is the single \"bring everything current\" verb (re-render host\r\n // config + refresh the home pointer + managed channel guidance). `sync` and\r\n // `update` are kept as back-compat aliases that route to the same module so\r\n // existing scripts/docs keep working without a second concept to learn.\r\n upgrade: () => import(\"./commands/upgrade.js\"),\r\n sync: () => import(\"./commands/upgrade.js\"),\r\n update: () => import(\"./commands/upgrade.js\"),\r\n package: () => import(\"./commands/package.js\"),\n audit: () => import(\"./commands/audit.js\"),\n doctor: () => import(\"./commands/doctor.js\"),\n status: () => import(\"./commands/status.js\"),\r\n telemetry: () => import(\"./commands/telemetry.js\"),\r\n usage: () => import(\"./commands/usage.js\"),\r\n leaderboard: () => import(\"./commands/leaderboard.js\"),\r\n hook: () => import(\"./commands/hook.js\"),\r\n // Internal (omitted from USAGE): the statusline (HUD) entrypoint a host's\r\n // status line config points at. Fail-safe: always exits 0 with at most a\r\n // rendered line. See cli/commands/statusline.ts.\r\n statusline: () => import(\"./commands/statusline.js\"),\r\n // Internal (omitted from USAGE): the user-invokable action entrypoint a future\r\n // host affordance points at. USER-TRIGGERED: surfaces errors (exit 1 + stderr),\r\n // unlike the fail-open hook / fail-safe statusline. See cli/commands/action.ts.\r\n action: () => import(\"./commands/action.js\"),\r\n serve: () => import(\"./commands/serve.js\"),\r\n // Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an\r\n // AfterModel / PostInvocation hook points at. Always exits 0; records a\r\n // distinct `model_turn` row. See cli/commands/usage-event.ts.\r\n \"usage-event\": () => import(\"./commands/usage-event.js\"),\r\n};\r\n\r\n/** Default program name; an embedding SDK CLI overrides it via {@link MainOptions}. */\r\nexport const DEFAULT_PROGRAM_NAME = \"agent-connector\";\r\n\r\n/**\r\n * One-line usage signature per command — the single central copy behind\r\n * `<command> --help` and the friendly bad-flag error. Command modules use\r\n * node:util parseArgs (strict), which THROWS on an unknown flag; without the\r\n * dispatcher-level handling in {@link main}, `agent-connector install --help`\r\n * would die with a raw ERR_PARSE_ARGS stack trace — the very invocation the\r\n * root help tells users to run.\r\n */\r\nconst COMMAND_USAGE: Record<string, string> = {\r\n detect: \"detect [--json] [--project <dir>]\",\r\n install:\n \"install [<source>] [--method direct|marketplace] [--connector <source>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--force] [--quiet]\\n\" +\n \" <source> a local path OR a remote connector source: owner/repo[/subpath][#ref], a github.com URL (incl. /tree/<ref>/<sub>), git@github.com:owner/repo, github:owner/repo, npm:<package>[@version], archive:<path-or-url>, or a direct .tgz/.tar.gz URL/path. Remote sources are fetched to ~/.agent-connector/sources/ and must be an agent-connector package (have an agent-connector.config.{mjs,js,json}).\",\n uninstall:\r\n \"uninstall [--method auto|direct|marketplace] [--connector <path>] [--connector-id <id>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--purge] [--quiet]\",\r\n upgrade:\r\n \"upgrade [--method direct|marketplace] [--channel stable|latest] [--connector <path>] [--scope user|project] [--targets a,b] [--project <dir>] [--dry-run] [--quiet]\",\r\n sync: \"sync — alias of upgrade (see `upgrade --help`)\",\r\n update: \"update — alias of upgrade (see `upgrade --help`)\",\r\n package:\n \"package [--connector <path>] [--format <fmt>|all] [--out <dir>] [--project <dir>] [--dry-run]\",\n audit:\n \"audit [--connector <path>] [--package-json <path>] [--project <dir>] [--json] [--strict]\",\n doctor:\n \"doctor [--targets a,b] [--connector <path>] [--scope user|project] [--project <dir>] [--probe] [--explain] [--json] [--heal] [--dry-run] [--quiet]\\n\" +\r\n \" --explain per-(host,event) hook honor matrix (honored/degraded/dropped). Exit non-zero ONLY when an explicitly-targeted host DEGRADES a declared event (fires it but silently won't honor the reply); dropped/mcp-only hosts and fleet-wide (targets:auto) gaps are informational (exit 0).\",\r\n status: \"status [--connector <path>] [--scope user|project] [--project <dir>] [--json]\",\r\n telemetry:\r\n \"telemetry report|export|leaderboard [--by <dim>] [--since <dur>] [--connector <id>] [--scope <slice>] [--format csv|json] [--out <file>] [--json]\",\r\n usage:\r\n \"usage report|export|leaderboard [--by <dim>] [--since <dur>] [--platform <id>] [--format csv|json] [--out <file>] [--json]\",\r\n leaderboard: \"leaderboard [--since <dur>] [--connector <id>] [--scope <slice>] [--json]\",\r\n hook: \"hook <platform> <event> --connector <id> (internal — host hook configs point here)\",\r\n statusline:\r\n \"statusline <platform> --connector <id> (internal — host status line configs point here)\",\r\n action:\r\n \"action <platform> <actionId> --connector <id> (internal — host action affordances point here)\",\r\n serve:\r\n \"serve --connector <id> [--scope user|project] [--host <platformId>] -- <command> [args...] (internal — host MCP entries point here)\",\r\n};\r\n\r\n/**\r\n * Build the top-level usage string for a given program name. The brand replaces\r\n * \"agent-connector\" in the title, the `usage:` line, and the per-command help\r\n * footer so an embedded CLI (e.g. `acme-db`) reads as its own tool.\r\n */\r\nfunction buildUsage(programName: string): string {\r\n return `${programName} — write your MCP server + hooks once, install everywhere.\r\n\r\nusage: ${programName} <command> [flags]\r\n\r\ncommands:\r\n detect List the AI-agent platforms installed on this machine.\r\n install Deploy a connector across its target platforms (--method direct writes host config; --method marketplace drives the host's plugin install).\r\n uninstall Remove a connector's registrations (--method auto reverses whichever method is actually installed).\r\n upgrade Bring everything current: re-render host config + heal the home pointer + managed update guidance (alias: update, sync).\n package Emit a marketplace/extension bundle (10 host formats, or the standard artifacts mcp-server-json | mcpb).\n audit Check branded package identity before install/publish.\n doctor Health-check every detected platform; non-zero exit on any failure.\n status Light install-state summary: which connectors are present on which hosts (always exits 0).\r\n telemetry Inspect local per-tool token telemetry (report | export | leaderboard).\r\n usage Inspect host-native token usage from agent CLI logs (report | export | leaderboard).\r\n leaderboard Three leaderboards: 🔌 MCP/plugin (mcp-self) + 🖥️ host/user (host-scan-logs) + 🛰️ host-native turns (host-native-live) — never summed.\r\n hook Universal json-stdio hook entrypoint (hosts call this).\r\n serve Telemetry-wrapping MCP stdio proxy (wraps a real server command).\r\n\r\nRun \\`${programName} <command> --help\\` for command-specific flags.`;\r\n}\r\n\r\n/** Options accepted by {@link main}. */\r\nexport interface MainOptions {\r\n /**\r\n * The brand shown in usage/help text. Defaults to {@link DEFAULT_PROGRAM_NAME}.\r\n * An embedding SDK CLI (see cli/sdk.ts) passes its own bin name so every\r\n * subcommand's help reads as the developer's tool.\r\n */\r\n programName?: string;\r\n /**\r\n * Version shown by --version. Defaults to agent-connector's own package version.\r\n * Embedded branded CLIs pass their package.json version.\r\n */\r\n programVersion?: string;\r\n}\r\n\r\nexport async function main(argv: string[], opts: MainOptions = {}): Promise<number> {\r\n const programName = opts.programName ?? DEFAULT_PROGRAM_NAME;\r\n activeProgramName = programName; // brand every fail() in this invocation\r\n const usage = buildUsage(programName);\r\n const command = argv[0];\r\n\r\n if (command == null || command === \"--help\" || command === \"-h\" || command === \"help\") {\r\n print(usage);\r\n return command == null ? 1 : 0;\r\n }\r\n if (command === \"--version\" || command === \"-v\") {\r\n print(`${programName} ${opts.programVersion ?? resolveOwnVersion()}`);\r\n return 0;\r\n }\r\n\r\n const loader = COMMANDS[command];\r\n if (!loader) {\r\n process.stderr.write(`${programName}: unknown command \"${command}\"\\n\\n`);\r\n process.stderr.write(`${usage}\\n`);\r\n return 2;\r\n }\r\n\r\n // Per-command help: no command module defines a --help flag (strict parseArgs\r\n // would throw on it), so answer it centrally from COMMAND_USAGE.\r\n const rest = argv.slice(1);\r\n if (rest.includes(\"--help\") || rest.includes(\"-h\")) {\r\n const sig = COMMAND_USAGE[command];\r\n if (sig) {\r\n print(`usage: ${programName} ${sig}`);\r\n return 0;\r\n }\r\n }\r\n\r\n const mod = await loader();\r\n try {\r\n return await mod.run(rest);\r\n } catch (err) {\r\n // Friendly bad-flag errors: strict parseArgs throws ERR_PARSE_ARGS_* for an\r\n // unknown/malformed option — print the message + the usage line instead of\r\n // letting a raw stack trace reach the user. Everything else still rethrows\r\n // (the bin entry reports those as fatal).\r\n const code = (err as { code?: string }).code;\r\n if (typeof code === \"string\" && code.startsWith(\"ERR_PARSE_ARGS\")) {\r\n const message = err instanceof Error ? err.message : String(err);\r\n const sig = COMMAND_USAGE[command];\r\n if (sig) process.stderr.write(`usage: ${programName} ${sig}\\n`);\r\n return fail(message);\r\n }\r\n throw err;\r\n }\r\n}\r\n","/**\r\n * cli/banner — the branded ASCII-art header shown once atop install / uninstall\r\n * / upgrade / doctor.\r\n *\r\n * Two PURE functions drive everything (no process.* reads here — the command\r\n * wiring injects the real env so tests can call these directly without a TTY):\r\n *\r\n * renderBrandBanner(name, { color, columns, palette }) → the banner string\r\n * shouldShowBanner({ isTTY, noColor, json, quiet }) → whether to show it\r\n *\r\n * RESPONSIVE (one line, NEVER stacked), two forms:\r\n * • WIDE — a 6-row \"ANSI Shadow\" block font (solid `█` + `╗╔╝╚║═` shadow,\r\n * ~8 cols/char, hand-transcribed + fixed-width so it tiles cleanly) when its\r\n * render fits the terminal width.\r\n * • NARROW — a single-line gradient TITLE `◆ AGENT-CONNECTOR` (the brand\r\n * uppercased, each char colored along the palette + bold). ~18 cols, so it\r\n * fits any real terminal; it is the universal narrow form.\r\n * The WIDE font covers the connector-id charset [A-Za-z0-9 ._-].\r\n *\r\n * COLOR: a palette gradient (three RGB stops, a {@link Palette}) — swept per\r\n * column across the block art, or per character across the title. The render is\r\n * PURE and palette-parameterized — the caller picks the palette (the impure\r\n * app.ts wrapper rotates {@link PALETTES} per run). truecolor→256→16→none tiers\r\n * all honor the palette; NO_COLOR = zero ANSI.\r\n */\r\n\r\n/** Color capability the host terminal advertises, highest → lowest. */\r\nexport type ColorMode = \"truecolor\" | \"ansi256\" | \"ansi16\" | \"none\";\r\n\r\n/** A 24-bit RGB triple. */\r\nexport type RGB = readonly [number, number, number];\r\n\r\n/** A 3-stop gradient: the sweep lerps stop0 → stop1 → stop2 across the columns. */\r\nexport type Palette = readonly [RGB, RGB, RGB];\r\n\r\n/**\r\n * The 10 rotation palettes. The impure {@link maybePrintBanner} wrapper picks one\r\n * at random per run so each real invocation shows a different color; the pure\r\n * renderer defaults to PALETTES[0] so direct callers + tests stay deterministic.\r\n */\r\nexport const PALETTES: readonly Palette[] = [\r\n [[255, 210, 0], [255, 110, 10], [220, 30, 25]], // Sunset\r\n [[255, 225, 90], [255, 120, 0], [200, 20, 20]], // Lava\r\n [[230, 30, 30], [255, 120, 0], [255, 220, 0]], // Fire\r\n [[255, 225, 120], [255, 170, 40], [225, 110, 20]], // Amber gold\r\n [[255, 205, 150], [255, 150, 130], [255, 120, 175]], // Peach pastel\r\n [[255, 80, 170], [200, 40, 200], [100, 60, 210]], // Berry\r\n [[0, 220, 180], [0, 160, 230], [60, 90, 230]], // Ocean\r\n [[80, 230, 140], [0, 200, 210], [150, 90, 235]], // Aurora\r\n [[170, 230, 90], [60, 200, 120], [20, 150, 140]], // Forest\r\n [[0, 200, 200], [40, 80, 230], [200, 40, 200]], // Synthwave\r\n] as const;\r\n\r\n/** Inputs to {@link renderBrandBanner} — all injected, never read from process. */\r\nexport interface BannerOptions {\r\n /** Color capability to render at. \"none\" emits zero ANSI codes. */\r\n color: ColorMode;\r\n /** Terminal width in columns; selects the form (wide block art → one-line title). */\r\n columns: number;\r\n /** The 3-stop gradient. Defaults to {@link PALETTES}[0] (Sunset) when omitted. */\r\n palette?: Palette;\r\n}\r\n\r\n/** Inputs to {@link shouldShowBanner} — the real env, injected by the caller. */\r\nexport interface BannerGate {\r\n /** process.stdout.isTTY (banner is suppressed entirely when not a TTY). */\r\n isTTY: boolean;\r\n /** NO_COLOR is set (the banner still shows, but with zero color codes). */\r\n noColor: boolean;\r\n /** A machine-readable --json was requested (suppress entirely). */\r\n json: boolean;\r\n /** An explicit --quiet was passed (suppress entirely). */\r\n quiet: boolean;\r\n}\r\n\r\n/**\r\n * Whether to print the banner at all. The banner is decorative, so it shows ONLY\r\n * for an interactive TTY and never when output is being consumed by a script or\r\n * pipeline: not when piped/redirected (`!isTTY`), not under `--json`, and not\r\n * under `--quiet`. `NO_COLOR` does NOT suppress it — the banner renders without\r\n * color in that case (handled by {@link resolveColorMode}).\r\n */\r\nexport function shouldShowBanner(gate: BannerGate): boolean {\r\n return gate.isTTY && !gate.json && !gate.quiet;\r\n}\r\n\r\n/**\r\n * Resolve the color tier from the (injected) terminal env. 24-bit when the\r\n * terminal advertises it (COLORTERM=truecolor|24bit), 256-color when TERM names\r\n * a 256 palette, else 16-color — and PLAIN (no color) under NO_COLOR or a dumb /\r\n * absent TERM.\r\n */\r\nexport function resolveColorMode(env: {\r\n noColor: boolean;\r\n colorterm?: string | undefined;\r\n term?: string | undefined;\r\n}): ColorMode {\r\n if (env.noColor) return \"none\";\r\n const term = (env.term ?? \"\").toLowerCase();\r\n if (term === \"\" || term === \"dumb\") return \"none\";\r\n const colorterm = (env.colorterm ?? \"\").toLowerCase();\r\n if (colorterm === \"truecolor\" || colorterm === \"24bit\") return \"truecolor\";\r\n if (term.includes(\"256\")) return \"ansi256\";\r\n return \"ansi16\";\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// WIDE font — \"ANSI Shadow\" (6 rows). Hand-transcribed bold figlet glyphs —\r\n// solid `█` with a `╗╔╝╚║═` 3D shadow — fixed-width per glyph so they TILE\r\n// cleanly when concatenated (~8 cols/char → \"agent-connector\" ≈ 126 cols on\r\n// one line). Used only when the terminal is wide enough.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nconst WIDE_FONT: Record<string, readonly string[]> = {\r\n A: [\" █████╗ \", \"██╔══██╗\", \"███████║\", \"██╔══██║\", \"██║ ██║\", \"╚═╝ ╚═╝\"],\r\n B: [\"██████╗ \", \"██╔══██╗\", \"██████╔╝\", \"██╔══██╗\", \"██████╔╝\", \"╚═════╝ \"],\r\n C: [\" ██████╗\", \"██╔════╝\", \"██║ \", \"██║ \", \"╚██████╗\", \" ╚═════╝\"],\r\n D: [\"██████╗ \", \"██╔══██╗\", \"██║ ██║\", \"██║ ██║\", \"██████╔╝\", \"╚═════╝ \"],\r\n E: [\"███████╗\", \"██╔════╝\", \"█████╗ \", \"██╔══╝ \", \"███████╗\", \"╚══════╝\"],\r\n F: [\"███████╗\", \"██╔════╝\", \"█████╗ \", \"██╔══╝ \", \"██║ \", \"╚═╝ \"],\r\n G: [\" ██████╗ \", \"██╔════╝ \", \"██║ ███╗\", \"██║ ██║\", \"╚██████╔╝\", \" ╚═════╝ \"],\r\n H: [\"██╗ ██╗\", \"██║ ██║\", \"███████║\", \"██╔══██║\", \"██║ ██║\", \"╚═╝ ╚═╝\"],\r\n I: [\"██╗\", \"██║\", \"██║\", \"██║\", \"██║\", \"╚═╝\"],\r\n J: [\" ██╗\", \" ██║\", \" ██║\", \"██ ██║\", \"╚█████╔╝\", \" ╚════╝ \"],\r\n K: [\"██╗ ██╗\", \"██║ ██╔╝\", \"█████╔╝ \", \"██╔═██╗ \", \"██║ ██╗\", \"╚═╝ ╚═╝\"],\r\n L: [\"██╗ \", \"██║ \", \"██║ \", \"██║ \", \"███████╗\", \"╚══════╝\"],\r\n M: [\"███╗ ███╗\", \"████╗ ████║\", \"██╔████╔██║\", \"██║╚██╔╝██║\", \"██║ ╚═╝ ██║\", \"╚═╝ ╚═╝\"],\r\n N: [\"███╗ ██╗\", \"████╗ ██║\", \"██╔██╗ ██║\", \"██║╚██╗██║\", \"██║ ╚████║\", \"╚═╝ ╚═══╝\"],\r\n O: [\" ██████╗ \", \"██╔═══██╗\", \"██║ ██║\", \"██║ ██║\", \"╚██████╔╝\", \" ╚═════╝ \"],\r\n P: [\"██████╗ \", \"██╔══██╗\", \"██████╔╝\", \"██╔═══╝ \", \"██║ \", \"╚═╝ \"],\r\n Q: [\" ██████╗ \", \"██╔═══██╗\", \"██║ ██║\", \"██║▄▄ ██║\", \"╚██████╔╝\", \" ╚══▀▀═╝ \"],\r\n R: [\"██████╗ \", \"██╔══██╗\", \"██████╔╝\", \"██╔══██╗\", \"██║ ██║\", \"╚═╝ ╚═╝\"],\r\n S: [\"███████╗\", \"██╔════╝\", \"███████╗\", \"╚════██║\", \"███████║\", \"╚══════╝\"],\r\n T: [\"████████╗\", \"╚══██╔══╝\", \" ██║ \", \" ██║ \", \" ██║ \", \" ╚═╝ \"],\r\n U: [\"██╗ ██╗\", \"██║ ██║\", \"██║ ██║\", \"██║ ██║\", \"╚██████╔╝\", \" ╚═════╝ \"],\r\n V: [\"██╗ ██╗\", \"██║ ██║\", \"██║ ██║\", \"╚██╗ ██╔╝\", \" ╚████╔╝ \", \" ╚═══╝ \"],\r\n W: [\"██╗ ██╗\", \"██║ ██║\", \"██║ █╗ ██║\", \"██║███╗██║\", \"╚███╔███╔╝\", \" ╚══╝╚══╝ \"],\r\n X: [\"██╗ ██╗\", \"╚██╗██╔╝\", \" ╚███╔╝ \", \" ██╔██╗ \", \"██╔╝ ██╗\", \"╚═╝ ╚═╝\"],\r\n Y: [\"██╗ ██╗\", \"╚██╗ ██╔╝\", \" ╚████╔╝ \", \" ╚██╔╝ \", \" ██║ \", \" ╚═╝ \"],\r\n Z: [\"███████╗\", \"╚══███╔╝\", \" ███╔╝ \", \" ███╔╝ \", \"███████╗\", \"╚══════╝\"],\r\n \"0\": [\" ██████╗ \", \"██╔═████╗\", \"██║██╔██║\", \"████╔╝██║\", \"╚██████╔╝\", \" ╚═════╝ \"],\r\n \"1\": [\" ██╗\", \"███║\", \"╚██║\", \" ██║\", \" ██║\", \" ╚═╝\"],\r\n \"2\": [\"██████╗ \", \"╚════██╗\", \" █████╔╝\", \"██╔═══╝ \", \"███████╗\", \"╚══════╝\"],\r\n \"3\": [\"██████╗ \", \"╚════██╗\", \" █████╔╝\", \" ╚═══██╗\", \"██████╔╝\", \"╚═════╝ \"],\r\n \"4\": [\"██╗ ██╗\", \"██║ ██║\", \"███████║\", \"╚════██║\", \" ██║\", \" ╚═╝\"],\r\n \"5\": [\"███████╗\", \"██╔════╝\", \"███████╗\", \"╚════██║\", \"███████║\", \"╚══════╝\"],\r\n \"6\": [\" ██████╗ \", \"██╔════╝ \", \"███████╗ \", \"██╔═══██╗\", \"╚██████╔╝\", \" ╚═════╝ \"],\r\n \"7\": [\"███████╗\", \"╚════██║\", \" ██╔╝\", \" ██╔╝ \", \" ██║ \", \" ╚═╝ \"],\r\n \"8\": [\" █████╗ \", \"██╔══██╗\", \"╚█████╔╝\", \"██╔══██╗\", \"╚█████╔╝\", \" ╚════╝ \"],\r\n \"9\": [\" █████╗ \", \"██╔══██╗\", \"╚██████║\", \" ╚═══██║\", \" █████╔╝\", \" ╚════╝ \"],\r\n \"-\": [\" \", \" \", \"█████╗\", \"╚════╝\", \" \", \" \"],\r\n \"_\": [\" \", \" \", \" \", \" \", \"███████╗\", \"╚══════╝\"],\r\n \".\": [\" \", \" \", \" \", \" \", \"██╗\", \"╚═╝\"],\r\n \" \": [\" \", \" \", \" \", \" \", \" \", \" \"],\r\n};\r\n\r\nconst GLYPH_ROWS = 6;\r\n\r\n/** Visible column count of a string (full-block + box-drawing are 1 cell each). */\r\nfunction vlen(s: string): number {\r\n return [...s].length;\r\n}\r\n\r\n/**\r\n * Render `name` into the fixed-width `font` as GLYPH_ROWS lines. The ANSI-Shadow\r\n * glyphs already carry their own trailing shadow column and tile cleanly with NO\r\n * inter-glyph gap. Returns null when the name has no renderable characters; the\r\n * glyphs are width-consistent per glyph, so the rows stay aligned.\r\n */\r\nfunction renderWithFont(name: string, font: Record<string, readonly string[]>): string[] | null {\r\n const chars = [...name];\r\n if (chars.length === 0) return null;\r\n const blank = font[\" \"]!;\r\n const rows: string[] = Array.from({ length: GLYPH_ROWS }, () => \"\");\r\n for (const ch of chars) {\r\n const glyph = font[ch.toUpperCase()] ?? blank;\r\n for (let r = 0; r < GLYPH_ROWS; r++) {\r\n rows[r] += glyph[r] ?? \"\";\r\n }\r\n }\r\n // Drop any fully-blank bottom rows so a name built from narrower glyphs (e.g.\r\n // \".\" / \"_\") never pads the banner with trailing empty lines.\r\n while (rows.length > 1 && rows[rows.length - 1]!.trim() === \"\") rows.pop();\r\n return rows;\r\n}\r\n\r\n/** Max visible width across an art block's rows. */\r\nfunction blockWidth(rows: string[]): number {\r\n return rows.length === 0 ? 0 : Math.max(...rows.map(vlen));\r\n}\r\n\r\n/**\r\n * The WIDE ANSI-Shadow block art for `name` when it fits `columns` (ONE line,\r\n * never stacked); else null so the caller renders the narrow one-line title.\r\n * `columns <= 0` means \"no constraint\" → always the WIDE art.\r\n */\r\nfunction selectWideArt(name: string, columns: number): string[] | null {\r\n const limit = columns > 0 ? columns : Infinity;\r\n const wide = renderWithFont(name, WIDE_FONT);\r\n return wide != null && blockWidth(wide) <= limit ? wide : null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Palette-parameterized gradient. The sweep lerps the three palette stops\r\n// across each row's columns (t∈[0,1]). truecolor uses the exact RGB; 256 and 16\r\n// derive the nearest representable code FROM the same RGB, so every palette\r\n// works in every tier. \"none\" emits the bare char.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The interpolated RGB of `palette` at gradient position t∈[0,1]. */\r\nfunction gradientRGB(t: number, palette: Palette): RGB {\r\n const clamp = Math.max(0, Math.min(1, t));\r\n const seg = clamp >= 0.5 ? 1 : 0;\r\n const local = (clamp - seg * 0.5) / 0.5;\r\n const a = palette[seg]!;\r\n const b = palette[seg + 1]!;\r\n return [\r\n Math.round(a[0] + (b[0] - a[0]) * local),\r\n Math.round(a[1] + (b[1] - a[1]) * local),\r\n Math.round(a[2] + (b[2] - a[2]) * local),\r\n ];\r\n}\r\n\r\n/** Nearest xterm-256 cube index (16..231) for an RGB triple. */\r\nfunction rgbTo256(r: number, g: number, b: number): number {\r\n const q = (v: number): number => (v < 48 ? 0 : v < 115 ? 1 : Math.round((v - 35) / 40));\r\n return 16 + 36 * q(r) + 6 * q(g) + q(b);\r\n}\r\n\r\n/** Nearest of the 8 bright 16-color fg codes (90..97) for an RGB triple. */\r\nfunction rgbTo16(r: number, g: number, b: number): number {\r\n // Threshold each channel; map the on/off triple to its bright SGR code.\r\n const hi = (v: number): number => (v >= 128 ? 1 : 0);\r\n const key = (hi(r) << 2) | (hi(g) << 1) | hi(b);\r\n // index: RGB bits → code. 0:black(90) 1:blue(94) 2:green(92) 3:cyan(96)\r\n // 4:red(91) 5:magenta(95) 6:yellow(93) 7:white(97)\r\n return [90, 94, 92, 96, 91, 95, 93, 97][key]!;\r\n}\r\n\r\nconst RESET = \"\\x1b[0m\";\r\n\r\n/**\r\n * Wrap a single grapheme `ch` at gradient position `t` in the SGR escape for the\r\n * given color tier + palette. Whitespace is never colored (no point paying for\r\n * an escape around a space) and \"none\" returns the bare char.\r\n */\r\nfunction colorChar(ch: string, t: number, color: ColorMode, palette: Palette): string {\r\n if (color === \"none\" || ch.trim() === \"\") return ch;\r\n const [r, g, b] = gradientRGB(t, palette);\r\n if (color === \"truecolor\") return `\\x1b[38;2;${r};${g};${b}m${ch}${RESET}`;\r\n if (color === \"ansi256\") return `\\x1b[38;5;${rgbTo256(r, g, b)}m${ch}${RESET}`;\r\n return `\\x1b[${rgbTo16(r, g, b)}m${ch}${RESET}`;\r\n}\r\n\r\n/** Apply the left-to-right gradient across one art row (by visible column). */\r\nfunction colorizeRow(row: string, color: ColorMode, palette: Palette): string {\r\n if (color === \"none\") return row;\r\n const chars = [...row];\r\n const width = Math.max(1, chars.length - 1);\r\n let out = \"\";\r\n for (let i = 0; i < chars.length; i++) {\r\n out += colorChar(chars[i]!, i / width, color, palette);\r\n }\r\n return out;\r\n}\r\n\r\n/** A single BOLD grapheme at gradient position `t` (used by the narrow title). */\r\nfunction boldColorChar(ch: string, t: number, color: ColorMode, palette: Palette): string {\r\n if (color === \"none\") return ch;\r\n const [r, g, b] = gradientRGB(t, palette);\r\n const fg =\r\n color === \"truecolor\"\r\n ? `38;2;${r};${g};${b}`\r\n : color === \"ansi256\"\r\n ? `38;5;${rgbTo256(r, g, b)}`\r\n : `${rgbTo16(r, g, b)}`;\r\n return `\\x1b[1;${fg}m${ch}${RESET}`;\r\n}\r\n\r\n/**\r\n * The NARROW one-line title `◆ AGENT-CONNECTOR`: a colored leading diamond (the\r\n * palette mid stop), two spaces, then the UPPERCASED brand with each character\r\n * colored along the palette gradient (i → t = i/(len-1)) and bold. Under \"none\"\r\n * it is the plain text with ZERO ANSI. ~18 cols for \"agent-connector\", so it\r\n * fits any real terminal.\r\n */\r\nfunction renderTitle(name: string, color: ColorMode, palette: Palette): string {\r\n const upper = name.toUpperCase();\r\n if (color === \"none\") return `◆ ${upper}`;\r\n const diamond = boldColorChar(\"◆\", 0.5, color, palette);\r\n const chars = [...upper];\r\n const span = Math.max(1, chars.length - 1);\r\n let title = \"\";\r\n for (let i = 0; i < chars.length; i++) {\r\n title += boldColorChar(chars[i]!, i / span, color, palette);\r\n }\r\n return `${diamond} ${title}`;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Footer (engine attribution). Shown on BOTH the global and branded CLIs — the\r\n// \"powered by\" wording is intentional.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nconst FOOTER_LINES = [\r\n \"powered by @ken-jo/agent-connector\",\r\n \"more → https://github.com/ken-jo/agent-connector\",\r\n] as const;\r\n\r\n/** Dim (de-emphasized) footer line; plain under \"none\". */\r\nfunction dim(text: string, color: ColorMode): string {\r\n return color === \"none\" ? text : `\\x1b[2m${text}${RESET}`;\r\n}\r\n\r\n/**\r\n * Render the full banner: a responsive brand title with a palette-driven\r\n * gradient, then a two-line dim footer directly below.\r\n *\r\n * • WIDE — the ANSI-Shadow block art when it fits `columns` (ONE line, never\r\n * stacked; `columns <= 0` = no constraint).\r\n * • NARROW — the one-line `◆ AGENT-CONNECTOR` gradient title (the universal\r\n * narrow form, ~18 cols) when the block art would overflow.\r\n * • `palette` defaults to PALETTES[0] so direct callers + tests are\r\n * deterministic; the impure app.ts wrapper rotates the palettes per run.\r\n * • Under `color: \"none\"` (NO_COLOR / dumb term) the output carries zero ANSI\r\n * escape codes — only the raw art/title + footer text.\r\n *\r\n * The result has NO trailing newline; the caller prints it with one.\r\n */\r\nexport function renderBrandBanner(name: string, opts: BannerOptions): string {\r\n const { color, columns } = opts;\r\n const palette = opts.palette ?? PALETTES[0]!;\r\n const footer = FOOTER_LINES.map((l) => dim(l, color)).join(\"\\n\");\r\n\r\n const art = selectWideArt(name, columns);\r\n const body =\r\n art != null\r\n ? art.map((row) => colorizeRow(row, color, palette)).join(\"\\n\")\r\n : renderTitle(name, color, palette);\r\n return `${body}\\n${footer}`;\r\n}\r\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import {
4
4
  backupsDir,
5
5
  connectorDir,
6
6
  ensureDir
7
- } from "./chunk-GZGLCCEE.js";
7
+ } from "./chunk-QYOUQCC6.js";
8
8
 
9
9
  // src/core/managed-block.ts
10
10
  import { createHash } from "crypto";
@@ -493,4 +493,4 @@ export {
493
493
  hasMemoryLedger,
494
494
  recordMemoryTarget
495
495
  };
496
- //# sourceMappingURL=chunk-UMQ6NBQR.js.map
496
+ //# sourceMappingURL=chunk-ILWHLGIC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/managed-block.ts"],"sourcesContent":["/**\r\n * core/managed-block — the marker-fenced MANAGED BLOCK engine behind the\r\n * `memory` content surface.\r\n *\r\n * Memory/rules files (AGENTS.md, CLAUDE.md, GEMINI.md, …) are SHARED,\r\n * user-authored files — unlike commands/skills/subagents, agent-connector does\r\n * not own them. Every write therefore goes through this one module, which\r\n * implements idempotent, hash-stamped, uninstall-reversible blocks:\r\n *\r\n * <!-- agent-connector:begin <connectorId>/<name> hash=<sha256-12> -->\r\n * <!-- Managed by agent-connector for \"<connectorId>\". Do not edit … -->\r\n * …guidance…\r\n * <!-- agent-connector:end <connectorId>/<name> -->\r\n *\r\n * Design rules (each grounded in surveyed prior art — ansible blockinfile,\r\n * conda init, OMC mergeClaudeMd, Ruler, doctoc):\r\n * • UNIQUE marker per block: the blockId (`<connectorId>/<entryName>`) lives\r\n * ON the marker line, so multiple connectors coexist in one file and each\r\n * update path only ever touches its own pair (ansible's documented\r\n * multi-block rule). The shared `agent-connector` namespace token lets\r\n * doctor/uninstall enumerate every block with one scan.\r\n * • `hash=` is the first 12 hex chars of sha256 over the NORMALIZED inner\r\n * region (CRLF→LF + trim — stable under prettier/EOL converters): O(1)\r\n * idempotence (unchanged → skip, no mtime/git churn) and tamper detection\r\n * (actual inner hash ≠ recorded ⇒ the user edited inside the block ⇒ warn,\r\n * never clobber without an explicit force).\r\n * • IN-PLACE replacement (conda semantics): zero bytes outside the marker\r\n * pair ever change — no move-to-top, no user blank-line reflow.\r\n * • Line-anchored matching that explicitly tolerates `\\r` line ends and a\r\n * FENCE-AWARE scanner (markers quoted inside ``` / ~~~ code fences never\r\n * match) — fixes the CRLF duplicate-block and quoted-marker classes.\r\n * • First-begin / FIRST-end-after pairing (never last-end): a missing end\r\n * marker must not swallow a sibling connector's block.\r\n * • HTML-comment markers are CORRECT for CLAUDE.md: Claude Code strips HTML\r\n * comments from CLAUDE.md before context injection (verified against docs\r\n * and the 2.1.172 binary), so the markers and the do-not-edit notice are\r\n * INVISIBLE to the model there while remaining fully parseable by us for\r\n * sync/doctor/uninstall. On AGENTS.md hosts (which inline the whole file\r\n * into the prompt) the short notice doubles as an in-prompt \"do not edit\"\r\n * instruction to the host's own agent. A `commentStyle: \"hash\"` variant\r\n * exists for future non-markdown targets (`#`-prefixed marker lines).\r\n *\r\n * The module also owns the per-connector MEMORY OWNERSHIP LEDGER\r\n * (`connectorDir(id)/memory-state.json`): the markers in the file remain the\r\n * source of truth for uninstall (a teammate's machine with no ledger still\r\n * uninstalls via the prefix scan); the ledger only adds the created-vs-modified\r\n * distinction (file deletion rights) and doctor diagnostics.\r\n */\r\n\r\nimport { createHash } from \"node:crypto\";\r\nimport {\r\n chmodSync,\r\n copyFileSync,\r\n existsSync,\r\n readFileSync,\r\n renameSync,\r\n rmSync,\r\n statSync,\r\n writeFileSync,\r\n} from \"node:fs\";\r\nimport { basename, dirname, join } from \"node:path\";\r\n\r\nimport { assertNoSymlinkInPath, backupsDir, connectorDir, ensureDir } from \"./paths.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Grammar constants (shared with defineConnector's content validation)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Literal begin token. Connector memory content MUST NOT contain it. */\r\nexport const MANAGED_BLOCK_BEGIN_TOKEN = \"agent-connector:begin\";\r\n/** Literal end token. Connector memory content MUST NOT contain it. */\r\nexport const MANAGED_BLOCK_END_TOKEN = \"agent-connector:end\";\r\n\r\n/** Hard cap on one memory entry's content (ConnectorConfigError above this). */\r\nexport const MEMORY_CONTENT_HARD_CAP_BYTES = 16 * 1024;\r\n/**\r\n * Soft per-entry budget — exceeded → install-time `warn` ChangeRecord (memory\r\n * files are injected into EVERY prompt of EVERY session on the host; codex\r\n * additionally caps combined project docs at 32 KiB).\r\n */\r\nexport const MEMORY_CONTENT_SOFT_BUDGET_BYTES = 4 * 1024;\r\n\r\n/** Marker comment style: HTML comments (default, all v1 markdown targets) or `#` lines. */\r\nexport type BlockCommentStyle = \"html\" | \"hash\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Hashing / rendering\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** CRLF/CR → LF + trim: the normalization both hashing sides use. */\r\nfunction normalizeInner(s: string): string {\r\n return s.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\").trim();\r\n}\r\n\r\n/** First 12 hex chars of sha256 over the NORMALIZED inner region. */\r\nexport function hashBlockContent(inner: string): string {\r\n return createHash(\"sha256\").update(normalizeInner(inner), \"utf8\").digest(\"hex\").slice(0, 12);\r\n}\r\n\r\n/** The conda-style in-block warning, adapted for the LLM era (see header). */\r\nfunction defaultNotice(connectorId: string): string {\r\n return (\r\n `Managed by agent-connector for \"${connectorId}\". Do not edit between these markers: ` +\r\n `run your connector package's upgrade/sync command to rewrite this block; ` +\r\n `run its uninstall command to remove it ` +\r\n `(framework fallback: \\`agent-connector uninstall ${connectorId}\\`).`\r\n );\r\n}\r\n\r\nfunction beginLine(blockId: string, hash: string, style: BlockCommentStyle): string {\r\n return style === \"hash\"\r\n ? `# ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash}`\r\n : `<!-- ${MANAGED_BLOCK_BEGIN_TOKEN} ${blockId} hash=${hash} -->`;\r\n}\r\n\r\n/** END line is a fixed exact string (no hash) so a content change never strands it. */\r\nfunction endLine(blockId: string, style: BlockCommentStyle): string {\r\n return style === \"hash\"\r\n ? `# ${MANAGED_BLOCK_END_TOKEN} ${blockId}`\r\n : `<!-- ${MANAGED_BLOCK_END_TOKEN} ${blockId} -->`;\r\n}\r\n\r\nfunction noticeLine(notice: string, style: BlockCommentStyle): string {\r\n return style === \"hash\" ? `# ${notice}` : `<!-- ${notice} -->`;\r\n}\r\n\r\nexport interface RenderBlockOptions {\r\n /** `<connectorId>/<entryName>` (or the reserved `_shared/<name>` bridge prefix). */\r\n blockId: string;\r\n /** Connector id named in the default do-not-edit notice line. */\r\n connectorId: string;\r\n /** The guidance payload (plain markdown; normalized + trimmed on emit). */\r\n content: string;\r\n /** Marker comment style; default \"html\". */\r\n commentStyle?: BlockCommentStyle;\r\n /** Override the default notice line TEXT (without comment delimiters). */\r\n notice?: string;\r\n}\r\n\r\n/**\r\n * Render the block as LOGICAL lines (no EOL chars). The recorded `hash=`\r\n * covers the full inner region (notice line + content) so install and scan\r\n * compare like for like.\r\n */\r\nexport function renderBlockLines(opts: RenderBlockOptions): string[] {\r\n const style = opts.commentStyle ?? \"html\";\r\n const inner = [\r\n noticeLine(opts.notice ?? defaultNotice(opts.connectorId), style),\r\n ...normalizeInner(opts.content).split(\"\\n\"),\r\n ];\r\n const hash = hashBlockContent(inner.join(\"\\n\"));\r\n return [beginLine(opts.blockId, hash, style), ...inner, endLine(opts.blockId, style)];\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Scanning (fence-aware, line-anchored, CRLF-tolerant)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n// Both comment styles are RECOGNIZED in one pass (a file may legitimately mix\r\n// styles only across rewrites; emission always uses the requested style).\r\nconst BEGIN_RE =\r\n /^(?:<!--\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12})\\s+-->|#\\s+agent-connector:begin\\s+(\\S+)\\s+hash=([0-9a-f]{12}))\\s*$/;\r\nconst END_RE = /^(?:<!--\\s+agent-connector:end\\s+(\\S+)\\s+-->|#\\s+agent-connector:end\\s+(\\S+))\\s*$/;\r\n\r\ninterface MarkerEvent {\r\n kind: \"begin\" | \"end\";\r\n blockId: string;\r\n /** Recorded hash (begin markers only). */\r\n hash?: string;\r\n /** Line index into the logical-lines array. */\r\n index: number;\r\n}\r\n\r\n/** Strip ONE trailing `\\r` — `raw.split(\"\\n\")` leaves it on CRLF files. */\r\nfunction stripCr(line: string): string {\r\n return line.endsWith(\"\\r\") ? line.slice(0, -1) : line;\r\n}\r\n\r\n/**\r\n * Scan logical lines for marker events, tracking ``` / ~~~ fence state so a\r\n * marker QUOTED inside a fenced code block never matches (the OMC class of\r\n * false positives, eliminated rather than just reduced).\r\n */\r\nfunction scanMarkers(logical: string[]): MarkerEvent[] {\r\n const events: MarkerEvent[] = [];\r\n let fence: { char: string; len: number } | null = null;\r\n for (let i = 0; i < logical.length; i++) {\r\n const line = logical[i]!;\r\n if (fence) {\r\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\r\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\r\n continue;\r\n }\r\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\r\n if (open) {\r\n fence = { char: open[1]![0]!, len: open[1]!.length };\r\n continue;\r\n }\r\n const b = line.match(BEGIN_RE);\r\n if (b) {\r\n events.push({ kind: \"begin\", blockId: (b[1] ?? b[3])!, hash: (b[2] ?? b[4])!, index: i });\r\n continue;\r\n }\r\n const e = line.match(END_RE);\r\n if (e) events.push({ kind: \"end\", blockId: (e[1] ?? e[2])!, index: i });\r\n }\r\n return events;\r\n}\r\n\r\n/**\r\n * Logical lines of `raw` that sit OUTSIDE ``` / ~~~ code fences — for host\r\n * probes that must ignore quoted examples (e.g. the claude-code `@AGENTS.md`\r\n * import detection). Fence lines themselves are excluded.\r\n */\r\nexport function linesOutsideFences(raw: string): string[] {\r\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\r\n const logical = body.split(\"\\n\").map(stripCr);\r\n const out: string[] = [];\r\n let fence: { char: string; len: number } | null = null;\r\n for (const line of logical) {\r\n if (fence) {\r\n const close = line.match(/^ {0,3}(`{3,}|~{3,})\\s*$/);\r\n if (close && close[1]![0] === fence.char && close[1]!.length >= fence.len) fence = null;\r\n continue;\r\n }\r\n const open = line.match(/^ {0,3}(`{3,}|~{3,})/);\r\n if (open) {\r\n fence = { char: open[1]![0]!, len: open[1]!.length };\r\n continue;\r\n }\r\n out.push(line);\r\n }\r\n return out;\r\n}\r\n\r\ninterface BlockPair {\r\n blockId: string;\r\n begin: MarkerEvent;\r\n end: MarkerEvent;\r\n}\r\n\r\n/**\r\n * Pair markers per blockId: first begin, then the FIRST end at-or-after it.\r\n * A nested begin for the SAME id (inside an open pair) is treated as inner\r\n * content; unpaired markers are returned as strays. Per-id state means a\r\n * missing end for connector A can never swallow connector B's block.\r\n */\r\nfunction pairMarkers(events: MarkerEvent[]): { pairs: BlockPair[]; strays: MarkerEvent[] } {\r\n const open = new Map<string, MarkerEvent>();\r\n const pairs: BlockPair[] = [];\r\n const strays: MarkerEvent[] = [];\r\n for (const ev of events) {\r\n if (ev.kind === \"begin\") {\r\n if (!open.has(ev.blockId)) open.set(ev.blockId, ev);\r\n // else: a begin inside an open pair — inner content / abuse; the hash\r\n // check will flag the pair as drifted rather than guessing boundaries.\r\n } else {\r\n const b = open.get(ev.blockId);\r\n if (b) {\r\n pairs.push({ blockId: ev.blockId, begin: b, end: ev });\r\n open.delete(ev.blockId);\r\n } else {\r\n strays.push(ev);\r\n }\r\n }\r\n }\r\n for (const b of open.values()) strays.push(b);\r\n return { pairs, strays };\r\n}\r\n\r\n/** One discovered block (for doctor / refcount / uninstall enumeration). */\r\nexport interface ManagedBlockInfo {\r\n blockId: string;\r\n /** The hash recorded on the begin marker line. */\r\n recordedHash: string;\r\n /** Hash of the actual normalized inner region as found on disk. */\r\n actualHash: string;\r\n /** True when recordedHash ≠ actualHash — the user edited inside the block. */\r\n drifted: boolean;\r\n beginLine: number;\r\n endLine: number;\r\n}\r\n\r\n/** Enumerate every complete agent-connector block in `raw` (namespace scan). */\r\nexport function listManagedBlocks(raw: string): ManagedBlockInfo[] {\r\n const body = raw.startsWith(\"\\uFEFF\") ? raw.slice(1) : raw;\r\n const logical = body.split(\"\\n\").map(stripCr);\r\n const { pairs } = pairMarkers(scanMarkers(logical));\r\n return pairs.map((p) => {\r\n const inner = logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\");\r\n const actualHash = hashBlockContent(inner);\r\n const recordedHash = p.begin.hash ?? \"\";\r\n return {\r\n blockId: p.blockId,\r\n recordedHash,\r\n actualHash,\r\n drifted: recordedHash !== actualHash,\r\n beginLine: p.begin.index,\r\n endLine: p.end.index,\r\n };\r\n });\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Pure text upsert / removal\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nexport interface UpsertBlockOptions extends RenderBlockOptions {\r\n /** Overwrite a USER-EDITED (drifted) block. Default false → warn + leave intact. */\r\n force?: boolean;\r\n}\r\n\r\nexport interface BlockTextResult {\r\n /** Resulting full text (=== input when nothing changed). */\r\n text: string;\r\n action: \"create\" | \"update\" | \"skip\" | \"warn\";\r\n detail: string;\r\n changed: boolean;\r\n /**\r\n * True when the rewrite was DESTRUCTIVE-ADJACENT (force-overwrote a drifted\r\n * block, collapsed duplicate pairs, or stripped stray markers) — the file\r\n * wrapper writes a timestamped backup before persisting such a change.\r\n */\r\n recovered: boolean;\r\n /** Hash of the (new) rendered inner region — recorded in the ledger. */\r\n hash: string;\r\n}\r\n\r\n/** Detect the file's dominant EOL; new/replaced lines are emitted with it. */\r\nfunction detectEol(body: string): \"\\n\" | \"\\r\\n\" {\r\n const crlf = (body.match(/\\r\\n/g) ?? []).length;\r\n const total = (body.match(/\\n/g) ?? []).length;\r\n return crlf > 0 && crlf >= total - crlf ? \"\\r\\n\" : \"\\n\";\r\n}\r\n\r\n/** Add `\\r` to logical lines when the file is CRLF (joined with \"\\n\" later). */\r\nfunction withEol(lines: string[], eol: \"\\n\" | \"\\r\\n\"): string[] {\r\n return eol === \"\\r\\n\" ? lines.map((l) => `${l}\\r`) : lines;\r\n}\r\n\r\n/**\r\n * Strip trailing newline(s) + whitespace-only line tails WITHOUT touching\r\n * trailing spaces on the last content line (bytes outside our block).\r\n */\r\nfunction trimTrailingBlank(body: string): string {\r\n let out = body;\r\n for (;;) {\r\n const m = out.match(/\\r?\\n[ \\t]*$/);\r\n if (!m) return out;\r\n out = out.slice(0, out.length - m[0].length);\r\n }\r\n}\r\n\r\n/** Append the rendered block at EOF with exactly ONE blank separator line. */\r\nfunction appendBlock(body: string, blockLines: string[], eol: \"\\n\" | \"\\r\\n\"): string {\r\n const blockText = blockLines.join(eol) + eol;\r\n if (body.trim() === \"\") return blockText;\r\n return trimTrailingBlank(body) + eol + eol + blockText;\r\n}\r\n\r\n/**\r\n * Idempotent upsert of one managed block into `raw` (pure; no I/O).\r\n * See the module header for the full algorithm contract.\r\n */\r\nexport function upsertBlockInText(raw: string, opts: UpsertBlockOptions): BlockTextResult {\r\n const bom = raw.startsWith(\"\\uFEFF\");\r\n const body = bom ? raw.slice(1) : raw;\r\n const eol = detectEol(body);\r\n const lines = body.split(\"\\n\"); // elements keep a trailing \"\\r\" on CRLF files\r\n const logical = lines.map(stripCr);\r\n\r\n const events = scanMarkers(logical).filter((e) => e.blockId === opts.blockId);\r\n const { pairs, strays } = pairMarkers(events);\r\n\r\n const newLines = renderBlockLines(opts);\r\n const newHash = hashBlockContent(newLines.slice(1, -1).join(\"\\n\"));\r\n const finish = (text: string, r: Omit<BlockTextResult, \"text\" | \"hash\">): BlockTextResult => ({\r\n text: bom ? `\\uFEFF${text}` : text,\r\n hash: newHash,\r\n ...r,\r\n });\r\n\r\n if (pairs.length > 0) {\r\n const { begin, end } = pairs[0]!;\r\n const recorded = begin.hash ?? \"\";\r\n const actualHash = hashBlockContent(logical.slice(begin.index + 1, end.index).join(\"\\n\"));\r\n const drifted = actualHash !== recorded;\r\n\r\n if (drifted && !opts.force) {\r\n return finish(body, {\r\n action: \"warn\",\r\n detail:\r\n `block ${opts.blockId} was edited inside the markers ` +\r\n `(recorded hash ${recorded}, found ${actualHash}); left untouched — ` +\r\n `re-run with --force to overwrite the in-block edits`,\r\n changed: false,\r\n recovered: false,\r\n });\r\n }\r\n\r\n const duplicates = pairs.slice(1);\r\n const needsWrite =\r\n drifted || recorded !== newHash || duplicates.length > 0 || strays.length > 0;\r\n if (!needsWrite) {\r\n return finish(body, {\r\n action: \"skip\",\r\n detail: `block ${opts.blockId} already up to date (hash ${newHash})`,\r\n changed: false,\r\n recovered: false,\r\n });\r\n }\r\n\r\n // Build the deletion set: the canonical pair region (replaced in place),\r\n // duplicate pairs (+ ONE adjacent blank line each), and stray marker LINES.\r\n const del = new Set<number>();\r\n for (let i = begin.index; i <= end.index; i++) del.add(i);\r\n for (const dup of duplicates) {\r\n for (let i = dup.begin.index; i <= dup.end.index; i++) del.add(i);\r\n reclaimBlankLine(logical, dup.begin.index, dup.end.index, del, lines.length);\r\n }\r\n for (const s of strays) del.add(s.index);\r\n\r\n const out: string[] = [];\r\n for (let i = 0; i < lines.length; i++) {\r\n if (i === begin.index) out.push(...withEol(newLines, eol));\r\n if (!del.has(i)) out.push(lines[i]!);\r\n }\r\n const notes: string[] = [];\r\n if (drifted) notes.push(\"in-block edits overwritten (--force; backup taken)\");\r\n if (duplicates.length > 0) notes.push(`${duplicates.length} duplicate pair(s) collapsed`);\r\n if (strays.length > 0) notes.push(`${strays.length} stray marker line(s) removed`);\r\n return finish(out.join(\"\\n\"), {\r\n action: \"update\",\r\n detail:\r\n `block ${opts.blockId} updated (hash ${recorded || \"?\"} → ${newHash})` +\r\n (notes.length > 0 ? `; ${notes.join(\"; \")}` : \"\"),\r\n changed: true,\r\n recovered: drifted || duplicates.length > 0 || strays.length > 0,\r\n });\r\n }\r\n\r\n if (strays.length > 0) {\r\n // Corruption recovery: strip ONLY the stray marker line(s) (never the text\r\n // between guessed boundaries), then proceed as not-found.\r\n const del = new Set(strays.map((s) => s.index));\r\n const cleaned = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\r\n return finish(appendBlock(cleaned, newLines, eol), {\r\n action: \"create\",\r\n detail:\r\n `block ${opts.blockId} appended after recovery: ${strays.length} stray ` +\r\n `marker line(s) removed (backup taken)`,\r\n changed: true,\r\n recovered: true,\r\n });\r\n }\r\n\r\n // Not found → append at EOF (one blank separator; whole file when empty).\r\n return finish(appendBlock(body, newLines, eol), {\r\n action: \"create\",\r\n detail: `block ${opts.blockId} appended (hash ${newHash})`,\r\n changed: true,\r\n recovered: false,\r\n });\r\n}\r\n\r\n/**\r\n * Mark ONE blank line adjacent to a removed begin..end region for deletion\r\n * (prefer the line before; never the post-final-newline \"\" sentinel).\r\n */\r\nfunction reclaimBlankLine(\r\n logical: string[],\r\n beginIdx: number,\r\n endIdx: number,\r\n del: Set<number>,\r\n lineCount: number,\r\n): void {\r\n const before = beginIdx - 1;\r\n if (before >= 0 && !del.has(before) && logical[before]!.trim() === \"\") {\r\n del.add(before);\r\n return;\r\n }\r\n const after = endIdx + 1;\r\n // The final \"\" element of split(\"\\n\") on a newline-terminated file is the\r\n // trailing-newline sentinel, not a blank line — leave it alone.\r\n const isSentinel = after === lineCount - 1 && logical[after] === \"\";\r\n if (after < lineCount && !isSentinel && !del.has(after) && logical[after]!.trim() === \"\") {\r\n del.add(after);\r\n }\r\n}\r\n\r\nexport interface RemoveBlocksOptions {\r\n /** Remove the block with EXACTLY this id… */\r\n blockId?: string;\r\n /** …or every block whose id starts with this prefix (e.g. `<connectorId>/`). */\r\n blockIdPrefix?: string;\r\n}\r\n\r\nexport interface RemoveRecord {\r\n blockId: string;\r\n action: \"remove\" | \"warn\";\r\n detail: string;\r\n}\r\n\r\nexport interface RemoveBlocksResult {\r\n text: string;\r\n changed: boolean;\r\n records: RemoveRecord[];\r\n /** True when the remaining text is whitespace-only (file-deletion candidate). */\r\n fileNowEmpty: boolean;\r\n /** True when a drifted block was removed or stray markers were stripped. */\r\n recovered: boolean;\r\n}\r\n\r\n/**\r\n * Remove every matching managed block (begin..end inclusive + at most ONE\r\n * adjacent blank separator line — no blank-line accumulation across cycles).\r\n * Drifted blocks are removed WITH a warn (uninstall intent is explicit; the\r\n * file wrapper backs the file up first). Stray matching markers are stripped\r\n * line-only with a warn. Pure; no I/O.\r\n */\r\nexport function removeBlocksFromText(raw: string, match: RemoveBlocksOptions): RemoveBlocksResult {\r\n const bom = raw.startsWith(\"\\uFEFF\");\r\n const body = bom ? raw.slice(1) : raw;\r\n const lines = body.split(\"\\n\");\r\n const logical = lines.map(stripCr);\r\n\r\n const matches = (id: string): boolean =>\r\n (match.blockId !== undefined && id === match.blockId) ||\r\n (match.blockIdPrefix !== undefined && id.startsWith(match.blockIdPrefix));\r\n\r\n const { pairs, strays } = pairMarkers(scanMarkers(logical));\r\n const targetPairs = pairs.filter((p) => matches(p.blockId));\r\n const targetStrays = strays.filter((s) => matches(s.blockId));\r\n\r\n if (targetPairs.length === 0 && targetStrays.length === 0) {\r\n return { text: raw, changed: false, records: [], fileNowEmpty: false, recovered: false };\r\n }\r\n\r\n const del = new Set<number>();\r\n const records: RemoveRecord[] = [];\r\n let recovered = false;\r\n\r\n for (const p of targetPairs) {\r\n const recorded = p.begin.hash ?? \"\";\r\n const actualHash = hashBlockContent(\r\n logical.slice(p.begin.index + 1, p.end.index).join(\"\\n\"),\r\n );\r\n for (let i = p.begin.index; i <= p.end.index; i++) del.add(i);\r\n reclaimBlankLine(logical, p.begin.index, p.end.index, del, lines.length);\r\n if (actualHash !== recorded) {\r\n recovered = true;\r\n records.push({\r\n blockId: p.blockId,\r\n action: \"warn\",\r\n detail:\r\n `block ${p.blockId} had in-block edits (recorded hash ${recorded}, found ` +\r\n `${actualHash}); removed anyway (backup taken)`,\r\n });\r\n }\r\n records.push({ blockId: p.blockId, action: \"remove\", detail: `block ${p.blockId} removed` });\r\n }\r\n for (const s of targetStrays) {\r\n del.add(s.index);\r\n recovered = true;\r\n records.push({\r\n blockId: s.blockId,\r\n action: \"warn\",\r\n detail: `stray ${s.kind} marker for ${s.blockId} removed (marker line only)`,\r\n });\r\n }\r\n\r\n const text = lines.filter((_, i) => !del.has(i)).join(\"\\n\");\r\n return {\r\n text: bom ? `\\uFEFF${text}` : text,\r\n changed: true,\r\n records,\r\n fileNowEmpty: text.trim() === \"\",\r\n recovered,\r\n };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// File-level wrappers (atomic write, backups, dry-run)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nexport interface BlockFileChange {\r\n action: \"create\" | \"update\" | \"skip\" | \"warn\" | \"remove\";\r\n path: string;\r\n detail: string;\r\n /** True when the FILE did not exist and this upsert created it (ledger fact). */\r\n createdFile: boolean;\r\n /** Set when a pre-mutation backup was written (destructive/recovery paths only). */\r\n backupPath?: string;\r\n /** Hash of the rendered inner region (ledger / doctor). */\r\n hash: string;\r\n}\r\n\r\n/** Timestamped copy into backupsDir(); best-effort (null on failure). */\r\nfunction backupFile(path: string): string | null {\r\n try {\r\n ensureDir(backupsDir());\r\n const stamp = new Date().toISOString().replace(/[:.]/g, \"-\");\r\n const dest = join(backupsDir(), `memory-${stamp}-${basename(path)}`);\r\n copyFileSync(path, dest);\r\n return dest;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Atomic write: temp file in the SAME directory + rename, preserving the\r\n * destination's mode. Shrinks (does not eliminate) the read-modify-write race\r\n * with hosts that append to memory files mid-session (Claude `#` quick-memory).\r\n */\r\nfunction atomicWriteFile(path: string, text: string): void {\r\n const dir = dirname(path);\r\n ensureDir(dir);\r\n const tmp = join(dir, `.${basename(path)}.ac-tmp-${process.pid}-${Date.now()}`);\r\n try {\r\n writeFileSync(tmp, text, \"utf8\");\r\n try {\r\n chmodSync(tmp, statSync(path).mode);\r\n } catch {\r\n /* destination absent — default mode is fine */\r\n }\r\n renameSync(tmp, path);\r\n } catch (err) {\r\n rmSync(tmp, { force: true });\r\n throw err;\r\n }\r\n}\r\n\r\n/**\r\n * Upsert one managed block into the file at `path` (created when absent).\r\n * Re-reads immediately before computing+writing; honors dryRun (the action is\r\n * computed and reported, nothing is written).\r\n */\r\nexport function upsertManagedBlockFile(\r\n path: string,\r\n opts: UpsertBlockOptions & { dryRun: boolean },\r\n): BlockFileChange {\r\n let raw: string | null = null;\r\n if (existsSync(path)) {\r\n try {\r\n raw = readFileSync(path, \"utf8\");\r\n } catch {\r\n return {\r\n action: \"warn\",\r\n path,\r\n detail: `cannot read ${path}; memory block ${opts.blockId} not written`,\r\n createdFile: false,\r\n hash: \"\",\r\n };\r\n }\r\n }\r\n\r\n if (raw === null) {\r\n const lines = renderBlockLines(opts);\r\n const hash = hashBlockContent(lines.slice(1, -1).join(\"\\n\"));\r\n if (!opts.dryRun) atomicWriteFile(path, `${lines.join(\"\\n\")}\\n`);\r\n return {\r\n action: \"create\",\r\n path,\r\n detail: `created ${basename(path)} with block ${opts.blockId} (hash ${hash})`,\r\n createdFile: true,\r\n hash,\r\n };\r\n }\r\n\r\n const res = upsertBlockInText(raw, opts);\r\n const change: BlockFileChange = {\r\n action: res.action,\r\n path,\r\n detail: res.detail,\r\n createdFile: false,\r\n hash: res.hash,\r\n };\r\n if (res.changed && !opts.dryRun) {\r\n if (res.recovered) {\r\n const backup = backupFile(path);\r\n if (backup) change.backupPath = backup;\r\n }\r\n atomicWriteFile(path, res.text);\r\n }\r\n return change;\r\n}\r\n\r\n/**\r\n * Remove every matching managed block from the file at `path`. Missing file or\r\n * no matching markers → a single idempotent \"skip\". When the remaining content\r\n * is whitespace-only AND `deleteFileIfCreated` is true (the ledger recorded\r\n * that agent-connector created this file), the file itself is deleted (Ruler\r\n * revert semantics: delete only what we created).\r\n */\r\nexport function removeManagedBlocksFile(\r\n path: string,\r\n match: RemoveBlocksOptions,\r\n opts: { dryRun: boolean; deleteFileIfCreated?: boolean },\r\n): BlockFileChange[] {\r\n if (!existsSync(path)) {\r\n return [\r\n {\r\n action: \"skip\",\r\n path,\r\n detail: `${basename(path)} absent; nothing to remove`,\r\n createdFile: false,\r\n hash: \"\",\r\n },\r\n ];\r\n }\r\n let raw: string;\r\n try {\r\n raw = readFileSync(path, \"utf8\");\r\n } catch {\r\n return [\r\n {\r\n action: \"warn\",\r\n path,\r\n detail: `cannot read ${path}; managed blocks left in place`,\r\n createdFile: false,\r\n hash: \"\",\r\n },\r\n ];\r\n }\r\n\r\n const res = removeBlocksFromText(raw, match);\r\n if (!res.changed) {\r\n return [\r\n {\r\n action: \"skip\",\r\n path,\r\n detail: `no agent-connector blocks matching ${match.blockId ?? match.blockIdPrefix ?? \"?\"} in ${basename(path)}`,\r\n createdFile: false,\r\n hash: \"\",\r\n },\r\n ];\r\n }\r\n\r\n const changes: BlockFileChange[] = [];\r\n let backupPath: string | undefined;\r\n if (!opts.dryRun) {\r\n if (res.recovered) backupPath = backupFile(path) ?? undefined;\r\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\r\n rmSync(path, { force: true });\r\n } else {\r\n atomicWriteFile(path, res.text);\r\n }\r\n }\r\n for (const r of res.records) {\r\n changes.push({\r\n action: r.action,\r\n path,\r\n detail: r.detail,\r\n createdFile: false,\r\n hash: \"\",\r\n ...(backupPath && r.action === \"warn\" ? { backupPath } : {}),\r\n });\r\n }\r\n if (res.fileNowEmpty && opts.deleteFileIfCreated) {\r\n changes.push({\r\n action: \"remove\",\r\n path,\r\n detail: `${basename(path)} deleted (agent-connector created it; only whitespace remained)`,\r\n createdFile: false,\r\n hash: \"\",\r\n });\r\n }\r\n return changes;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Memory ownership ledger — connectorDir(id)/memory-state.json\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nexport interface MemoryLedgerTarget {\r\n platform: string;\r\n scope: string;\r\n path: string;\r\n blockId: string;\r\n /** True when agent-connector CREATED the file (grants deletion rights). */\r\n createdFile: boolean;\r\n /** Inner-region hash we last wrote (doctor drift detection). */\r\n hash: string;\r\n}\r\n\r\nexport interface MemoryLedger {\r\n version: 1;\r\n targets: MemoryLedgerTarget[];\r\n}\r\n\r\nexport function memoryLedgerPath(connectorId: string): string {\r\n return join(connectorDir(connectorId), \"memory-state.json\");\r\n}\r\n\r\nexport function loadMemoryLedger(connectorId: string): MemoryLedger {\r\n const p = memoryLedgerPath(connectorId);\r\n if (!existsSync(p)) return { version: 1, targets: [] };\r\n try {\r\n const parsed = JSON.parse(readFileSync(p, \"utf8\")) as MemoryLedger;\r\n if (parsed && Array.isArray(parsed.targets)) return { version: 1, targets: parsed.targets };\r\n } catch {\r\n /* corrupt → fresh ledger; the markers remain the source of truth */\r\n }\r\n return { version: 1, targets: [] };\r\n}\r\n\r\n/** Persist the ledger; an EMPTY ledger deletes the file (no orphan state). */\r\nexport function saveMemoryLedger(connectorId: string, ledger: MemoryLedger): void {\r\n const p = memoryLedgerPath(connectorId);\r\n assertNoSymlinkInPath(p);\r\n if (ledger.targets.length === 0) {\r\n rmSync(p, { force: true });\r\n return;\r\n }\r\n ensureDir(dirname(p));\r\n writeFileSync(p, `${JSON.stringify(ledger, null, 2)}\\n`, \"utf8\");\r\n}\r\n\r\n/** True when the connector has any recorded memory targets (uninstall guard). */\r\nexport function hasMemoryLedger(connectorId: string): boolean {\r\n return loadMemoryLedger(connectorId).targets.length > 0;\r\n}\r\n\r\n/**\r\n * Upsert one ledger row (keyed by platform+scope+path+blockId). The\r\n * `createdFile` fact is STICKY: once we created the file, deletion rights\r\n * survive later syncs that found it present.\r\n */\r\nexport function recordMemoryTarget(ledger: MemoryLedger, t: MemoryLedgerTarget): void {\r\n const i = ledger.targets.findIndex(\r\n (x) =>\r\n x.platform === t.platform &&\r\n x.scope === t.scope &&\r\n x.path === t.path &&\r\n x.blockId === t.blockId,\r\n );\r\n if (i >= 0) {\r\n ledger.targets[i] = { ...t, createdFile: ledger.targets[i]!.createdFile || t.createdFile };\r\n } else {\r\n ledger.targets.push(t);\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ensureDir,
4
4
  telemetryPath
5
- } from "./chunk-GZGLCCEE.js";
5
+ } from "./chunk-QYOUQCC6.js";
6
6
 
7
7
  // src/telemetry/store.ts
8
8
  import { appendFileSync, existsSync, readFileSync } from "fs";
@@ -193,4 +193,4 @@ export {
193
193
  getTokenizer,
194
194
  inferModelFamily
195
195
  };
196
- //# sourceMappingURL=chunk-IVAWP6HH.js.map
196
+ //# sourceMappingURL=chunk-IOJDZJ72.js.map