@ken-jo/agent-connector 0.4.95 → 0.4.97

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 (378) 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-IPFDPOZU.js} +16 -16
  5. package/dist/action-IPFDPOZU.js.map +1 -0
  6. package/dist/{amazon-q-ETMAGY3D.js → amazon-q-IT44LEWV.js} +6 -6
  7. package/dist/amazon-q-IT44LEWV.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-P35FRU2Z.js} +7 -7
  11. package/dist/amp-P35FRU2Z.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-TWIWXTQH.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-MPE27LPI.js} +9 -9
  18. package/dist/antigravity-cli-MPE27LPI.js.map +1 -0
  19. package/dist/audit-3E5JAOP2.js +311 -0
  20. package/dist/audit-3E5JAOP2.js.map +1 -0
  21. package/dist/{chunk-PW42ZXCB.js → chunk-3EP5V2F4.js} +3 -3
  22. package/dist/chunk-3EP5V2F4.js.map +1 -0
  23. package/dist/{chunk-MGTDQLJJ.js → chunk-3FINQ2ZF.js} +4 -4
  24. package/dist/chunk-3FINQ2ZF.js.map +1 -0
  25. package/dist/{chunk-KHO5WNTP.js → chunk-4GH2KA7V.js} +1 -1
  26. package/dist/chunk-4GH2KA7V.js.map +1 -0
  27. package/dist/{chunk-2Y2MZRLP.js → chunk-7C2IPIIB.js} +3 -3
  28. package/dist/chunk-7C2IPIIB.js.map +1 -0
  29. package/dist/{chunk-NLE2J5P4.js → chunk-7HHW23AC.js} +29 -29
  30. package/dist/chunk-7HHW23AC.js.map +1 -0
  31. package/dist/{chunk-XD7MY6HB.js → chunk-7PSNXUFK.js} +1 -1
  32. package/dist/chunk-7PSNXUFK.js.map +1 -0
  33. package/dist/{chunk-5IOTP7LQ.js → chunk-7ZFK2WEO.js} +7 -5
  34. package/dist/chunk-7ZFK2WEO.js.map +1 -0
  35. package/dist/{chunk-XC5SJ35F.js → chunk-C63AAXK7.js} +5 -5
  36. package/dist/chunk-C63AAXK7.js.map +1 -0
  37. package/dist/{chunk-UM5S7DKK.js → chunk-C747DYNT.js} +1 -1
  38. package/dist/chunk-C747DYNT.js.map +1 -0
  39. package/dist/{chunk-YPAXJ7EW.js → chunk-FHYR5Q5T.js} +13 -13
  40. package/dist/chunk-FHYR5Q5T.js.map +1 -0
  41. package/dist/{chunk-I5UXHIDT.js → chunk-GCPEPUD7.js} +8 -8
  42. package/dist/chunk-GCPEPUD7.js.map +1 -0
  43. package/dist/{chunk-ISEJWBFF.js → chunk-GZZCHJDP.js} +2 -2
  44. package/dist/chunk-GZZCHJDP.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-7F5KHLEP.js → chunk-L2C5UMKW.js} +4 -4
  54. package/dist/chunk-L2C5UMKW.js.map +1 -0
  55. package/dist/{chunk-OP4KBXUO.js → chunk-LFWYYWLV.js} +1 -1
  56. package/dist/chunk-LFWYYWLV.js.map +1 -0
  57. package/dist/{chunk-APZDTY76.js → chunk-LQ55E7QI.js} +7 -7
  58. package/dist/chunk-LQ55E7QI.js.map +1 -0
  59. package/dist/{chunk-PAPMUAR5.js → chunk-MLU7NDAZ.js} +12 -12
  60. package/dist/chunk-MLU7NDAZ.js.map +1 -0
  61. package/dist/{chunk-H33M77DD.js → chunk-N4ENLZEU.js} +22 -19
  62. package/dist/chunk-N4ENLZEU.js.map +1 -0
  63. package/dist/{chunk-D4ELPBB5.js → chunk-NDMNMAKP.js} +43 -43
  64. package/dist/chunk-NDMNMAKP.js.map +1 -0
  65. package/dist/{chunk-H53QZQJI.js → chunk-PSGTHJQU.js} +1 -1
  66. package/dist/chunk-PSGTHJQU.js.map +1 -0
  67. package/dist/{chunk-FBJQGRET.js → chunk-Q4ISQHUQ.js} +1 -1
  68. package/dist/chunk-Q4ISQHUQ.js.map +1 -0
  69. package/dist/{chunk-6TF7MHG5.js → chunk-Q7PR2WGT.js} +2 -2
  70. package/dist/chunk-Q7PR2WGT.js.map +1 -0
  71. package/dist/{chunk-GZGLCCEE.js → chunk-QYOUQCC6.js} +1 -1
  72. package/dist/chunk-QYOUQCC6.js.map +1 -0
  73. package/dist/{chunk-Z2MRSS2I.js → chunk-SLJI5BOM.js} +2 -2
  74. package/dist/chunk-SLJI5BOM.js.map +1 -0
  75. package/dist/{chunk-JKKU2WKG.js → chunk-TGZFDXNH.js} +4 -4
  76. package/dist/chunk-TGZFDXNH.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-MQPNU2CY.js → chunk-UZZTWWGG.js} +1 -1
  80. package/dist/chunk-UZZTWWGG.js.map +1 -0
  81. package/dist/{chunk-3NH2ARIS.js → chunk-WPTNMYYM.js} +2 -2
  82. package/dist/chunk-WPTNMYYM.js.map +1 -0
  83. package/dist/{chunk-OPXAP3AC.js → chunk-XN7S44U4.js} +1 -1
  84. package/dist/chunk-XN7S44U4.js.map +1 -0
  85. package/dist/{chunk-6WZODR3Z.js → chunk-XVEJAFKW.js} +5 -5
  86. package/dist/chunk-XVEJAFKW.js.map +1 -0
  87. package/dist/{chunk-BEFVJ2OE.js → chunk-XXLCMSD3.js} +1 -1
  88. package/dist/chunk-XXLCMSD3.js.map +1 -0
  89. package/dist/{chunk-YT43MUSJ.js → chunk-XZWMJLIT.js} +1 -1
  90. package/dist/chunk-XZWMJLIT.js.map +1 -0
  91. package/dist/{chunk-4NHXLXSD.js → chunk-Y3K6KJMS.js} +2 -2
  92. package/dist/chunk-Y3K6KJMS.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-QBWDT5RT.js} +11 -11
  98. package/dist/claude-code-QBWDT5RT.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-JKEAYWVR.js} +6 -6
  104. package/dist/cline-JKEAYWVR.js.map +1 -0
  105. package/dist/{codebuddy-ZNYQACMF.js → codebuddy-EB6EYPC3.js} +7 -7
  106. package/dist/codebuddy-EB6EYPC3.js.map +1 -0
  107. package/dist/{codebuff-VR6JUDIY.js → codebuff-5RSXFU6G.js} +6 -6
  108. package/dist/codebuff-5RSXFU6G.js.map +1 -0
  109. package/dist/{codebuff-ETYT5UBL.js → codebuff-6KWBW6CT.js} +4 -4
  110. package/dist/codebuff-6KWBW6CT.js.map +1 -0
  111. package/dist/{codex-CPNKTXG3.js → codex-ART46CDD.js} +9 -9
  112. package/dist/codex-ART46CDD.js.map +1 -0
  113. package/dist/{codex-YAORPCOD.js → codex-DKBAAUCO.js} +4 -4
  114. package/dist/codex-DKBAAUCO.js.map +1 -0
  115. package/dist/{continue-WU2IB5KS.js → continue-JHZCMSPH.js} +8 -8
  116. package/dist/continue-JHZCMSPH.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-QVAU5CFM.js} +7 -7
  120. package/dist/copilot-cli-QVAU5CFM.js.map +1 -0
  121. package/dist/{crush-3AVQA4YU.js → crush-7TORBYUL.js} +7 -7
  122. package/dist/crush-7TORBYUL.js.map +1 -0
  123. package/dist/{crush-QBXLNN7T.js → crush-A5C5USRL.js} +4 -4
  124. package/dist/crush-A5C5USRL.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-W7I4QUFO.js +22 -0
  128. package/dist/{detect-6V4LC3MA.js → detect-JHSA3G3U.js} +4 -4
  129. package/dist/detect-JHSA3G3U.js.map +1 -0
  130. package/dist/{devin-QMEM3OFA.js → devin-SSR7S4WX.js} +7 -7
  131. package/dist/devin-SSR7S4WX.js.map +1 -0
  132. package/dist/{doctor-2YDUVSAU.js → doctor-CQJ7TZPA.js} +26 -26
  133. package/dist/doctor-CQJ7TZPA.js.map +1 -0
  134. package/dist/{droid-MOKV53J4.js → droid-45PJ7JGF.js} +7 -7
  135. package/dist/droid-45PJ7JGF.js.map +1 -0
  136. package/dist/{droid-U3ZBLQFO.js → droid-PFQ2PZSF.js} +4 -4
  137. package/dist/droid-PFQ2PZSF.js.map +1 -0
  138. package/dist/{gemini-cli-47ZHCOZR.js → gemini-cli-24PFDK7D.js} +8 -8
  139. package/dist/gemini-cli-24PFDK7D.js.map +1 -0
  140. package/dist/{gemini-cli-NMVVBO3K.js → gemini-cli-Y6RJMU24.js} +4 -4
  141. package/dist/gemini-cli-Y6RJMU24.js.map +1 -0
  142. package/dist/{goose-64V46Y2W.js → goose-K2HKUTBK.js} +4 -4
  143. package/dist/goose-K2HKUTBK.js.map +1 -0
  144. package/dist/{goose-4EI5MYTI.js → goose-U5D3LCPC.js} +9 -9
  145. package/dist/goose-U5D3LCPC.js.map +1 -0
  146. package/dist/{grok-cli-QYQPDSVB.js → grok-cli-L2MHAPBY.js} +7 -7
  147. package/dist/grok-cli-L2MHAPBY.js.map +1 -0
  148. package/dist/{hermes-F75OSK3Y.js → hermes-2S5JUTTJ.js} +7 -7
  149. package/dist/hermes-2S5JUTTJ.js.map +1 -0
  150. package/dist/{hermes-F3EGTK6N.js → hermes-MF3NX4ZY.js} +4 -4
  151. package/dist/hermes-MF3NX4ZY.js.map +1 -0
  152. package/dist/{hook-OEVRDMXD.js → hook-VHICXHXL.js} +16 -16
  153. package/dist/hook-VHICXHXL.js.map +1 -0
  154. package/dist/index.js +5 -5
  155. package/dist/{install-5NMCUDG5.js → install-WLENR4KF.js} +192 -28
  156. package/dist/install-WLENR4KF.js.map +1 -0
  157. package/dist/{jetbrains-copilot-ZGIWI6YV.js → jetbrains-copilot-Z4FC3RM3.js} +6 -6
  158. package/dist/jetbrains-copilot-Z4FC3RM3.js.map +1 -0
  159. package/dist/{junie-DIFN2P22.js → junie-ULGJJIHB.js} +6 -6
  160. package/dist/junie-ULGJJIHB.js.map +1 -0
  161. package/dist/{kilo-SW7BH6EG.js → kilo-SMHPOHJ5.js} +4 -4
  162. package/dist/kilo-SMHPOHJ5.js.map +1 -0
  163. package/dist/{kilo-EMZJBEBB.js → kilo-WWIJOVWD.js} +8 -8
  164. package/dist/kilo-WWIJOVWD.js.map +1 -0
  165. package/dist/{kilo-cli-S3GXBPAE.js → kilo-cli-QKE2EQLS.js} +8 -8
  166. package/dist/kilo-cli-QKE2EQLS.js.map +1 -0
  167. package/dist/{kilo-cli-ZF272ZHN.js → kilo-cli-T2SRRRJS.js} +5 -5
  168. package/dist/kilo-cli-T2SRRRJS.js.map +1 -0
  169. package/dist/{kimi-IQJOIY6B.js → kimi-JMUFTVSF.js} +7 -7
  170. package/dist/kimi-JMUFTVSF.js.map +1 -0
  171. package/dist/{kimi-5FHEXGZD.js → kimi-MSIDEMCI.js} +4 -4
  172. package/dist/kimi-MSIDEMCI.js.map +1 -0
  173. package/dist/{kiro-WGOI5CGT.js → kiro-NYRRBIKW.js} +4 -4
  174. package/dist/kiro-NYRRBIKW.js.map +1 -0
  175. package/dist/{kiro-BYX4HEAJ.js → kiro-UWUCRKR3.js} +7 -7
  176. package/dist/kiro-UWUCRKR3.js.map +1 -0
  177. package/dist/{leaderboard-XEKS7B3H.js → leaderboard-NJWKGMXP.js} +7 -7
  178. package/dist/leaderboard-NJWKGMXP.js.map +1 -0
  179. package/dist/{mimo-code-7R53QDHB.js → mimo-code-BPNYYIVM.js} +7 -7
  180. package/dist/mimo-code-BPNYYIVM.js.map +1 -0
  181. package/dist/{mistral-vibe-LHJ55FSB.js → mistral-vibe-LT3DAJ3L.js} +6 -6
  182. package/dist/mistral-vibe-LT3DAJ3L.js.map +1 -0
  183. package/dist/{mux-XM6AP35L.js → mux-7PIJ7HUQ.js} +4 -4
  184. package/dist/mux-7PIJ7HUQ.js.map +1 -0
  185. package/dist/{mux-NYCNGL43.js → mux-AHNUAY5Z.js} +6 -6
  186. package/dist/mux-AHNUAY5Z.js.map +1 -0
  187. package/dist/{nemoclaw-WSIPSE7U.js → nemoclaw-RE5RZASZ.js} +7 -7
  188. package/dist/nemoclaw-RE5RZASZ.js.map +1 -0
  189. package/dist/{omp-562NK5BJ.js → omp-D2EXEPH7.js} +7 -7
  190. package/dist/omp-D2EXEPH7.js.map +1 -0
  191. package/dist/{open-interpreter-I2CNOEXY.js → open-interpreter-SSGBEUKX.js} +6 -6
  192. package/dist/open-interpreter-SSGBEUKX.js.map +1 -0
  193. package/dist/openclaw-IJ33K45M.js +17 -0
  194. package/dist/{openclaw-5EQFGOWL.js → openclaw-KAFTNLR2.js} +4 -4
  195. package/dist/openclaw-KAFTNLR2.js.map +1 -0
  196. package/dist/{opencode-YS4WX2E2.js → opencode-YKUKZY3J.js} +7 -7
  197. package/dist/opencode-YKUKZY3J.js.map +1 -0
  198. package/dist/{opencode-QGP4ALQY.js → opencode-Z65JYILL.js} +4 -4
  199. package/dist/opencode-Z65JYILL.js.map +1 -0
  200. package/dist/{openhands-QMYIKNOS.js → openhands-SEZMCUC3.js} +7 -7
  201. package/dist/openhands-SEZMCUC3.js.map +1 -0
  202. package/dist/{package-G25GVTH2.js → package-JECVQEFT.js} +15 -15
  203. package/dist/package-JECVQEFT.js.map +1 -0
  204. package/dist/{pi-GGDQREVG.js → pi-DLKCPOJE.js} +4 -4
  205. package/dist/pi-DLKCPOJE.js.map +1 -0
  206. package/dist/{pi-644FIN3A.js → pi-YPYV2ULH.js} +6 -6
  207. package/dist/pi-YPYV2ULH.js.map +1 -0
  208. package/dist/{qwen-code-GQILBJ5B.js → qwen-code-26CSFDX6.js} +4 -4
  209. package/dist/qwen-code-26CSFDX6.js.map +1 -0
  210. package/dist/{qwen-code-STDMX7EM.js → qwen-code-ZHCLCYMC.js} +9 -9
  211. package/dist/qwen-code-ZHCLCYMC.js.map +1 -0
  212. package/dist/{roo-code-DLPIHHQ6.js → roo-code-7F4HYB34.js} +6 -6
  213. package/dist/roo-code-7F4HYB34.js.map +1 -0
  214. package/dist/{roo-code-SUWI4BBN.js → roo-code-HSAE2CJU.js} +4 -4
  215. package/dist/roo-code-HSAE2CJU.js.map +1 -0
  216. package/dist/runtime/index.js +14 -14
  217. package/dist/sdk/index.js +6 -6
  218. package/dist/sdk/index.js.map +1 -1
  219. package/dist/sdk/test.js +11 -11
  220. package/dist/{serve-XTMIUHKK.js → serve-LYSBH43G.js} +16 -16
  221. package/dist/serve-LYSBH43G.js.map +1 -0
  222. package/dist/{status-VJAGO4Z7.js → status-PHKKGEW5.js} +11 -11
  223. package/dist/status-PHKKGEW5.js.map +1 -0
  224. package/dist/{statusline-EY2E2UGF.js → statusline-ZDD4OZ4F.js} +15 -15
  225. package/dist/statusline-ZDD4OZ4F.js.map +1 -0
  226. package/dist/{synthetic-6FRA7P5Q.js → synthetic-LUT6V6SD.js} +4 -4
  227. package/dist/synthetic-LUT6V6SD.js.map +1 -0
  228. package/dist/{telemetry-OLZQBADT.js → telemetry-HDGMI2BK.js} +10 -10
  229. package/dist/telemetry-HDGMI2BK.js.map +1 -0
  230. package/dist/{trae-CPPYASR2.js → trae-SIQI3C66.js} +4 -4
  231. package/dist/trae-SIQI3C66.js.map +1 -0
  232. package/dist/{trae-UOYD6JZZ.js → trae-Y67HSDOW.js} +6 -6
  233. package/dist/trae-Y67HSDOW.js.map +1 -0
  234. package/dist/{uninstall-AZEUPAND.js → uninstall-RWO2GM2I.js} +21 -21
  235. package/dist/uninstall-RWO2GM2I.js.map +1 -0
  236. package/dist/{upgrade-CAUUHSSC.js → upgrade-YJCXNUEE.js} +21 -21
  237. package/dist/upgrade-YJCXNUEE.js.map +1 -0
  238. package/dist/{usage-3KHZ4RYZ.js → usage-IWO4RQN6.js} +4 -4
  239. package/dist/usage-IWO4RQN6.js.map +1 -0
  240. package/dist/{usage-event-TZWOZPRJ.js → usage-event-AFFKCLHE.js} +15 -15
  241. package/dist/usage-event-AFFKCLHE.js.map +1 -0
  242. package/dist/{vscode-copilot-NIMH2DGU.js → vscode-copilot-5CI5B3X6.js} +7 -7
  243. package/dist/vscode-copilot-5CI5B3X6.js.map +1 -0
  244. package/dist/{warp-NRBBJQR2.js → warp-5YBSP7FP.js} +4 -4
  245. package/dist/warp-5YBSP7FP.js.map +1 -0
  246. package/dist/{warp-QYJGKURM.js → warp-INAKVGBV.js} +6 -6
  247. package/dist/warp-INAKVGBV.js.map +1 -0
  248. package/dist/{windsurf-75LLZ37C.js → windsurf-4HM57QAY.js} +6 -6
  249. package/dist/windsurf-4HM57QAY.js.map +1 -0
  250. package/dist/{zed-XJFOOKCO.js → zed-XXCNYOIN.js} +4 -4
  251. package/dist/zed-XXCNYOIN.js.map +1 -0
  252. package/dist/{zed-HKAZXEJW.js → zed-YN5X37PQ.js} +7 -7
  253. package/dist/zed-YN5X37PQ.js.map +1 -0
  254. package/package.json +92 -88
  255. package/dist/action-Q7GGO4PA.js.map +0 -1
  256. package/dist/amazon-q-ETMAGY3D.js.map +0 -1
  257. package/dist/amp-67BZONGF.js.map +0 -1
  258. package/dist/amp-BQZOL5GR.js.map +0 -1
  259. package/dist/antigravity-EA4L225L.js.map +0 -1
  260. package/dist/antigravity-VXLDLTO7.js +0 -18
  261. package/dist/antigravity-cli-B2HXZFYQ.js.map +0 -1
  262. package/dist/antigravity-cli-OM6SC3PE.js.map +0 -1
  263. package/dist/chunk-2Y2MZRLP.js.map +0 -1
  264. package/dist/chunk-3NH2ARIS.js.map +0 -1
  265. package/dist/chunk-4NHXLXSD.js.map +0 -1
  266. package/dist/chunk-5IOTP7LQ.js.map +0 -1
  267. package/dist/chunk-6TF7MHG5.js.map +0 -1
  268. package/dist/chunk-6WZODR3Z.js.map +0 -1
  269. package/dist/chunk-7F5KHLEP.js.map +0 -1
  270. package/dist/chunk-APZDTY76.js.map +0 -1
  271. package/dist/chunk-BEFVJ2OE.js.map +0 -1
  272. package/dist/chunk-D4ELPBB5.js.map +0 -1
  273. package/dist/chunk-FBJQGRET.js.map +0 -1
  274. package/dist/chunk-FJCUKXGX.js.map +0 -1
  275. package/dist/chunk-GZGLCCEE.js.map +0 -1
  276. package/dist/chunk-H33M77DD.js.map +0 -1
  277. package/dist/chunk-H53QZQJI.js.map +0 -1
  278. package/dist/chunk-I5UXHIDT.js.map +0 -1
  279. package/dist/chunk-ISEJWBFF.js.map +0 -1
  280. package/dist/chunk-IVAWP6HH.js.map +0 -1
  281. package/dist/chunk-JKKU2WKG.js.map +0 -1
  282. package/dist/chunk-KHO5WNTP.js.map +0 -1
  283. package/dist/chunk-MGTDQLJJ.js.map +0 -1
  284. package/dist/chunk-MQPNU2CY.js.map +0 -1
  285. package/dist/chunk-NBYKLUF6.js.map +0 -1
  286. package/dist/chunk-NLE2J5P4.js.map +0 -1
  287. package/dist/chunk-O7SDRBVB.js.map +0 -1
  288. package/dist/chunk-OP4KBXUO.js.map +0 -1
  289. package/dist/chunk-OPXAP3AC.js.map +0 -1
  290. package/dist/chunk-PAPMUAR5.js.map +0 -1
  291. package/dist/chunk-PW42ZXCB.js.map +0 -1
  292. package/dist/chunk-RK6VBLXP.js.map +0 -1
  293. package/dist/chunk-UM5S7DKK.js.map +0 -1
  294. package/dist/chunk-UMQ6NBQR.js.map +0 -1
  295. package/dist/chunk-XC5SJ35F.js.map +0 -1
  296. package/dist/chunk-XD7MY6HB.js.map +0 -1
  297. package/dist/chunk-YPAXJ7EW.js.map +0 -1
  298. package/dist/chunk-YT43MUSJ.js.map +0 -1
  299. package/dist/chunk-Z2MRSS2I.js.map +0 -1
  300. package/dist/claude-code-GRWO6XBZ.js.map +0 -1
  301. package/dist/claude-code-NMRKTAP7.js.map +0 -1
  302. package/dist/cline-25KW25IN.js.map +0 -1
  303. package/dist/codebuddy-ZNYQACMF.js.map +0 -1
  304. package/dist/codebuff-ETYT5UBL.js.map +0 -1
  305. package/dist/codebuff-VR6JUDIY.js.map +0 -1
  306. package/dist/codex-CPNKTXG3.js.map +0 -1
  307. package/dist/codex-YAORPCOD.js.map +0 -1
  308. package/dist/continue-WU2IB5KS.js.map +0 -1
  309. package/dist/copilot-cli-MZTAWMPW.js.map +0 -1
  310. package/dist/copilot-cli-PAP377OM.js.map +0 -1
  311. package/dist/crush-3AVQA4YU.js.map +0 -1
  312. package/dist/crush-QBXLNN7T.js.map +0 -1
  313. package/dist/cursor-DIW43TRZ.js.map +0 -1
  314. package/dist/cursor-GSLUET3V.js +0 -22
  315. package/dist/detect-6V4LC3MA.js.map +0 -1
  316. package/dist/devin-QMEM3OFA.js.map +0 -1
  317. package/dist/doctor-2YDUVSAU.js.map +0 -1
  318. package/dist/droid-MOKV53J4.js.map +0 -1
  319. package/dist/droid-U3ZBLQFO.js.map +0 -1
  320. package/dist/gemini-cli-47ZHCOZR.js.map +0 -1
  321. package/dist/gemini-cli-NMVVBO3K.js.map +0 -1
  322. package/dist/goose-4EI5MYTI.js.map +0 -1
  323. package/dist/goose-64V46Y2W.js.map +0 -1
  324. package/dist/grok-cli-QYQPDSVB.js.map +0 -1
  325. package/dist/hermes-F3EGTK6N.js.map +0 -1
  326. package/dist/hermes-F75OSK3Y.js.map +0 -1
  327. package/dist/hook-OEVRDMXD.js.map +0 -1
  328. package/dist/install-5NMCUDG5.js.map +0 -1
  329. package/dist/jetbrains-copilot-ZGIWI6YV.js.map +0 -1
  330. package/dist/junie-DIFN2P22.js.map +0 -1
  331. package/dist/kilo-EMZJBEBB.js.map +0 -1
  332. package/dist/kilo-SW7BH6EG.js.map +0 -1
  333. package/dist/kilo-cli-S3GXBPAE.js.map +0 -1
  334. package/dist/kilo-cli-ZF272ZHN.js.map +0 -1
  335. package/dist/kimi-5FHEXGZD.js.map +0 -1
  336. package/dist/kimi-IQJOIY6B.js.map +0 -1
  337. package/dist/kiro-BYX4HEAJ.js.map +0 -1
  338. package/dist/kiro-WGOI5CGT.js.map +0 -1
  339. package/dist/leaderboard-XEKS7B3H.js.map +0 -1
  340. package/dist/mimo-code-7R53QDHB.js.map +0 -1
  341. package/dist/mistral-vibe-LHJ55FSB.js.map +0 -1
  342. package/dist/mux-NYCNGL43.js.map +0 -1
  343. package/dist/mux-XM6AP35L.js.map +0 -1
  344. package/dist/nemoclaw-WSIPSE7U.js.map +0 -1
  345. package/dist/omp-562NK5BJ.js.map +0 -1
  346. package/dist/open-interpreter-I2CNOEXY.js.map +0 -1
  347. package/dist/openclaw-5EQFGOWL.js.map +0 -1
  348. package/dist/openclaw-7EYBQS4R.js +0 -17
  349. package/dist/opencode-QGP4ALQY.js.map +0 -1
  350. package/dist/opencode-YS4WX2E2.js.map +0 -1
  351. package/dist/openhands-QMYIKNOS.js.map +0 -1
  352. package/dist/package-G25GVTH2.js.map +0 -1
  353. package/dist/pi-644FIN3A.js.map +0 -1
  354. package/dist/pi-GGDQREVG.js.map +0 -1
  355. package/dist/qwen-code-GQILBJ5B.js.map +0 -1
  356. package/dist/qwen-code-STDMX7EM.js.map +0 -1
  357. package/dist/roo-code-DLPIHHQ6.js.map +0 -1
  358. package/dist/roo-code-SUWI4BBN.js.map +0 -1
  359. package/dist/serve-XTMIUHKK.js.map +0 -1
  360. package/dist/status-VJAGO4Z7.js.map +0 -1
  361. package/dist/statusline-EY2E2UGF.js.map +0 -1
  362. package/dist/synthetic-6FRA7P5Q.js.map +0 -1
  363. package/dist/telemetry-OLZQBADT.js.map +0 -1
  364. package/dist/trae-CPPYASR2.js.map +0 -1
  365. package/dist/trae-UOYD6JZZ.js.map +0 -1
  366. package/dist/uninstall-AZEUPAND.js.map +0 -1
  367. package/dist/upgrade-CAUUHSSC.js.map +0 -1
  368. package/dist/usage-3KHZ4RYZ.js.map +0 -1
  369. package/dist/usage-event-TZWOZPRJ.js.map +0 -1
  370. package/dist/vscode-copilot-NIMH2DGU.js.map +0 -1
  371. package/dist/warp-NRBBJQR2.js.map +0 -1
  372. package/dist/warp-QYJGKURM.js.map +0 -1
  373. package/dist/windsurf-75LLZ37C.js.map +0 -1
  374. package/dist/zed-HKAZXEJW.js.map +0 -1
  375. package/dist/zed-XJFOOKCO.js.map +0 -1
  376. /package/dist/{antigravity-VXLDLTO7.js.map → antigravity-TWIWXTQH.js.map} +0 -0
  377. /package/dist/{cursor-GSLUET3V.js.map → cursor-W7I4QUFO.js.map} +0 -0
  378. /package/dist/{openclaw-7EYBQS4R.js.map → openclaw-IJ33K45M.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/qwen-code/index.ts"],"sourcesContent":["/**\r\n * adapters/qwen-code — Qwen Code (Qwen CLI) platform adapter for agent-connector.\r\n *\r\n * Qwen Code is a Gemini-CLI-derived host, but — unlike Gemini CLI — its hook\r\n * WIRE PROTOCOL is Claude-compatible (verified against context-mode's proven\r\n * qwen-code adapter, which extends the shared ClaudeCodeBaseAdapter):\r\n *\r\n * - Hook event names are PascalCase, identical to Claude Code:\r\n * PreToolUse, PostToolUse, PreCompact, SessionStart, SessionEnd,\r\n * UserPromptSubmit, Stop, Notification — plus the E1 extension events\r\n * PermissionRequest, PostToolUseFailure, SubagentStart and SubagentStop,\r\n * all Qwen-native (verified against the upstream\r\n * docs/users/features/hooks.md: PermissionRequest takes the nested\r\n * hookSpecificOutput.decision{behavior} envelope, PostToolUseFailure /\r\n * SubagentStart are additionalContext feedback, and the Stop-class events\r\n * Stop / SubagentStop / UserPromptSubmit / PostToolUse block via the\r\n * TOP-LEVEL {\"decision\":\"block\",\"reason\"} shape — only PreToolUse uses\r\n * hookSpecificOutput.permissionDecision for deny).\r\n * (NOT Gemini's BeforeTool/AfterTool/PreCompress vocabulary.)\r\n * - Hook stdin JSON carries snake_case fields: session_id, transcript_path,\r\n * cwd, tool_name, tool_input, tool_response, source, reason, prompt,\r\n * trigger, stop_hook_active, message.\r\n * - Reply is exit-code 0 + a `hookSpecificOutput` JSON object on stdout\r\n * (permissionDecision allow|deny|ask, updatedInput, additionalContext) —\r\n * the Claude reply shape. Qwen's PreToolUse CAN rewrite tool input\r\n * (updatedInput; capabilities.canModifyArgs = true), but — verified against\r\n * qwen 0.17.1 — there is NO `updatedMCPToolOutput` honor on PostToolUse, so\r\n * this host CANNOT rewrite already-emitted tool output\r\n * (capabilities.canModifyOutput = false, like the Claude-family hosts).\r\n * - Native tool names are Qwen/Gemini-flavored (run_shell_command, read_file,\r\n * write_file, grep_search, …) — used only inside matcher strings; the wire\r\n * field names are unchanged from Claude.\r\n *\r\n * Native config (JSONC — Qwen shares Gemini's tolerant settings loader; we write\r\n * strict JSON and MERGE into any existing settings so user keys survive):\r\n * - MCP servers: user → ~/.qwen/settings.json; project → <projectDir>/.qwen/\r\n * settings.json. Root key \"mcpServers\". Qwen is a Gemini-CLI fork, so — like\r\n * Gemini — the MCP TRANSPORT IS SELECTED BY WHICH KEY IS PRESENT, not a\r\n * `type` field: stdio → {command,args,env(,cwd)}; SSE → {url, headers?};\r\n * streamable-HTTP → {httpUrl, headers?}.\r\n * - Hooks: the SAME settings.json, top-level sibling \"hooks\" key, keyed by the\r\n * PascalCase event name, each value an array of\r\n * `{ matcher, hooks:[{ type:\"command\", command }] }`.\r\n *\r\n * Env handling: Qwen's settings loader has no `${env:VAR}` interpolation of our\r\n * framework's dialect, so env / header / url refs resolve to literals at install\r\n * time via resolveEnvRefsDeep — the safe default shared with the Gemini / Codex\r\n * adapters.\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, MemoryTarget, 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 JsonValue,\r\n NotificationEvent,\r\n PermissionRequestEvent,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostToolUseEvent,\r\n PostToolUseFailureEvent,\r\n PostCompactEvent,\r\n PreCompactEvent,\r\n PreToolUseEvent,\r\n ServerDef,\r\n SessionEndEvent,\r\n SessionStartEvent,\r\n SkillDef,\r\n StatuslineContext,\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 { renderSkillMd } from \"../claude-code/render.js\";\r\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\r\nimport { writeTomlString } from \"../../core/toml.js\";\r\nimport {\r\n buildHomeBinStatuslineCommand,\r\n buildWrappedStdio,\r\n isHomeBinHookCommand,\r\n isHomeBinStatuslineCommand,\r\n} from \"../../core/spawn.js\";\r\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\r\nimport {\r\n type ConfigPatchLedgerEntry,\r\n addLedgerOwner,\r\n createLedgerEntry,\r\n describeJsonValue,\r\n dropLedgerEntry,\r\n findLedgerEntry,\r\n hashJsonValue,\r\n jsonDeepEquals,\r\n ledgerEntriesOwnedBy,\r\n loadConfigPatchLedger,\r\n removeLedgerOwner,\r\n saveConfigPatchLedger,\r\n} from \"../../core/config-patch-ledger.js\";\r\n\r\nconst HOST: PlatformId = \"qwen-code\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * settings.json leaf key the statusline surface owns on Qwen. UNLIKE claude-code\r\n * (a top-level `statusLine` leaf), Qwen nests its status-line config under `ui`\r\n * (`{ ui: { statusLine: { type:\"command\", command, refreshInterval? } } }` in\r\n * ~/.qwen/settings.json; verified against the qwen-code status-line docs and\r\n * QwenLM/qwen-code settings.md, shipped v0.14.3 / PR #2923). We own the\r\n * `ui.statusLine` leaf via the SAME refcounted ownership ledger as configPatch\r\n * (the ledger is surface-agnostic) — never clobbering a `ui.statusLine` a user\r\n * already set.\r\n */\r\nconst STATUSLINE_KEY = \"ui.statusLine\";\r\n\r\n/** A single hook registration entry as Qwen stores it (Claude-shaped, nested). */\r\ninterface QwenHookEntry {\r\n matcher: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/** Shape of Qwen's settings.json (only the parts we touch). */\r\ninterface QwenSettingsFile {\r\n mcpServers?: Record<string, unknown>;\r\n hooks?: Record<string, QwenHookEntry[]>;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Qwen's statusLine command stdin payload (the documented status-line input Qwen\r\n * pipes to the command, read once). Every field optional — a refresh only carries\r\n * what the host knows. Unmodeled fields (version, git, metrics, vim) stay in\r\n * StatuslineContext.raw. Sources: qwenlm.github.io/qwen-code-docs status-line page,\r\n * QwenLM/qwen-code settings.md.\r\n */\r\ninterface QwenStatuslineInput {\r\n session_id?: string;\r\n version?: string;\r\n model?: { display_name?: string };\r\n context_window?: {\r\n context_window_size?: number;\r\n used_percentage?: number;\r\n remaining_percentage?: number;\r\n current_usage?: number;\r\n total_input_tokens?: number;\r\n total_output_tokens?: number;\r\n };\r\n workspace?: { current_dir?: string };\r\n git?: { branch?: string };\r\n vim?: { mode?: string };\r\n}\r\n\r\n/**\r\n * Native MCP server entry shapes Qwen accepts under `mcpServers`. Qwen is a\r\n * Gemini-CLI fork, so the REMOTE transport is selected by WHICH KEY is present\r\n * (NOT a `type` field): SSE → `url`, streamable-HTTP → `httpUrl`. The stdio\r\n * entry keeps its (harmless, Claude-style) `type:\"stdio\"` tag — Qwen accepts it\r\n * and stdio is unambiguous by its command/args anyway.\r\n */\r\ninterface QwenStdioServer {\r\n type: \"stdio\";\r\n command: string;\r\n args: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\ninterface QwenSseServer {\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\ninterface QwenHttpServer {\r\n httpUrl: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\n/** Raw Qwen hook stdin payload (Claude-compatible snake_case wire fields). */\r\ninterface QwenWireInput {\r\n session_id?: string;\r\n transcript_path?: string;\r\n cwd?: string;\r\n hook_event_name?: string;\r\n\r\n // tool events\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n /** PostToolUse result payload (string or structured). */\r\n tool_response?: unknown;\r\n\r\n // PermissionRequest — suggested permission entries the dialog would offer.\r\n permission_suggestions?: unknown[];\r\n\r\n // PostToolUseFailure (Qwen documents tool_use_id/error/is_interrupt; there is\r\n // no duration_ms on this host's payload).\r\n tool_use_id?: string;\r\n error?: string;\r\n is_interrupt?: boolean;\r\n\r\n // SubagentStart / SubagentStop — treat both as optional everywhere (the\r\n // Claude-family quirk: agent_type is not reliably populated on stop).\r\n agent_id?: string;\r\n agent_type?: string;\r\n // SubagentStop — the subagent's OWN transcript + its final message.\r\n agent_transcript_path?: string;\r\n last_assistant_message?: string;\r\n\r\n // SessionStart\r\n source?: string;\r\n // SessionEnd\r\n reason?: string;\r\n // UserPromptSubmit\r\n prompt?: string;\r\n // PreCompact\r\n trigger?: string;\r\n // Stop\r\n stop_hook_active?: boolean;\r\n // Notification\r\n message?: string;\r\n\r\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\r\n connector?: unknown;\r\n}\r\n\r\nexport class QwenCodeAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Qwen CLI\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\r\n // via the base default — Qwen reads repo AGENTS.md natively alongside QWEN.md,\r\n // so no QWEN.md duplicate; user scope → ~/.qwen/QWEN.md below, the only\r\n // documented user-scope memory file).\r\n supportsMemory: true,\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n // Qwen fires PostCompact natively (observe-only — \"not in the decision mode\r\n // supported events list\"; QwenLM/qwen-code docs/users/features/hooks.md\r\n // \"#### PostCompact\", trigger + compact_summary payload).\r\n postCompact: true,\r\n sessionStart: true,\r\n sessionEnd: true,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: true,\r\n // E1 events — all four are Qwen-native (its 16-event surface is strictly\r\n // wider than the canonical union).\r\n permissionRequest: true,\r\n postToolUseFailure: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // Qwen's PreToolUse can rewrite input (updatedInput). It CANNOT rewrite\r\n // already-emitted tool output — `updatedMCPToolOutput` does not exist in\r\n // qwen 0.17.1, so canModifyOutput is false (like the Claude-family hosts).\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n transports: [\"stdio\", \"sse\", \"http\"],\r\n // Content surfaces: Qwen ships native slash commands (TOML), subagents\r\n // (md+frontmatter), and skills (SKILL.md under .qwen/skills/<name>/).\r\n // Confirmed dir: .qwen/skills/ (project), ~/.qwen/skills/ (user scope).\r\n // Ground truth: kilo-pi-ground-truth.md § \"Already-known skills gaps\".\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n // Statusline surface: qwen-code is the 2nd v1 host (after claude-code).\r\n // installStatusline wires settings.json `ui.statusLine` = {type:\"command\",\r\n // command:<home-bin statusline cmd>} through the SAME refcounted ownership\r\n // ledger as configPatch (never clobbers a ui.statusLine agent-connector does\r\n // not own). The key is NESTED here (`ui.statusLine`), unlike claude-code's\r\n // top-level `statusLine`. Confirmed config key + stdin payload against the\r\n // qwen-code status-line docs (shipped v0.14.3, PR #2923).\r\n supportsStatusline: true,\r\n // Native passthrough: Qwen's 16-event surface includes 3 host-specific events\r\n // with NO canonical HookEventName analog — TodoCreated / TodoCompleted /\r\n // StopFailure (QwenLM/qwen-code docs/users/features/hooks.md). A connector\r\n // reaches them via platforms[\"qwen-code\"].nativeHooks; installHooks files the\r\n // PascalCase event key VERBATIM into settings.json hooks, and the generic\r\n // uninstall reverses it.\r\n supportsNativeHooks: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".qwen\");\r\n const userSettings = join(userDir, \"settings.json\");\r\n const projectDirQwen = join(projectDir, \".qwen\");\r\n const projectSettings = join(projectDirQwen, \"settings.json\");\r\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\r\n const projInstalled = existsSync(projectDirQwen) || existsSync(projectSettings);\r\n const installed = userInstalled || projInstalled;\r\n // Report the scope/path that actually matched, so a project-only install\r\n // isn't misreported as a (non-existent) user install.\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projectSettings : userSettings;\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,\r\n scope,\r\n reason: installed\r\n ? scope === \"project\"\r\n ? `found project Qwen CLI config at ${projectSettings}`\r\n : `found Qwen CLI config under ${userDir}`\r\n : `no Qwen CLI config at ${userDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Memory surface: ~/.qwen/QWEN.md at user scope ────────────────────────\r\n // Project scope stays on the AGENTS.md base default (Qwen reads the repo\r\n // AGENTS.md natively in ADDITION to QWEN.md — one canonical copy, never a\r\n // QWEN.md duplicate). User scope targets ~/.qwen/QWEN.md: Qwen has no\r\n // user-scope AGENTS.md, so the host's own global memory file is the only\r\n // file it actually reads there.\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\r\n return super.memoryTargets(ctx);\r\n }\r\n return [\r\n {\r\n path: join(homedir(), \".qwen\", \"QWEN.md\"),\r\n reason: \"qwen-code global memory (~/.qwen/QWEN.md; no user-scope AGENTS.md exists)\",\r\n },\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, \".qwen\")\r\n : join(homedir(), \".qwen\");\r\n }\r\n\r\n /** MCP servers live in settings.json under `mcpServers`. */\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n /** Hooks live in the SAME settings.json under the sibling `hooks` key. */\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.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 qwen-code\"\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 /**\r\n * Render a normalized ServerDef into Qwen's native mcpServers entry. As a\r\n * Gemini-CLI fork, the transport is encoded by WHICH KEY is present (NOT a\r\n * `type` field): command/args/env (stdio), url (sse), httpUrl (http).\r\n */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): QwenStdioServer | QwenSseServer | QwenHttpServer {\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: QwenStdioServer = {\r\n type: \"stdio\",\r\n command: resolveEnvRefsDeep(command),\r\n args: args.map((a) => resolveEnvRefsDeep(a)),\r\n };\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\r\n return entry;\r\n }\r\n\r\n // SSE transport → `url` key.\r\n if (transport === \"sse\") {\r\n const entry: QwenSseServer = { url: resolveEnvRefsDeep(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 // http (streamable-HTTP) and any other remote transport → `httpUrl` key.\r\n const entry: QwenHttpServer = { httpUrl: resolveEnvRefsDeep(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. Qwen's settings loader does not interpret our\r\n * `${env:VAR}` dialect, so refs resolve to literals at install time — the safe\r\n * default shared with the Gemini / Codex adapters.\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 return resolveEnvRefsDeep({ ...env });\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 const hooksDisabled = override?.hooks === false;\r\n // `hooks: false` disables only the NORMALIZED events; nativeHooks is a\r\n // sibling, qwen-scoped declaration that installs regardless.\r\n const normalizedEvents = hooksDisabled ? [] : 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: hooksDisabled ? \"hooks disabled for qwen-code\" : \"connector declares no hooks\",\r\n },\r\n ];\r\n }\r\n\r\n // Normalized events register their canonical PascalCase name verbatim (qwen's\r\n // hook vocabulary is Claude-identical — NO mapEvent, no warn path). Native\r\n // event-name keys ride the separate `native` pass (verbatim keys, FIRST-INNER\r\n // command match, the `(native)` detail) — see hookDescriptor + 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 * Qwen's hook-merge descriptor (NESTED shape `{ matcher, hooks:[{type,command}] }`):\r\n * - NO mapEvent — qwen's events are Claude-identical, every canonical event is\r\n * supported natively, so there is no unmapped/warn path.\r\n * - install find (entryOwnsCommand) is connector-GENERIC: ANY of our commands in\r\n * the nested hooks array (= the old entryHasOurCommand).\r\n * - uninstall is NESTED: ownsEntryForRemove is never-true, so the engine only\r\n * ever runs stripInner — strip our owned inner commands, keep foreign ones,\r\n * drop entries left empty; `removed` = inner commands removed.\r\n * - the native pass uses FIRST-INNER (`hooks[0].command`) EXACT-command ownership\r\n * — qwen's exact current native match (NOT a `.some()`), distinct from the\r\n * connector-generic normalized find. qwen writes no version/envelope (no onMutate).\r\n */\r\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<QwenHookEntry> {\r\n return {\r\n renderEntry: (_event, matcher, command) => ({\r\n matcher,\r\n hooks: [{ type: \"command\", command }],\r\n }),\r\n entryOwnsCommand: (entry, _command) =>\r\n (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx)),\r\n ownsEntryForRemove: () => () => false,\r\n stripInner: (c) => (entry) => {\r\n const innerBefore = entry.hooks?.length ?? 0;\r\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, c));\r\n return {\r\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\r\n removed: innerBefore - inner.length,\r\n };\r\n },\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 nativeOwnsCommand: (entry, command) => entry.hooks?.[0]?.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 // ── Statusline surface (a HUD/status line) ────────────────────────────────\r\n // Wires settings.json `ui.statusLine` = { type:\"command\", command:<home-bin\r\n // statusline cmd> } through the SAME refcounted ownership ledger as configPatch\r\n // (the ledger primitives are surface-agnostic). qwen-code does NOT advertise\r\n // supportsConfigPatch, so — unlike claude-code, which routes the statusline\r\n // through its private applyConfigPatches loop — this adapter performs the nested\r\n // set-if-absent write directly with the exported ledger primitives. Semantics\r\n // are identical: never clobber a ui.statusLine agent-connector does not own\r\n // (skip-warn), record prior state + owner (refcounted across connectors),\r\n // reversible by uninstallStatusline (last-owner-verified delete). The key is\r\n // NESTED (`ui.statusLine`), so we own the `ui.statusLine` leaf — if the user\r\n // already has it, we skip-warn and never touch their value.\r\n //\r\n // The home-bin command makes Qwen exec\r\n // `<homeBin> statusline qwen-code --connector <id>` for every status refresh,\r\n // which re-imports the connector module and renders the line (runtime/\r\n // statusline-entrypoint). No telemetry in v1.\r\n\r\n /** The statusLine config object value agent-connector writes at `ui.statusLine`. */\r\n private statuslineValue(ctx: InstallContext): JsonValue {\r\n const command = buildHomeBinStatuslineCommand(ctx.homeBinPath, HOST, ctx.connector.id);\r\n return { type: \"command\", command };\r\n }\r\n\r\n override installStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.statusline == null) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no statusline\" }];\r\n }\r\n if (connector.platforms[HOST]?.statusline === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"statusline disabled for qwen-code\" }];\r\n }\r\n\r\n const filePath = this.getServerConfigPath(ctx);\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) return [symlink];\r\n\r\n // OVERWRITE GUARD (upsertServerInJson precedent): never round-trip a\r\n // present-but-unparseable settings file into `{}`.\r\n if (this.isPresentButUnparseable(filePath)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not parseable; statusline left unapplied (back it up / fix it, then re-run)`,\r\n },\r\n ];\r\n }\r\n const settings = this.readJson<Record<string, unknown>>(filePath) ?? {};\r\n if (typeof settings !== \"object\" || Array.isArray(settings)) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `existing ${filePath} is not a JSON object; statusline left unapplied`,\r\n },\r\n ];\r\n }\r\n\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n const desired = this.statuslineValue(ctx);\r\n const segments = STATUSLINE_KEY.split(\".\");\r\n const leaf = readJsonLeaf(settings, segments);\r\n const entry = findLedgerEntry(ledger, HOST, filePath, STATUSLINE_KEY);\r\n const changes: ChangeRecord[] = [];\r\n\r\n if (leaf.kind === \"blocked\") {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: \"${leaf.atPath}\" exists but is not an ` +\r\n `object — set ${STATUSLINE_KEY} manually if wanted`,\r\n },\r\n ];\r\n }\r\n\r\n if (leaf.kind === \"absent\") {\r\n // SET-IF-ABSENT: the one write path. Intermediates (`ui`) created as needed.\r\n writeJsonLeaf(settings, segments, desired);\r\n this.writeJson(filePath, settings, ctx.dryRun);\r\n if (entry) {\r\n // Stale ledger row (key deleted out from under us): re-assert the value,\r\n // keep existing owners (they still rely on the key), record what we wrote.\r\n entry.writtenValue = desired;\r\n entry.writtenValueHash = hashJsonValue(desired);\r\n addLedgerOwner(entry, connector.id, connector.version);\r\n } else {\r\n createLedgerEntry(ledger, {\r\n platform: HOST,\r\n file: filePath,\r\n key: STATUSLINE_KEY,\r\n value: desired,\r\n connectorId: connector.id,\r\n connectorVersion: connector.version,\r\n });\r\n }\r\n if (!ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n changes.push({\r\n platform: this.id,\r\n action: \"create\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY}: <absent> → ${describeJsonValue(desired)}`,\r\n });\r\n return changes;\r\n }\r\n\r\n // Key PRESENT — never overwrite; the only question is ownership/refcount.\r\n if (!entry) {\r\n // User- (or other-tool-) owned. No ownership is taken even when the values\r\n // happen to match — uninstall must never delete a key we did not create.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: already set to ${describeJsonValue(leaf.value)} ` +\r\n `(not created by agent-connector) — left untouched`,\r\n },\r\n ];\r\n }\r\n\r\n if (!jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // DRIFT: the user edited the value after we wrote it. Never revert.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `leaving in place`,\r\n },\r\n ];\r\n }\r\n\r\n if (jsonDeepEquals(desired, leaf.value)) {\r\n // Same value we own: register as co-owner (refcount++) or idempotent skip.\r\n const owners = entry.owners.map((o) => o.connectorId);\r\n if (addLedgerOwner(entry, connector.id, connector.version)) {\r\n if (!ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY} already installed; registered as co-owner (co-owned with ${owners.join(\", \")})`,\r\n },\r\n ];\r\n }\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${STATUSLINE_KEY} already installed`,\r\n },\r\n ];\r\n }\r\n\r\n // FIRST-WRITER-WINS: another connector owns the key with a different value.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${STATUSLINE_KEY} skipped: already owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")} with a different value — left untouched`,\r\n },\r\n ];\r\n }\r\n\r\n override uninstallStatusline(ctx: InstallContext): ChangeRecord[] {\r\n const ledger = loadConfigPatchLedger(ctx.dataRoot);\r\n // Release ONLY the ui.statusLine ledger row this connector owns (keyed off the\r\n // ledger, not the declaration, so an id-only synthetic uninstall still reclaims\r\n // it). Last-owner-verified delete: remove the key ONLY when last-owner ∧\r\n // value-unchanged ∧ prior-absent (else skip-warn + leave the key).\r\n const owned = ledgerEntriesOwnedBy(ledger, HOST, ctx.connector.id).filter(\r\n (e) => e.key === STATUSLINE_KEY,\r\n );\r\n if (owned.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"statusline: no ownership recorded; left untouched\",\r\n },\r\n ];\r\n }\r\n\r\n const changes: ChangeRecord[] = [];\r\n let ledgerMutated = false;\r\n\r\n // All rows share one file (the scope-resolved settings.json), but group by\r\n // file anyway so a scope drift between install and uninstall stays correct.\r\n const byFile = new Map<string, ConfigPatchLedgerEntry[]>();\r\n for (const entry of owned) {\r\n const bucket = byFile.get(entry.file) ?? [];\r\n bucket.push(entry);\r\n byFile.set(entry.file, bucket);\r\n }\r\n\r\n for (const [filePath, entries] of byFile) {\r\n const symlink = this.symlinkPathWarning(filePath);\r\n if (symlink) {\r\n changes.push(symlink);\r\n continue;\r\n }\r\n\r\n const unparseable = this.isPresentButUnparseable(filePath);\r\n const settings = unparseable ? null : this.readJson<Record<string, unknown>>(filePath);\r\n let fileMutated = false;\r\n\r\n for (const entry of entries) {\r\n const { lastOwner } = removeLedgerOwner(entry, ctx.connector.id);\r\n ledgerMutated = true;\r\n\r\n if (!lastOwner) {\r\n // Shared-flag case: A uninstalls, B still relies on the key.\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} retained: still owned by ${entry.owners\r\n .map((o) => o.connectorId)\r\n .join(\", \")}`,\r\n });\r\n continue;\r\n }\r\n\r\n // Last owner out → the ledger row is dropped on every branch below; the\r\n // KEY is removed only on the fully-verified branch.\r\n dropLedgerEntry(ledger, entry);\r\n\r\n if (unparseable) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail: `statusline ${entry.key}: ${filePath} is not parseable; key left in place (ownership released)`,\r\n });\r\n continue;\r\n }\r\n if (!settings || typeof settings !== \"object\" || Array.isArray(settings)) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} already absent (no settings file); ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n const leaf = readJsonLeaf(settings, entry.key.split(\".\"));\r\n if (leaf.kind !== \"present\") {\r\n changes.push({\r\n platform: this.id,\r\n action: \"skip\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} already absent; ownership record dropped`,\r\n });\r\n continue;\r\n }\r\n if (entry.prior?.present !== false || !jsonDeepEquals(leaf.value, entry.writtenValue)) {\r\n // User edited the value after install (or the row predates the\r\n // set-if-absent guarantee): deleting would clobber them. Leave it.\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n path: filePath,\r\n detail:\r\n `statusline ${entry.key}: value changed since install ` +\r\n `(current ${describeJsonValue(leaf.value)}, wrote ${describeJsonValue(entry.writtenValue)}); ` +\r\n `left in place`,\r\n });\r\n continue;\r\n }\r\n\r\n // VERIFIED: last owner + current === writtenValue + prior absent. Delete\r\n // the leaf key (the `ui` intermediate we may have created is left in place).\r\n deleteJsonLeaf(settings, entry.key.split(\".\"));\r\n fileMutated = true;\r\n changes.push({\r\n platform: this.id,\r\n action: \"remove\",\r\n path: filePath,\r\n detail: `statusline ${entry.key} removed (was ${describeJsonValue(entry.writtenValue)})`,\r\n });\r\n }\r\n\r\n if (fileMutated && settings) this.writeJson(filePath, settings, ctx.dryRun);\r\n }\r\n\r\n if (ledgerMutated && !ctx.dryRun) saveConfigPatchLedger(ctx.dataRoot, ledger);\r\n return changes;\r\n }\r\n\r\n /**\r\n * Parse Qwen's statusLine stdin JSON into the normalized\r\n * {@link StatuslineContext}. Qwen pipes a JSON object to the statusLine command\r\n * on stdin (model, context_window, workspace, git, …); fields the payload omits\r\n * stay undefined. `raw` keeps the verbatim payload (incl. version/git/metrics/\r\n * vim). NOTE: Qwen has NO cost analog (no cost field in the payload), so\r\n * `ctx.cost` is intentionally left undefined. Sources: qwen-code status-line\r\n * docs, QwenLM/qwen-code settings.md.\r\n */\r\n parseStatusInput(raw: unknown): StatuslineContext {\r\n const input = (raw ?? {}) as QwenStatuslineInput;\r\n\r\n const ctx: StatuslineContext = {\r\n host: HOST,\r\n capabilities: this.capabilities,\r\n raw,\r\n };\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n ctx.sessionId = input.session_id;\r\n }\r\n if (typeof input.workspace?.current_dir === \"string\") {\r\n ctx.cwd = input.workspace.current_dir;\r\n }\r\n if (typeof input.model?.display_name === \"string\") {\r\n ctx.model = { displayName: input.model.display_name };\r\n }\r\n const cw = input.context_window;\r\n if (cw) {\r\n const context: { usedTokens?: number; maxTokens?: number; percent?: number } = {};\r\n if (typeof cw.context_window_size === \"number\") context.maxTokens = cw.context_window_size;\r\n if (typeof cw.current_usage === \"number\") context.usedTokens = cw.current_usage;\r\n if (typeof cw.used_percentage === \"number\") context.percent = cw.used_percentage;\r\n if (\r\n context.usedTokens !== undefined ||\r\n context.maxTokens !== undefined ||\r\n context.percent !== undefined\r\n ) {\r\n ctx.context = context;\r\n }\r\n }\r\n // ctx.cost stays undefined: Qwen's status payload has no cost analog.\r\n return ctx;\r\n }\r\n\r\n /** Format the rendered status line into Qwen's native reply: stdout = line, exit 0. */\r\n formatStatusOutput(rendered: string): HookReply {\r\n return { exitCode: 0, stdout: rendered };\r\n }\r\n\r\n // ── Content surfaces: commands / subagents ───────────────────────────────\r\n // CONTENT-ONLY: pure native-file writers under <qwenDir>/{commands,agents}. No\r\n // runtime dispatch, no home-bin pointer, no telemetry wrap. Each method is\r\n // idempotent (byte-identical → skip) via BaseAdapter.writeContentFile and\r\n // reversible via removeContentFile. Honors platforms[\"qwen-code\"] per-surface\r\n // false to skip. Qwen has NO Agent-Skills surface, so skills are left to the\r\n // BaseAdapter skip/warn default (supportsSkills stays false).\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: <qwenDir>/commands/<name>.toml. */\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.commandsDir(ctx), `${name}.toml`);\r\n }\r\n /** Native skill dir: <qwenDir>/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: <qwenDir>/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 qwen-code\" }];\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 /** Render a command to Qwen's native TOML (description, prompt). */\r\n private renderCommand(cmd: CommandDef): string {\r\n const obj: Record<string, unknown> = {};\r\n if (cmd.description !== undefined) obj.description = cmd.description;\r\n obj.prompt = cmd.prompt;\r\n return writeTomlString(obj);\r\n }\r\n\r\n // ── Skills ────────────────────────────────────────────────────────────────\r\n // Qwen reads SKILL.md from <qwenDir>/skills/<name>/SKILL.md.\r\n // Project dir: <projectDir>/.qwen/skills/<name>/SKILL.md\r\n // User dir: ~/.qwen/skills/<name>/SKILL.md\r\n // Confirmed: kilo-pi-ground-truth.md § \"Already-known skills gaps\" (.qwen/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 qwen-code\" }];\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\"), this.renderSkill(skill), ctx.dryRun),\r\n );\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 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;\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n private renderSkill(skill: SkillDef): string {\r\n return renderSkillMd(skill);\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 qwen-code\" }];\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 subagent to md+frontmatter (name, description, tools, model) + 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 const allow = agent.tools?.allow;\r\n if (allow && allow.length > 0) frontmatter.tools = allow.join(\", \");\r\n if (agent.model !== undefined) frontmatter.model = agent.model;\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 settingsPath = this.getHookConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const homeBin = ctx.homeBinPath;\r\n const hookEvents = ctx.connector.hookEvents;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: settings.json present`,\r\n check: () =>\r\n existsSync(settingsPath)\r\n ? { status: \"OK\", detail: settingsPath }\r\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\r\n },\r\n {\r\n name: `${this.name}: hook command registered`,\r\n check: () => {\r\n if (hookEvents.length === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n const settings = this.readJson<QwenSettingsFile>(settingsPath);\r\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\r\n const hooks = settings.hooks ?? {};\r\n const registered = Object.values(hooks).some((entries) =>\r\n (entries ?? []).some((e) =>\r\n (e.hooks ?? []).some((h) =>\r\n isHomeBinHookCommand(h.command, homeBin, connectorId),\r\n ),\r\n ),\r\n );\r\n return registered\r\n ? { status: \"OK\", detail: \"hook command present\" }\r\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${settingsPath}` };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: assert presence of all three content surfaces\r\n // (commands, skills, subagents) this connector declares.\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\r\n // Statusline check: assert it when the connector declares a statusline AND it\r\n // is not disabled for this host, OR when the ownership ledger holds a\r\n // ui.statusLine row this connector owns (the REGISTERED-connector path:\r\n // connectorFromMeta can't re-expose the render fn, so statusline comes back\r\n // undefined — but the ledger row proves the surface was wired). Mirrors\r\n // claude-code's \"statusline wired\" check; ui.statusLine.command must be OUR\r\n // home-bin statusline command (OK); present-but-not-ours / absent → FAIL.\r\n const statuslineLedgerOwned = ledgerEntriesOwnedBy(\r\n loadConfigPatchLedger(ctx.dataRoot),\r\n HOST,\r\n connectorId,\r\n ).some((e) => e.key === STATUSLINE_KEY);\r\n if (\r\n (ctx.connector.statusline != null || statuslineLedgerOwned) &&\r\n ctx.connector.platforms[HOST]?.statusline !== false\r\n ) {\r\n checks.push({\r\n name: `${this.name}: statusline wired`,\r\n check: () => {\r\n const settings = this.readJson<{ ui?: { statusLine?: { command?: unknown } } }>(\r\n settingsPath,\r\n );\r\n const command = settings?.ui?.statusLine?.command;\r\n if (command === undefined) {\r\n return { status: \"FAIL\", detail: `ui.statusLine not set in ${settingsPath}` };\r\n }\r\n if (\r\n typeof command === \"string\" &&\r\n isHomeBinStatuslineCommand(command, homeBin, connectorId)\r\n ) {\r\n return { status: \"OK\", detail: \"ui.statusLine command present\" };\r\n }\r\n // Present but not ours — a non-AC ui.statusLine we must never clobber.\r\n return {\r\n status: \"FAIL\",\r\n detail: `ui.statusLine in ${settingsPath} is not agent-connector's (left untouched)`,\r\n };\r\n },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse Qwen stdin JSON → normalized event ────────────────────\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as QwenWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n const sessionId = extractSessionId(input);\r\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\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 ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolResponseToString(input.tool_response) !== undefined\r\n ? { toolOutput: toolResponseToString(input.tool_response) }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n const ev: SessionStartEvent = {\r\n ...base,\r\n source: normalizeSessionSource(input.source),\r\n };\r\n return ev;\r\n }\r\n case \"SessionEnd\": {\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 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 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 \"PostCompact\": {\r\n // Qwen fires PostCompact natively (observe-only). Parsed like PreCompact:\r\n // normalize the trigger (auto|manual); compact_summary rides on `raw`.\r\n const ev: PostCompactEvent = {\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 \"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 \"Notification\": {\r\n const ev: NotificationEvent = {\r\n ...base,\r\n message: typeof input.message === \"string\" ? input.message : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PermissionRequest\": {\r\n const ev: PermissionRequestEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(Array.isArray(input.permission_suggestions)\r\n ? { permissionSuggestions: input.permission_suggestions }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUseFailure\": {\r\n // durationMs stays unset — Qwen's failure payload has no duration_ms.\r\n const ev: PostToolUseFailureEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error: typeof input.error === \"string\" ? input.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 };\r\n return ev;\r\n }\r\n case \"SubagentStart\": {\r\n const ev: SubagentStartEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStop\": {\r\n // agent_id/agent_type stay optional — the Claude-family SDK does not\r\n // reliably populate agent_type on stop.\r\n const ev: SubagentStopEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\"\r\n ? { agentType: input.agent_type }\r\n : {}),\r\n ...(typeof input.agent_transcript_path === \"string\"\r\n ? { agentTranscriptPath: input.agent_transcript_path }\r\n : {}),\r\n ...(typeof input.last_assistant_message === \"string\"\r\n ? { lastAssistantMessage: input.last_assistant_message }\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 // Exhaustive guard — every HookEventName is handled above.\r\n const _never: never = event;\r\n throw new Error(`unsupported qwen-code hook event: ${String(_never)}`);\r\n }\r\n }\r\n }\r\n\r\n // ── Runtime: normalized response → Qwen native hook reply ────────────────\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const hookEventName = event;\r\n const decision = response.decision ?? \"allow\";\r\n\r\n // PermissionRequest uses Qwen's nested decision{behavior} envelope (Claude-\r\n // identical) and is the ONE event where an EXPLICIT \"allow\" is an ACTIVE\r\n // grant that suppresses the permission dialog:\r\n // allow → decision{behavior:\"allow\"} (+updatedInput when set —\r\n // Qwen honors input rewrite, canModifyArgs above);\r\n // modify → an allow grant carrying updatedInput;\r\n // deny → decision{behavior:\"deny\", message};\r\n // ask/context/void → NO decision output: fall through to the native\r\n // dialog (the dialog IS the ask).\r\n if (event === \"PermissionRequest\") {\r\n if (response.decision === \"deny\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"deny\",\r\n message: response.reason ?? \"Blocked by hook\",\r\n },\r\n },\r\n });\r\n }\r\n if (\r\n response.decision === \"allow\" ||\r\n (response.decision === \"modify\" && response.updatedInput)\r\n ) {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"allow\",\r\n ...(response.updatedInput\r\n ? { updatedInput: response.updatedInput }\r\n : {}),\r\n },\r\n },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\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 // Qwen: \"context\" emits additionalContext, and a \"deny\" DEGRADES to the\r\n // same shape carrying the reason (the tool already failed / the spawn is\r\n // not blockable).\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 if (context) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: context },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // deny → block the action with a reason (exit 0; JSON carries the decision).\r\n // Qwen's deny shape is EVENT-SPECIFIC (claude-wire-compatible): PreToolUse\r\n // uses hookSpecificOutput.permissionDecision, but Stop / SubagentStop /\r\n // UserPromptSubmit / PostToolUse honor only the TOP-LEVEL\r\n // {\"decision\":\"block\",\"reason\"} — those events do NOT take permissionDecision\r\n // (QwenLM/qwen-code docs/users/features/hooks.md: Stop/SubagentStop block via\r\n // {\"decision\":\"block\",\"reason\"}; UserPromptSubmit/PostToolUse output options\r\n // list top-level `decision`+`reason`, not permissionDecision — only\r\n // PreToolUse documents permissionDecision as its official interface). A\r\n // SubagentStop / Stop block keeps the agent running with `reason` as its next\r\n // instruction (Stop semantics).\r\n if (decision === \"deny\") {\r\n if (\r\n event === \"Stop\" ||\r\n event === \"SubagentStop\" ||\r\n event === \"UserPromptSubmit\" ||\r\n event === \"PostToolUse\"\r\n ) {\r\n return this.stdout({\r\n decision: \"block\",\r\n reason: response.reason ?? \"Blocked by hook\",\r\n });\r\n }\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"deny\",\r\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\r\n },\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 hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"ask\",\r\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\r\n },\r\n });\r\n }\r\n\r\n // modify → rewrite PreToolUse input only. Qwen 0.17.1 has no PostToolUse\r\n // output-rewrite (`updatedMCPToolOutput` does not exist), so a modify on any\r\n // other event falls through to allow.\r\n if (decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\r\n });\r\n }\r\n // Nothing applicable on this event; fall through to allow.\r\n }\r\n\r\n // context → inject soft guidance (also the SessionStart context path).\r\n if (decision === \"context\" && response.additionalContext) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\r\n });\r\n }\r\n\r\n // allow / void / unsupported-degradation → pass through with exit 0.\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// ─────────────────────────────────────────────────────────────────────────\r\n// JSON leaf-path helpers (statusline nested set-if-absent). Mirror claude-code's\r\n// file-local helpers (those are private to the claude-code module). The leaf\r\n// path here is the validated dotted `ui.statusLine`.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Result of looking up a dotted leaf path in a parsed JSON object. */\r\ntype JsonLeafLookup =\r\n | { kind: \"absent\" }\r\n | { kind: \"present\"; value: JsonValue }\r\n | { kind: \"blocked\"; atPath: string };\r\n\r\n/**\r\n * Walk `segments` (a dotted leaf path) through `root`. \"blocked\" reports the\r\n * first intermediate that exists but is not a plain object — the skip-warn case\r\n * (we never replace a non-object intermediate, e.g. a user's `ui: \"dark\"`).\r\n */\r\nfunction readJsonLeaf(root: Record<string, unknown>, segments: string[]): JsonLeafLookup {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === undefined) return { kind: \"absent\" };\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) {\r\n return { kind: \"blocked\", atPath: segments.slice(0, i + 1).join(\".\") };\r\n }\r\n node = next as Record<string, unknown>;\r\n }\r\n const leaf = node[segments[segments.length - 1]!];\r\n if (leaf === undefined) return { kind: \"absent\" };\r\n return { kind: \"present\", value: leaf as JsonValue };\r\n}\r\n\r\n/**\r\n * Write `value` at the leaf, creating ONLY absent intermediate objects along the\r\n * way (callers must have verified the path is not blocked).\r\n */\r\nfunction writeJsonLeaf(\r\n root: Record<string, unknown>,\r\n segments: string[],\r\n value: JsonValue,\r\n): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const seg = segments[i]!;\r\n const next = node[seg];\r\n if (next === undefined) {\r\n const created: Record<string, unknown> = {};\r\n node[seg] = created;\r\n node = created;\r\n } else {\r\n node = next as Record<string, unknown>;\r\n }\r\n }\r\n node[segments[segments.length - 1]!] = value;\r\n}\r\n\r\n/**\r\n * Delete the leaf key only. Intermediate objects — even ones we created (the\r\n * `ui` wrapper) — are deliberately left in place (harmless; pruning risks\r\n * clobbering sibling keys the user set under `ui`).\r\n */\r\nfunction deleteJsonLeaf(root: Record<string, unknown>, segments: string[]): void {\r\n let node: Record<string, unknown> = root;\r\n for (let i = 0; i < segments.length - 1; i++) {\r\n const next = node[segments[i]!];\r\n if (next === null || typeof next !== \"object\" || Array.isArray(next)) return;\r\n node = next as Record<string, unknown>;\r\n }\r\n delete node[segments[segments.length - 1]!];\r\n}\r\n\r\n/**\r\n * Extract a stable session id from a Qwen wire payload. Unlike Claude (which\r\n * prefers the transcript UUID), Qwen Code surfaces `session_id` directly and\r\n * prioritizes it — matching context-mode's QwenCodeAdapter.extractSessionId.\r\n * Falls back to the transcript UUID, then \"\" (no ppid fabrication — the\r\n * normalized event uses \"\" when the host provides no id).\r\n */\r\nfunction extractSessionId(input: QwenWireInput): string {\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n return input.session_id;\r\n }\r\n if (typeof input.transcript_path === \"string\") {\r\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\r\n if (m && m[1]) return m[1];\r\n }\r\n return \"\";\r\n}\r\n\r\n/** Coerce a Qwen PostToolUse `tool_response` into a string for the normalized event. */\r\nfunction toolResponseToString(value: unknown): string | undefined {\r\n if (value == null) return undefined;\r\n if (typeof value === \"string\") return value;\r\n try {\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n\r\nexport const adapter = new QwenCodeAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry","headers"]}
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveEnvRefsDeep
4
- } from "./chunk-BEFVJ2OE.js";
4
+ } from "./chunk-XXLCMSD3.js";
5
5
  import {
6
6
  BaseAdapter,
7
7
  renderCommandMd,
8
8
  renderSkillMd
9
- } from "./chunk-MGTDQLJJ.js";
9
+ } from "./chunk-3FINQ2ZF.js";
10
10
  import {
11
11
  buildWrappedStdio
12
- } from "./chunk-4NHXLXSD.js";
13
- import "./chunk-UMQ6NBQR.js";
14
- import "./chunk-GZGLCCEE.js";
12
+ } from "./chunk-Y3K6KJMS.js";
13
+ import "./chunk-ILWHLGIC.js";
14
+ import "./chunk-QYOUQCC6.js";
15
15
 
16
16
  // src/adapters/roo-code/index.ts
17
17
  import { existsSync } from "fs";
@@ -358,4 +358,4 @@ export {
358
358
  adapter,
359
359
  roo_code_default as default
360
360
  };
361
- //# sourceMappingURL=roo-code-DLPIHHQ6.js.map
361
+ //# sourceMappingURL=roo-code-7F4HYB34.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/roo-code/index.ts"],"sourcesContent":["/**\r\n * adapters/roo-code — Roo Code (VS Code extension) platform adapter.\r\n *\r\n * Roo Code (rooveterinaryinc.roo-cline) is a Cline-fork VS Code extension and an\r\n * **mcp-only** host from agent-connector's perspective: it exposes no lifecycle\r\n * hook system, so MCP server registration is the only thing we install and hooks\r\n * are reported unavailable. This mirrors the Warp reference adapter exactly.\r\n *\r\n * MCP config (vsix 3.54.0):\r\n * - user scope → <vscodeUserDir>/globalStorage/rooveterinaryinc.roo-cline/\r\n * settings/mcp_settings.json (renamed in 3.54.0 from the\r\n * older `cline_mcp_settings.json`; we PROBE both on detection\r\n * — the extension migrates the old name at startup — and\r\n * WRITE the new `mcp_settings.json`)\r\n * - project scope → <projectDir>/.roo/mcp.json\r\n * Both are JSON, root key \"mcpServers\".\r\n *\r\n * VS Code user-dir resolution (cross-OS):\r\n * - macOS → ~/Library/Application Support/Code/User\r\n * - Linux → ~/.config/Code/User\r\n * - Windows → %APPDATA%/Code/User (falls back to ~/AppData/Roaming/Code/User)\r\n * We deliberately target stable VS Code (\"Code\"), the documented home for the\r\n * published Roo Code extension's globalStorage. Insiders/forks would live under\r\n * a sibling dir but are out of scope for the default path.\r\n *\r\n * Env interpolation: Roo Code's settings file documents no native `${env:VAR}`\r\n * token (the entries are plain command/args/env literals), so we resolve every\r\n * `${env:VAR}` reference to a literal at install time — the no-native-token path.\r\n *\r\n * The hook \"config path\" is the SAME MCP settings file (there is no hook file),\r\n * so the generic doctor/backup behave sensibly.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { homedir, platform as osPlatform } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter } from \"../base.js\";\r\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookParadigm,\r\n PlatformCapabilities,\r\n PlatformId,\r\n ServerDef,\r\n Transport,\r\n} from \"../../core/types.js\";\r\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\r\nimport {\r\n buildWrappedStdio,\r\n} from \"../../core/spawn.js\";\r\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\r\n\r\nconst HOST: PlatformId = \"roo-code\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/** Roo Code extension id → its VS Code globalStorage folder. */\r\nconst ROO_EXTENSION_ID = \"rooveterinaryinc.roo-cline\";\r\n/** User-scope MCP settings filename — renamed in vsix 3.54.0. */\r\nconst MCP_SETTINGS_FILE = \"mcp_settings.json\";\r\n/** Legacy filename (pre-3.54.0) — probed on detection for older installs. */\r\nconst LEGACY_MCP_SETTINGS_FILE = \"cline_mcp_settings.json\";\r\n\r\n/**\r\n * Native MCP server entry shapes Roo Code accepts under `mcpServers`.\r\n * We write the minimal stdio shape { command, args, env, disabled }; Roo Code\r\n * also accepts optional `alwaysAllow` / `timeout`, which we intentionally omit.\r\n *\r\n * For remote (url-based) servers we ALWAYS emit `type`. Roo Code's config schema\r\n * (RooCodeInc/Roo-Code McpHub.ts `createServerTypeSchema` + `validateServerConfig`,\r\n * verified against v3.54.0) is STRICTER than its Cline parent: a url config with\r\n * NO `type` is REJECTED outright — \"Configuration with 'url' must explicitly\r\n * specify 'type' as 'sse' or 'streamable-http'.\" Note the value differs from\r\n * Cline: Roo Code uses the HYPHENATED `\"streamable-http\"` (Cline uses the\r\n * camelCase `\"streamableHttp\"`), so this is NOT byte-identical to the cline\r\n * adapter despite the fork lineage.\r\n */\r\ninterface RooStdioServer {\r\n command: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n disabled: boolean;\r\n}\r\ninterface RooHttpServer {\r\n url: string;\r\n type: \"sse\" | \"streamable-http\";\r\n headers?: Record<string, string>;\r\n disabled: boolean;\r\n}\r\n\r\n/**\r\n * Resolve the cross-OS VS Code per-user data directory (the \"User\" folder that\r\n * contains `globalStorage`). See module header for the per-platform mapping.\r\n */\r\nfunction vscodeUserDir(): string {\r\n const home = homedir();\r\n switch (osPlatform()) {\r\n case \"darwin\":\r\n return join(home, \"Library\", \"Application Support\", \"Code\", \"User\");\r\n case \"win32\": {\r\n const appData =\r\n process.env.APPDATA ?? join(home, \"AppData\", \"Roaming\");\r\n return join(appData, \"Code\", \"User\");\r\n }\r\n default:\r\n // Linux / other POSIX: XDG-style config dir.\r\n return join(home, \".config\", \"Code\", \"User\");\r\n }\r\n}\r\n\r\nexport class RooCodeAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Roo Code\";\r\n readonly paradigm: HookParadigm = \"mcp-only\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\r\n // via the base default — Roo's \"Agent Rules standard\" support is default-on;\r\n // user scope → ~/.roo/rules/agent-connector.md below).\r\n supportsMemory: true,\r\n // Roo Code has no lifecycle hook system — every hook capability is false.\r\n preToolUse: false,\r\n postToolUse: false,\r\n preCompact: false,\r\n sessionStart: false,\r\n sessionEnd: false,\r\n userPromptSubmit: false,\r\n stop: false,\r\n notification: false,\r\n canModifyArgs: false,\r\n canModifyOutput: false,\r\n canInjectSessionContext: false,\r\n // Roo Code registers stdio, SSE, and Streamable HTTP MCP servers.\r\n transports: [\"stdio\", \"sse\", \"http\"],\r\n // Content surfaces: Roo Code reads custom slash commands and AgentSkills from\r\n // its `.roo` config dir (BOTH user ~/.roo and project <projectDir>/.roo).\r\n // command → <configDir>/commands/<name>.md (md+optional frontmatter)\r\n // skill → <configDir>/skills/<name>/SKILL.md (+ resources)\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userSettings = this.userSettingsPath();\r\n const userExtDir = join(\r\n vscodeUserDir(),\r\n \"globalStorage\",\r\n ROO_EXTENSION_ID,\r\n );\r\n // Probe the legacy filename too (3.54.0 migrates it at startup) so an older\r\n // install is still recognized; we WRITE the new mcp_settings.json.\r\n const userLegacySettings = join(\r\n userExtDir,\r\n \"settings\",\r\n LEGACY_MCP_SETTINGS_FILE,\r\n );\r\n const projectMcp = join(projectDir, \".roo\", \"mcp.json\");\r\n\r\n const userMatch =\r\n existsSync(userSettings) ||\r\n existsSync(userLegacySettings) ||\r\n existsSync(userExtDir);\r\n const projectMatch = existsSync(projectMcp);\r\n const installed = userMatch || projectMatch;\r\n\r\n // Prefer the user scope/path when present; otherwise surface the project one.\r\n const scope = userMatch || !projectMatch ? \"user\" : \"project\";\r\n const configPath = scope === \"user\" ? userSettings : projectMcp;\r\n const reason = installed\r\n ? userMatch\r\n ? `found Roo Code globalStorage under ${userExtDir}`\r\n : `found Roo Code project config at ${projectMcp}`\r\n : `no Roo Code config at ${userExtDir} or ${projectMcp}`;\r\n\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,\r\n scope,\r\n reason,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n /** Absolute path to the user-scope MCP settings file (VS Code globalStorage). */\r\n private userSettingsPath(): string {\r\n return join(\r\n vscodeUserDir(),\r\n \"globalStorage\",\r\n ROO_EXTENSION_ID,\r\n \"settings\",\r\n MCP_SETTINGS_FILE,\r\n );\r\n }\r\n\r\n // ── Memory surface: global rules dir at user scope ──────────────────────\r\n // Project scope stays on the AGENTS.md base default (\"Agent Rules standard\",\r\n // default-on). User scope targets a dedicated agent-connector.md in Roo's\r\n // documented ~/.roo/rules/ dir (files concatenated; AC-created → cleanly\r\n // deletable on uninstall).\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\r\n return super.memoryTargets(ctx);\r\n }\r\n return [\r\n {\r\n path: join(homedir(), \".roo\", \"rules\", \"agent-connector.md\"),\r\n reason: \"roo-code global rules dir (~/.roo/rules; agent-connector-owned file)\",\r\n },\r\n ];\r\n }\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".roo\")\r\n : join(\r\n vscodeUserDir(),\r\n \"globalStorage\",\r\n ROO_EXTENSION_ID,\r\n \"settings\",\r\n );\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".roo\", \"mcp.json\")\r\n : this.userSettingsPath();\r\n }\r\n\r\n /**\r\n * Roo Code has no hook file — hooks are not a thing here. The hook \"config\r\n * path\" is the same MCP settings file so the generic doctor/backup behave\r\n * sensibly.\r\n */\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return this.getServerConfigPath(ctx);\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 roo-code\"\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 Roo Code's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): RooStdioServer | RooHttpServer {\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 // Roo Code documents no native interpolation token, so resolve every\r\n // ${env:VAR} to a literal at install time.\r\n const entry: RooStdioServer = {\r\n command: resolveEnvRefsDeep(command),\r\n // Honor the per-call server's enabled flag (mirror droid) rather than\r\n // hardcoding enabled — a server marked enabled:false installs disabled.\r\n disabled: server.enabled === false,\r\n };\r\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n return entry;\r\n }\r\n\r\n // sse / http (and any other remote transport) — Roo Code registers a URL.\r\n // We ALWAYS emit `type`: Roo Code REJECTS a url config that omits it (and an\r\n // untyped url has no sse-default fallback like Cline's). Map our \"http\"\r\n // transport to Roo Code's HYPHENATED \"streamable-http\" (NOT Cline's camelCase\r\n // \"streamableHttp\") so a Streamable-HTTP server registers correctly.\r\n const entry: RooHttpServer = {\r\n url: resolveEnvRefsDeep(server.url ?? \"\"),\r\n type: transport === \"http\" ? \"streamable-http\" : \"sse\",\r\n disabled: server.enabled === false,\r\n };\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. Roo Code documents no native interpolation token,\r\n * so resolve `${env:VAR}` references to literals at install time.\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 return resolveEnvRefsDeep({ ...env });\r\n }\r\n\r\n // ── Hooks (unavailable — Roo Code is mcp-only) ───────────────────────────\r\n\r\n installHooks(_ctx: InstallContext): ChangeRecord[] {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"hooks unavailable (Roo Code is mcp-only)\",\r\n },\r\n ];\r\n }\r\n\r\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"hooks unavailable (Roo Code is mcp-only)\",\r\n },\r\n ];\r\n }\r\n\r\n // ── Content surfaces: commands / skills ──────────────────────────────────\r\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\r\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\r\n // skip) via writeContentFile and reversible via removeContentFile. Honors\r\n // platforms[\"roo-code\"] per-surface false to skip. BOTH scopes are supported:\r\n // user → ~/.roo, project → <projectDir>/.roo.\r\n //\r\n // Native locations (the `.roo` content root, NOT the globalStorage MCP dir):\r\n // command → <rooDir>/commands/<name>.md md+optional frontmatter\r\n // (description, argument-hint, + `mode` when cmd.extra carries it)\r\n // skill → <rooDir>/skills/<name>/SKILL.md (+ resources)\r\n\r\n /**\r\n * The `.roo` content root for the active scope: ~/.roo (user) or\r\n * <projectDir>/.roo (project). Distinct from getConfigDir's user-scope path\r\n * (the VS Code globalStorage `settings` dir, which holds MCP settings only).\r\n */\r\n private rooDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".roo\")\r\n : join(homedir(), \".roo\");\r\n }\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.rooDir(ctx), \"commands\", `${name}.md`);\r\n }\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.rooDir(ctx), \"skills\", name);\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[this.id]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for roo-code\" }];\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 // Roo Code additionally honors a `mode` frontmatter key; it is passed\r\n // through only when cmd.extra carries it (renderCommandMd merges extra\r\n // verbatim). includeToolsAndModel:false suppresses allowed-tools/model so\r\n // the shape stays (description, argument-hint + verbatim extra).\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(\r\n this.commandPath(ctx, cmd.name),\r\n renderCommandMd(cmd, { includeToolsAndModel: false }),\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 // ── Skills ───────────────────────────────────────────────────────────────\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[this.id]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for roo-code\" }];\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 // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const mcpPath = this.getServerConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n return [\r\n {\r\n name: `${this.name}: MCP settings 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}: server entry registered`,\r\n check: () => {\r\n // Only assert what the connector declares: a server-less connector —\r\n // e.g. a catalog-only bundle of agents/skills/commands — never writes\r\n // an mcpServers entry, so its absence is healthy.\r\n if (!ctx.connector.server) {\r\n return { status: \"OK\", detail: \"no MCP server declared\" };\r\n }\r\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\r\n const bucket = cfg?.[MCP_ROOT_KEY];\r\n if (!cfg || !bucket) {\r\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\r\n }\r\n return connectorId in bucket\r\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\r\n : {\r\n status: \"FAIL\",\r\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\r\n };\r\n },\r\n },\r\n ];\r\n }\r\n}\r\n\r\nexport const adapter = new RooCodeAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry"]}
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readJsonFile
4
- } from "./chunk-RK6VBLXP.js";
4
+ } from "./chunk-ZSOS2KOR.js";
5
5
  import {
6
6
  expandHome,
7
7
  walkFiles
8
- } from "./chunk-O7SDRBVB.js";
8
+ } from "./chunk-KM2YXO6V.js";
9
9
  import {
10
10
  emptyTokens
11
- } from "./chunk-XD7MY6HB.js";
11
+ } from "./chunk-7PSNXUFK.js";
12
12
 
13
13
  // src/usage/readers/roo-code.ts
14
14
  import { existsSync, readFileSync } from "fs";
@@ -226,4 +226,4 @@ var roo_code_default = rooCodeReader;
226
226
  export {
227
227
  roo_code_default as default
228
228
  };
229
- //# sourceMappingURL=roo-code-SUWI4BBN.js.map
229
+ //# sourceMappingURL=roo-code-HSAE2CJU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/readers/roo-code.ts"],"sourcesContent":["/**\r\n * usage/readers/roo-code — Roo Code (VS Code extension) task-log reader.\r\n *\r\n * Faithful port of tokscale sessions/roocode.rs (parse_roo_kilo_file, source\r\n * \"roocode\"). Roo Code (rooveterinaryinc.roo-cline) is a Cline-fork VS Code\r\n * extension that persists per-task logs under its VS Code globalStorage:\r\n * <vscodeUserDir>/globalStorage/rooveterinaryinc.roo-cline/tasks/<taskId>/\r\n * ui_messages.json (the UI message stream — token source)\r\n * api_conversation_history.json (sibling — model/agent source)\r\n *\r\n * roo-code is NOT in paths.ts hostRoots (the framework's per-platform table\r\n * targets CLIs with ~/.<tool> roots, not VS Code extension globalStorage), so\r\n * this reader resolves the cross-OS VS Code \"User\" dir itself, mirroring the\r\n * roo-code platform adapter (adapters/roo-code/index.ts vscodeUserDir):\r\n * - macOS → ~/Library/Application Support/Code/User\r\n * - Windows → %APPDATA%/Code/User (else ~/AppData/Roaming/Code/User)\r\n * - Linux → ~/.config/Code/User\r\n * An AGENT_CONNECTOR_ROO_CODE_DIR override (verbatim, non-empty, ~-expanded)\r\n * points directly at a `tasks` parent when set, matching the env convention in\r\n * paths.ts hostRoots.\r\n *\r\n * Tokens (ui_messages.json): the file is a JSON ARRAY of entries; only entries\r\n * with type==\"say\" AND say==\"api_req_started\" carry usage. Each such entry's\r\n * `text` field is a JSON-in-string payload:\r\n * tokensIn → input\r\n * tokensOut → output\r\n * cacheReads → cacheRead\r\n * cacheWrites → cacheWrite\r\n * cost (f64) → cost\r\n * apiProtocol → providerId (preserved verbatim, e.g. \"bedrock/anthropic\")\r\n * reasoning is ALWAYS 0 (Roo Code does not report it). A malformed text payload,\r\n * a missing text, or an unparseable `ts` skips just that entry.\r\n *\r\n * model / agent (api_conversation_history.json): scan every\r\n * <environment_details>…</environment_details> block for <model>, <slug>, <name>\r\n * tags; the LAST <model> wins (default \"unknown\"); agent prefers <slug> then\r\n * <name> (optional). When the sibling file is absent/unreadable: model \"unknown\",\r\n * no agent — exactly the Rust read_task_metadata fallback.\r\n *\r\n * session id is the taskId — the parent directory name of ui_messages.json\r\n * (port of extract_session_id), defaulting to \"unknown\". provider from\r\n * apiProtocol (trimmed, default \"unknown\"). No project attribution (Roo Code's\r\n * logs carry no cwd). No dedup — one row per api_req_started event. Confidence is\r\n * \"host-reported\".\r\n *\r\n * Fail-open: no root → []; unreadable/malformed file, entry, or payload → skipped\r\n * (never throws). Read-only.\r\n */\r\n\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { homedir, platform as osPlatform } from \"node:os\";\r\nimport { basename, dirname, isAbsolute, join, resolve } from \"node:path\";\r\n\r\nimport type { UsageReader, UsageRecord } from \"../types.js\";\r\nimport { emptyTokens } from \"../aggregate.js\";\r\nimport { readJsonFile } from \"../jsonl.js\";\r\nimport { expandHome, walkFiles } from \"../paths.js\";\r\n\r\nconst PLATFORM_ID = \"roo-code\" as const;\r\nconst DEFAULT_MODEL = \"unknown\";\r\nconst DEFAULT_PROVIDER = \"unknown\";\r\nconst DEFAULT_SESSION = \"unknown\";\r\n\r\n/** Roo Code extension id → its VS Code globalStorage folder. */\r\nconst ROO_EXTENSION_ID = \"rooveterinaryinc.roo-cline\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Storage-root resolution (mirrors adapters/roo-code vscodeUserDir + the\r\n// AGENT_CONNECTOR_<PLATFORM>_DIR env convention in paths.ts hostRoots)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Resolve the cross-OS VS Code per-user \"User\" dir (the globalStorage parent). */\r\nfunction vscodeUserDir(): string {\r\n const home = homedir();\r\n switch (osPlatform()) {\r\n case \"darwin\":\r\n return join(home, \"Library\", \"Application Support\", \"Code\", \"User\");\r\n case \"win32\": {\r\n const appData = process.env.APPDATA ?? join(home, \"AppData\", \"Roaming\");\r\n return join(appData, \"Code\", \"User\");\r\n }\r\n default:\r\n return join(home, \".config\", \"Code\", \"User\");\r\n }\r\n}\r\n\r\n/**\r\n * The `tasks` root holding per-task subdirectories. Honors an\r\n * AGENT_CONNECTOR_ROO_CODE_DIR override (verbatim, non-empty, ~-expanded,\r\n * resolved against CWD when relative), else the extension's globalStorage tasks\r\n * dir under the resolved VS Code user dir.\r\n */\r\nfunction tasksRoot(): string {\r\n const raw = process.env.AGENT_CONNECTOR_ROO_CODE_DIR;\r\n if (raw != null && raw.trim() !== \"\") {\r\n const expanded = expandHome(raw.trim());\r\n return isAbsolute(expanded) ? expanded : resolve(expanded);\r\n }\r\n return join(vscodeUserDir(), \"globalStorage\", ROO_EXTENSION_ID, \"tasks\");\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Value coercion (ports of utils.rs extract_i64 / extract_f64 / parse_timestamp_str)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Port of extract_i64: number / numeric-string → integer, else undefined. */\r\nfunction extractI64(v: unknown): number | undefined {\r\n if (typeof v === \"number\") {\r\n if (!Number.isFinite(v)) return undefined;\r\n return Math.trunc(v);\r\n }\r\n if (typeof v === \"string\") {\r\n const trimmed = v.trim();\r\n if (!/^[+-]?\\d+$/.test(trimmed)) return undefined; // Rust parses as i64 (integer-only)\r\n const n = Number(trimmed);\r\n return Number.isFinite(n) ? Math.trunc(n) : undefined;\r\n }\r\n return undefined;\r\n}\r\n\r\n/** A non-negative integer from a payload field (0 on absence/garbage, clamped ≥ 0). */\r\nfunction tokenField(v: unknown): number {\r\n const n = extractI64(v);\r\n return n === undefined ? 0 : Math.max(0, n);\r\n}\r\n\r\n/** Port of extract_f64: number / numeric-string → f64, else undefined. */\r\nfunction extractF64(v: unknown): number | undefined {\r\n if (typeof v === \"number\") return Number.isFinite(v) ? v : undefined;\r\n if (typeof v === \"string\") {\r\n const n = Number(v.trim());\r\n return Number.isFinite(n) ? n : undefined;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Port of utils.rs parse_timestamp_str / parse_entry_timestamp: an RFC3339 string\r\n * → epoch ms; an integer (string or number) → ms (×1000 when below the 1e12 ms\r\n * threshold); rejects ≤ 0. Returns null when unusable so the entry is skipped.\r\n */\r\nfunction parseEntryTimestamp(v: unknown): number | null {\r\n let s: string;\r\n if (typeof v === \"string\") s = v;\r\n else if (typeof v === \"number\" && Number.isFinite(v)) s = String(Math.trunc(v));\r\n else return null;\r\n\r\n return parseTimestampStr(s);\r\n}\r\n\r\nfunction parseTimestampStr(value: string): number | null {\r\n const ms = Date.parse(value);\r\n if (!Number.isNaN(ms)) return ms; // RFC3339 / any Date-parseable form\r\n\r\n if (/^[+-]?\\d+$/.test(value.trim())) {\r\n const numeric = Number(value.trim());\r\n if (!Number.isFinite(numeric) || numeric <= 0) return null;\r\n return numeric >= 1_000_000_000_000 ? numeric : numeric * 1000;\r\n }\r\n return null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// session id (port of extract_session_id)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Session id = the parent directory (taskId) of ui_messages.json, else \"unknown\". */\r\nfunction extractSessionId(path: string): string {\r\n const parent = basename(dirname(path));\r\n return parent !== \"\" ? parent : DEFAULT_SESSION;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// model / agent (ports of read_task_metadata / extract_model_and_agent / extract_tag_value)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface TaskMetadata {\r\n model: string;\r\n agent?: string;\r\n}\r\n\r\n/** Read the sibling api_conversation_history.json for model/agent (fail-open). */\r\nfunction readTaskMetadata(uiMessagesPath: string): TaskMetadata {\r\n const historyPath = join(dirname(uiMessagesPath), \"api_conversation_history.json\");\r\n let content: string;\r\n try {\r\n content = readFileSync(historyPath, \"utf8\");\r\n } catch {\r\n return { model: DEFAULT_MODEL }; // missing/unreadable → (\"unknown\", None)\r\n }\r\n return extractModelAndAgent(content);\r\n}\r\n\r\n/**\r\n * Scan every <environment_details>…</environment_details> block, extracting\r\n * <model>, <slug>, <name>. The LAST non-empty value of each tag wins (port of the\r\n * Rust last_* accumulation). model defaults to \"unknown\"; agent prefers slug then\r\n * name (and is omitted when neither is present).\r\n */\r\nfunction extractModelAndAgent(content: string): TaskMetadata {\r\n const ENV_START = \"<environment_details>\";\r\n const ENV_END = \"</environment_details>\";\r\n\r\n let offset = 0;\r\n let lastModel: string | undefined;\r\n let lastSlug: string | undefined;\r\n let lastName: string | undefined;\r\n\r\n for (;;) {\r\n const startRel = content.indexOf(ENV_START, offset);\r\n if (startRel < 0) break;\r\n const startIdx = startRel + ENV_START.length;\r\n\r\n const endRel = content.indexOf(ENV_END, startIdx);\r\n if (endRel < 0) break;\r\n\r\n const block = content.slice(startIdx, endRel);\r\n\r\n const model = extractTagValue(block, \"model\");\r\n if (model !== undefined) lastModel = model;\r\n const slug = extractTagValue(block, \"slug\");\r\n if (slug !== undefined) lastSlug = slug;\r\n const name = extractTagValue(block, \"name\");\r\n if (name !== undefined) lastName = name;\r\n\r\n offset = endRel + ENV_END.length;\r\n }\r\n\r\n const agent = lastSlug ?? lastName;\r\n const result: TaskMetadata = { model: lastModel ?? DEFAULT_MODEL };\r\n if (agent !== undefined) result.agent = agent;\r\n return result;\r\n}\r\n\r\n/** First <tag>…</tag> value in `block`, trimmed; undefined when absent or empty. */\r\nfunction extractTagValue(block: string, tag: string): string | undefined {\r\n const open = `<${tag}>`;\r\n const close = `</${tag}>`;\r\n\r\n const openIdx = block.indexOf(open);\r\n if (openIdx < 0) return undefined;\r\n const start = openIdx + open.length;\r\n const endRel = block.indexOf(close, start);\r\n if (endRel < 0) return undefined;\r\n\r\n const value = block.slice(start, endRel).trim();\r\n return value === \"\" ? undefined : value;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// api_req_started payload (port of parse_api_req_started_payload + provider_from_api_protocol)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface ApiReqStartedPayload {\r\n cost: number;\r\n tokensIn: number;\r\n tokensOut: number;\r\n cacheReads: number;\r\n cacheWrites: number;\r\n apiProtocol?: string;\r\n}\r\n\r\n/** Parse the JSON-in-string `text` payload of an api_req_started entry. */\r\nfunction parseApiReqStartedPayload(text: string): ApiReqStartedPayload | undefined {\r\n let value: unknown;\r\n try {\r\n value = JSON.parse(text);\r\n } catch {\r\n return undefined;\r\n }\r\n if (typeof value !== \"object\" || value === null) return undefined;\r\n const obj = value as Record<string, unknown>;\r\n\r\n // cost: extract_f64(.cost).unwrap_or(0.0).max(0.0)\r\n const cost = Math.max(0, extractF64(obj[\"cost\"]) ?? 0);\r\n const apiProtocolRaw = typeof obj[\"apiProtocol\"] === \"string\" ? (obj[\"apiProtocol\"] as string) : undefined;\r\n\r\n const payload: ApiReqStartedPayload = {\r\n cost,\r\n tokensIn: tokenField(obj[\"tokensIn\"]),\r\n tokensOut: tokenField(obj[\"tokensOut\"]),\r\n cacheReads: tokenField(obj[\"cacheReads\"]),\r\n cacheWrites: tokenField(obj[\"cacheWrites\"]),\r\n };\r\n if (apiProtocolRaw !== undefined) payload.apiProtocol = apiProtocolRaw;\r\n return payload;\r\n}\r\n\r\n/** Provider from apiProtocol: trimmed, non-empty, else \"unknown\" (verbatim — no inference). */\r\nfunction providerFromApiProtocol(apiProtocol: string | undefined): string {\r\n if (apiProtocol === undefined) return DEFAULT_PROVIDER;\r\n const trimmed = apiProtocol.trim();\r\n return trimmed === \"\" ? DEFAULT_PROVIDER : trimmed;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// File parse (port of parse_roo_kilo_file with source \"roocode\")\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The fields we read off a ui_messages.json entry (all optional / unknown). */\r\ninterface UiMessageEntry {\r\n type?: unknown;\r\n say?: unknown;\r\n text?: unknown;\r\n ts?: unknown;\r\n}\r\n\r\n/** Parse one task's ui_messages.json into usage records. */\r\nfunction parseRooCodeFile(path: string): UsageRecord[] {\r\n const data = readJsonFile(path);\r\n if (!Array.isArray(data)) return []; // malformed / non-array → no rows\r\n\r\n const sessionId = extractSessionId(path);\r\n const { model, agent } = readTaskMetadata(path);\r\n\r\n const out: UsageRecord[] = [];\r\n for (const raw of data) {\r\n if (typeof raw !== \"object\" || raw === null) continue;\r\n const entry = raw as UiMessageEntry;\r\n\r\n if (entry.type !== \"say\" || entry.say !== \"api_req_started\") continue;\r\n\r\n if (typeof entry.text !== \"string\") continue; // None => skip\r\n const ts = parseEntryTimestamp(entry.ts);\r\n if (ts === null) continue; // unparseable ts => skip\r\n\r\n const payload = parseApiReqStartedPayload(entry.text);\r\n if (payload === undefined) continue; // malformed payload => skip\r\n\r\n const providerId = providerFromApiProtocol(payload.apiProtocol);\r\n\r\n const tokens = emptyTokens();\r\n tokens.input = payload.tokensIn;\r\n tokens.output = payload.tokensOut;\r\n tokens.cacheRead = payload.cacheReads;\r\n tokens.cacheWrite = payload.cacheWrites;\r\n // reasoning stays 0 (Roo Code does not report it).\r\n\r\n const record: UsageRecord = {\r\n platformId: PLATFORM_ID,\r\n modelId: model,\r\n providerId,\r\n sessionId,\r\n tokens,\r\n ts,\r\n messageCount: 1,\r\n confidence: \"host-reported\",\r\n };\r\n if (payload.cost > 0) record.cost = payload.cost;\r\n if (agent !== undefined) record.agent = agent;\r\n out.push(record);\r\n }\r\n\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Reader singleton\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The Roo Code (VS Code extension) usage reader singleton. */\r\nconst rooCodeReader: UsageReader = {\r\n platformId: PLATFORM_ID,\r\n kind: \"local\",\r\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\r\n const root = tasksRoot();\r\n if (!existsSync(root)) return []; // no tasks dir → fail-open\r\n\r\n // <root>/<taskId>/ui_messages.json\r\n const files = walkFiles(root, (name, abs) => {\r\n return name === \"ui_messages.json\" && /[\\\\/]ui_messages\\.json$/.test(abs);\r\n });\r\n\r\n const records: UsageRecord[] = [];\r\n for (const file of files) {\r\n let rows: UsageRecord[];\r\n try {\r\n rows = parseRooCodeFile(file);\r\n } catch {\r\n continue; // fail-open per file\r\n }\r\n for (const row of rows) {\r\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\r\n records.push(row);\r\n }\r\n }\r\n return records;\r\n },\r\n};\r\n\r\nexport default rooCodeReader;\r\n"],"mappings":"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","names":[]}
@@ -4,24 +4,24 @@ import {
4
4
  runServe,
5
5
  runStatusline,
6
6
  runUsageEvent
7
- } from "../chunk-YPAXJ7EW.js";
8
- import "../chunk-OP4KBXUO.js";
9
- import "../chunk-Z2MRSS2I.js";
10
- import "../chunk-ISEJWBFF.js";
7
+ } from "../chunk-FHYR5Q5T.js";
8
+ import "../chunk-LFWYYWLV.js";
9
+ import "../chunk-SLJI5BOM.js";
10
+ import "../chunk-GZZCHJDP.js";
11
11
  import {
12
12
  isNativeHookDeclared,
13
13
  runHook,
14
14
  runNativeHook
15
- } from "../chunk-I5UXHIDT.js";
16
- import "../chunk-KHO5WNTP.js";
17
- import "../chunk-IVAWP6HH.js";
18
- import "../chunk-PW42ZXCB.js";
19
- import "../chunk-5IOTP7LQ.js";
20
- import "../chunk-D4ELPBB5.js";
21
- import "../chunk-NBYKLUF6.js";
22
- import "../chunk-4NHXLXSD.js";
23
- import "../chunk-UMQ6NBQR.js";
24
- import "../chunk-GZGLCCEE.js";
15
+ } from "../chunk-GCPEPUD7.js";
16
+ import "../chunk-IOJDZJ72.js";
17
+ import "../chunk-4GH2KA7V.js";
18
+ import "../chunk-3EP5V2F4.js";
19
+ import "../chunk-7ZFK2WEO.js";
20
+ import "../chunk-NDMNMAKP.js";
21
+ import "../chunk-KFPSJRHR.js";
22
+ import "../chunk-Y3K6KJMS.js";
23
+ import "../chunk-ILWHLGIC.js";
24
+ import "../chunk-QYOUQCC6.js";
25
25
  export {
26
26
  isNativeHookDeclared,
27
27
  runAction,
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  capabilitiesOf,
5
5
  hostsSupporting,
6
6
  surfaceSupport
7
- } from "../chunk-3NH2ARIS.js";
7
+ } from "../chunk-WPTNMYYM.js";
8
8
  import {
9
9
  ConnectorConfigError,
10
10
  defineAction,
@@ -17,11 +17,11 @@ import {
17
17
  defineSkill,
18
18
  defineStatusline,
19
19
  defineSubagent
20
- } from "../chunk-5IOTP7LQ.js";
21
- import "../chunk-D4ELPBB5.js";
22
- import "../chunk-NBYKLUF6.js";
23
- import "../chunk-UMQ6NBQR.js";
24
- import "../chunk-GZGLCCEE.js";
20
+ } from "../chunk-7ZFK2WEO.js";
21
+ import "../chunk-NDMNMAKP.js";
22
+ import "../chunk-KFPSJRHR.js";
23
+ import "../chunk-ILWHLGIC.js";
24
+ import "../chunk-QYOUQCC6.js";
25
25
 
26
26
  // src/sdk/helpers.ts
27
27
  var PREFIXED_HOSTS = /* @__PURE__ */ new Set([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/sdk/helpers.ts"],"sourcesContent":["/**\n * sdk/helpers — host-aware authoring helpers for connector handlers.\n *\n * A handler (a hook, a statusline render, an action run) sees the host it is\n * dispatched for via the {@link HostCtx} (`ctx.host`). These two helpers let a\n * handler render a host-correct value without hardcoding a per-host branch:\n *\n * • {@link toolName} — resolve a bare MCP tool name to the host's native\n * reference form (some hosts namespace MCP tools as `mcp__<id>__<tool>`).\n * • {@link style} — wrap text in an ANSI escape ONLY on hosts that render\n * ANSI in a status line / output; plain everywhere else.\n *\n * Both are deliberately MODEST, documented best-effort lists — NOT a capability\n * query. The per-host convention each encodes is not centrally modeled in\n * {@link PlatformCapabilities} yet; if either set grows it should migrate to a\n * capability flag (a `mcpToolPrefix` / `rendersAnsi` flag) the adapter declares.\n */\n\nimport type { PlatformId } from \"../core/types.js\";\n\n/**\n * Hosts that namespace MCP tools as `mcp__<connectorId>__<tool>` — the\n * `mcp__`-prefix convention Claude Code popularized and most MCP-client agents\n * adopted. CONFIRMED in-repo via the adapters' own `mcp__` PreToolUse matchers\n * for claude-code, codex, and kimi; the remaining members are MCP-client hosts\n * the convention applies to but are not separately verified here (a wrong\n * inclusion only ever yields a name the host doesn't resolve, the same outcome\n * as wrongly EXCLUDING a prefixing host — and an author can always construct the\n * reference themselves). This is a SMALL explicit set, not a capability query;\n * if it grows, migrate it to a per-adapter `mcpToolPrefix` capability flag.\n * (Follow-up: spot-verify gemini-cli / a copilot variant on a live box.)\n */\nconst PREFIXED_HOSTS: ReadonlySet<PlatformId> = new Set<PlatformId>([\n \"claude-code\",\n \"codex\",\n \"kimi\",\n \"cursor\",\n \"copilot-cli\",\n \"vscode-copilot\",\n \"jetbrains-copilot\",\n \"gemini-cli\",\n \"qwen-code\",\n]);\n\n/**\n * Resolve a bare MCP tool name to the host's native reference form.\n *\n * On a {@link PREFIXED_HOSTS} host the result is `mcp__<connectorId>__<baseName>`\n * (how those hosts surface a connector's MCP tools); on every other host it is\n * the bare `baseName`. When the host prefixes but no `connectorId` is supplied\n * the helper falls back to the bare name rather than emitting a malformed\n * `mcp__undefined__…` reference — it NEVER throws.\n */\nexport function toolName(\n ctx: { host: PlatformId; connectorId?: string },\n baseName: string,\n): string {\n if (PREFIXED_HOSTS.has(ctx.host) && ctx.connectorId) {\n return `mcp__${ctx.connectorId}__${baseName}`;\n }\n return baseName;\n}\n\n/**\n * Hosts that render ANSI escape sequences in a status line / terminal output —\n * the CLI/TUI hosts. IDE-embedded hosts (where output lands in a webview /\n * editor panel that shows the raw escape) are deliberately EXCLUDED. Like\n * {@link PREFIXED_HOSTS} this is a documented best-effort list, not a capability\n * query; migrate it to a `rendersAnsi` capability flag if it grows.\n */\nconst ANSI_HOSTS: ReadonlySet<PlatformId> = new Set<PlatformId>([\n \"claude-code\",\n \"codex\",\n \"gemini-cli\",\n \"qwen-code\",\n \"cursor\",\n \"copilot-cli\",\n \"opencode\",\n \"droid\",\n \"crush\",\n \"goose\",\n \"amp\",\n]);\n\n/**\n * Style `text` with an ANSI SGR escape on hosts that render it (a status line /\n * terminal output), plain everywhere else.\n *\n * When `ctx.host` is in {@link ANSI_HOSTS} and `codes.ansi` is provided, returns\n * `\\x1b[<ansi>m<text>\\x1b[0m`; otherwise returns `text` unchanged (an\n * IDE-embedded host, or no `ansi` code given). `codes.ansi` is the SGR\n * parameter(s), e.g. `\"1\"` (bold) or `\"1;32\"` (bold green).\n */\nexport function style(\n ctx: { host: PlatformId },\n text: string,\n codes: { ansi?: string },\n): string {\n if (codes.ansi && ANSI_HOSTS.has(ctx.host)) {\n return `\\x1b[${codes.ansi}m${text}\\x1b[0m`;\n }\n return text;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,iBAA0C,oBAAI,IAAgB;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWM,SAAS,SACd,KACA,UACQ;AACR,MAAI,eAAe,IAAI,IAAI,IAAI,KAAK,IAAI,aAAa;AACnD,WAAO,QAAQ,IAAI,WAAW,KAAK,QAAQ;AAAA,EAC7C;AACA,SAAO;AACT;AASA,IAAM,aAAsC,oBAAI,IAAgB;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWM,SAAS,MACd,KACA,MACA,OACQ;AACR,MAAI,MAAM,QAAQ,WAAW,IAAI,IAAI,IAAI,GAAG;AAC1C,WAAO,QAAQ,MAAM,IAAI,IAAI,IAAI;AAAA,EACnC;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../src/sdk/helpers.ts"],"sourcesContent":["/**\r\n * sdk/helpers — host-aware authoring helpers for connector handlers.\r\n *\r\n * A handler (a hook, a statusline render, an action run) sees the host it is\r\n * dispatched for via the {@link HostCtx} (`ctx.host`). These two helpers let a\r\n * handler render a host-correct value without hardcoding a per-host branch:\r\n *\r\n * • {@link toolName} — resolve a bare MCP tool name to the host's native\r\n * reference form (some hosts namespace MCP tools as `mcp__<id>__<tool>`).\r\n * • {@link style} — wrap text in an ANSI escape ONLY on hosts that render\r\n * ANSI in a status line / output; plain everywhere else.\r\n *\r\n * Both are deliberately MODEST, documented best-effort lists — NOT a capability\r\n * query. The per-host convention each encodes is not centrally modeled in\r\n * {@link PlatformCapabilities} yet; if either set grows it should migrate to a\r\n * capability flag (a `mcpToolPrefix` / `rendersAnsi` flag) the adapter declares.\r\n */\r\n\r\nimport type { PlatformId } from \"../core/types.js\";\r\n\r\n/**\r\n * Hosts that namespace MCP tools as `mcp__<connectorId>__<tool>` — the\r\n * `mcp__`-prefix convention Claude Code popularized and most MCP-client agents\r\n * adopted. CONFIRMED in-repo via the adapters' own `mcp__` PreToolUse matchers\r\n * for claude-code, codex, and kimi; the remaining members are MCP-client hosts\r\n * the convention applies to but are not separately verified here (a wrong\r\n * inclusion only ever yields a name the host doesn't resolve, the same outcome\r\n * as wrongly EXCLUDING a prefixing host — and an author can always construct the\r\n * reference themselves). This is a SMALL explicit set, not a capability query;\r\n * if it grows, migrate it to a per-adapter `mcpToolPrefix` capability flag.\r\n * (Follow-up: spot-verify gemini-cli / a copilot variant on a live box.)\r\n */\r\nconst PREFIXED_HOSTS: ReadonlySet<PlatformId> = new Set<PlatformId>([\r\n \"claude-code\",\r\n \"codex\",\r\n \"kimi\",\r\n \"cursor\",\r\n \"copilot-cli\",\r\n \"vscode-copilot\",\r\n \"jetbrains-copilot\",\r\n \"gemini-cli\",\r\n \"qwen-code\",\r\n]);\r\n\r\n/**\r\n * Resolve a bare MCP tool name to the host's native reference form.\r\n *\r\n * On a {@link PREFIXED_HOSTS} host the result is `mcp__<connectorId>__<baseName>`\r\n * (how those hosts surface a connector's MCP tools); on every other host it is\r\n * the bare `baseName`. When the host prefixes but no `connectorId` is supplied\r\n * the helper falls back to the bare name rather than emitting a malformed\r\n * `mcp__undefined__…` reference — it NEVER throws.\r\n */\r\nexport function toolName(\r\n ctx: { host: PlatformId; connectorId?: string },\r\n baseName: string,\r\n): string {\r\n if (PREFIXED_HOSTS.has(ctx.host) && ctx.connectorId) {\r\n return `mcp__${ctx.connectorId}__${baseName}`;\r\n }\r\n return baseName;\r\n}\r\n\r\n/**\r\n * Hosts that render ANSI escape sequences in a status line / terminal output —\r\n * the CLI/TUI hosts. IDE-embedded hosts (where output lands in a webview /\r\n * editor panel that shows the raw escape) are deliberately EXCLUDED. Like\r\n * {@link PREFIXED_HOSTS} this is a documented best-effort list, not a capability\r\n * query; migrate it to a `rendersAnsi` capability flag if it grows.\r\n */\r\nconst ANSI_HOSTS: ReadonlySet<PlatformId> = new Set<PlatformId>([\r\n \"claude-code\",\r\n \"codex\",\r\n \"gemini-cli\",\r\n \"qwen-code\",\r\n \"cursor\",\r\n \"copilot-cli\",\r\n \"opencode\",\r\n \"droid\",\r\n \"crush\",\r\n \"goose\",\r\n \"amp\",\r\n]);\r\n\r\n/**\r\n * Style `text` with an ANSI SGR escape on hosts that render it (a status line /\r\n * terminal output), plain everywhere else.\r\n *\r\n * When `ctx.host` is in {@link ANSI_HOSTS} and `codes.ansi` is provided, returns\r\n * `\\x1b[<ansi>m<text>\\x1b[0m`; otherwise returns `text` unchanged (an\r\n * IDE-embedded host, or no `ansi` code given). `codes.ansi` is the SGR\r\n * parameter(s), e.g. `\"1\"` (bold) or `\"1;32\"` (bold green).\r\n */\r\nexport function style(\r\n ctx: { host: PlatformId },\r\n text: string,\r\n codes: { ansi?: string },\r\n): string {\r\n if (codes.ansi && ANSI_HOSTS.has(ctx.host)) {\r\n return `\\x1b[${codes.ansi}m${text}\\x1b[0m`;\r\n }\r\n return text;\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA,IAAM,iBAA0C,oBAAI,IAAgB;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWM,SAAS,SACd,KACA,UACQ;AACR,MAAI,eAAe,IAAI,IAAI,IAAI,KAAK,IAAI,aAAa;AACnD,WAAO,QAAQ,IAAI,WAAW,KAAK,QAAQ;AAAA,EAC7C;AACA,SAAO;AACT;AASA,IAAM,aAAsC,oBAAI,IAAgB;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWM,SAAS,MACd,KACA,MACA,OACQ;AACR,MAAI,MAAM,QAAQ,WAAW,IAAI,IAAI,IAAI,GAAG;AAC1C,WAAO,QAAQ,MAAM,IAAI,IAAI,IAAI;AAAA,EACnC;AACA,SAAO;AACT;","names":[]}
package/dist/sdk/test.js CHANGED
@@ -3,17 +3,17 @@ import {
3
3
  explain,
4
4
  explainHooks,
5
5
  simulate
6
- } from "../chunk-7F5KHLEP.js";
7
- import "../chunk-I5UXHIDT.js";
8
- import "../chunk-KHO5WNTP.js";
9
- import "../chunk-IVAWP6HH.js";
10
- import "../chunk-3NH2ARIS.js";
11
- import "../chunk-PW42ZXCB.js";
12
- import "../chunk-5IOTP7LQ.js";
13
- import "../chunk-D4ELPBB5.js";
14
- import "../chunk-NBYKLUF6.js";
15
- import "../chunk-UMQ6NBQR.js";
16
- import "../chunk-GZGLCCEE.js";
6
+ } from "../chunk-L2C5UMKW.js";
7
+ import "../chunk-GCPEPUD7.js";
8
+ import "../chunk-IOJDZJ72.js";
9
+ import "../chunk-4GH2KA7V.js";
10
+ import "../chunk-WPTNMYYM.js";
11
+ import "../chunk-3EP5V2F4.js";
12
+ import "../chunk-7ZFK2WEO.js";
13
+ import "../chunk-NDMNMAKP.js";
14
+ import "../chunk-KFPSJRHR.js";
15
+ import "../chunk-ILWHLGIC.js";
16
+ import "../chunk-QYOUQCC6.js";
17
17
  export {
18
18
  explain,
19
19
  explainHooks,
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  fail
4
- } from "./chunk-H33M77DD.js";
4
+ } from "./chunk-N4ENLZEU.js";
5
5
  import {
6
6
  runServe
7
- } from "./chunk-YPAXJ7EW.js";
8
- import "./chunk-OP4KBXUO.js";
9
- import "./chunk-Z2MRSS2I.js";
10
- import "./chunk-ISEJWBFF.js";
11
- import "./chunk-I5UXHIDT.js";
12
- import "./chunk-KHO5WNTP.js";
13
- import "./chunk-IVAWP6HH.js";
14
- import "./chunk-PW42ZXCB.js";
15
- import "./chunk-5IOTP7LQ.js";
16
- import "./chunk-D4ELPBB5.js";
17
- import "./chunk-NBYKLUF6.js";
18
- import "./chunk-4NHXLXSD.js";
19
- import "./chunk-UMQ6NBQR.js";
20
- import "./chunk-GZGLCCEE.js";
7
+ } from "./chunk-FHYR5Q5T.js";
8
+ import "./chunk-LFWYYWLV.js";
9
+ import "./chunk-SLJI5BOM.js";
10
+ import "./chunk-GZZCHJDP.js";
11
+ import "./chunk-GCPEPUD7.js";
12
+ import "./chunk-IOJDZJ72.js";
13
+ import "./chunk-4GH2KA7V.js";
14
+ import "./chunk-3EP5V2F4.js";
15
+ import "./chunk-7ZFK2WEO.js";
16
+ import "./chunk-NDMNMAKP.js";
17
+ import "./chunk-KFPSJRHR.js";
18
+ import "./chunk-Y3K6KJMS.js";
19
+ import "./chunk-ILWHLGIC.js";
20
+ import "./chunk-QYOUQCC6.js";
21
21
 
22
22
  // src/cli/commands/serve.ts
23
23
  import { parseArgs } from "util";
@@ -74,4 +74,4 @@ async function run(argv) {
74
74
  export {
75
75
  run
76
76
  };
77
- //# sourceMappingURL=serve-XTMIUHKK.js.map
77
+ //# sourceMappingURL=serve-LYSBH43G.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/commands/serve.ts"],"sourcesContent":["/**\r\n * cli/commands/serve — the telemetry-wrapping MCP stdio proxy entrypoint.\r\n *\r\n * agent-connector serve --connector <id> [--scope <user|project>] [--host <platformId>] -- <realCommand> <realArgs...>\r\n *\r\n * A stdio MCP server that opts into transparent telemetry has its host config\r\n * rewritten to launch THIS instead of the server directly. We split argv at the\r\n * literal `--` separator: flags on the left, the real server command + args on\r\n * the right (taken verbatim). The optional `--scope` flag records the install\r\n * dimension (global user vs project-local) onto telemetry; it is absent for\r\n * configs written before scope plumbing existed → the runtime reads \"unknown\".\r\n * The optional `--host` flag carries the install TARGET platform id so the proxy\r\n * stamps hostPlatform correctly under a headless spawn; absent configs fall back\r\n * to runtime env detection.\r\n * The optional `--data-dir` flag pins the framework data-root the child must use\r\n * to resolve the connector record (and write telemetry). It is written by the\r\n * wrapper only for a NON-DEFAULT root, because some hosts (codex) strip the MCP\r\n * child's environment and would otherwise not propagate AGENT_CONNECTOR_DATA_DIR\r\n * — the child would then resolve the default root and fail \"Connector not\r\n * registered\". Absent configs resolve the data-root the usual way.\r\n * runServe stands up the per-session telemetry context and proxies bytes both\r\n * ways, resolving with the child's exit code.\r\n */\r\n\r\nimport { parseArgs } from \"node:util\";\r\n\r\nimport type { PlatformId } from \"../../core/types.js\";\r\nimport type { TelemetryInstallScope } from \"../../telemetry/types.js\";\r\nimport { runServe } from \"../../runtime/index.js\";\r\nimport { fail } from \"../app.js\";\r\n\r\nexport async function run(argv: string[]): Promise<number> {\r\n // Split at the FIRST literal \"--\": everything after it is the real server\r\n // invocation and must be passed through verbatim (never re-parsed as flags).\r\n const sepIndex = argv.indexOf(\"--\");\r\n if (sepIndex === -1) {\r\n return fail(\r\n \"usage: agent-connector serve --connector <id> [--scope <user|project>] [--host <platformId>] [--data-dir <path>] -- <command> [args...]\",\r\n );\r\n }\r\n const flagArgs = argv.slice(0, sepIndex);\r\n const serverInvocation = argv.slice(sepIndex + 1);\r\n\r\n // strict:false so an unknown FUTURE flag before `--` (written by a newer host\r\n // config) is ignored instead of throwing — a parse throw here would prevent the\r\n // real MCP server from ever spawning and wedge the host's tool call. We only\r\n // read the flags we understand; everything else is tolerated.\r\n const { values } = parseArgs({\r\n args: flagArgs,\r\n options: {\r\n connector: { type: \"string\" },\r\n scope: { type: \"string\" },\r\n // `--host <platformId>` bakes the install TARGET platform into the wrapper\r\n // so the proxy stamps hostPlatform correctly under a headless spawn (where\r\n // runtime env markers are absent). Optional + tolerated (strict:false).\r\n host: { type: \"string\" },\r\n // `--data-dir <path>` pins the framework data-root for the child (connector\r\n // record + telemetry). Written only for a NON-DEFAULT root, so the child\r\n // never depends on inheriting AGENT_CONNECTOR_DATA_DIR (codex strips it).\r\n // Optional + tolerated (strict:false).\r\n \"data-dir\": { type: \"string\" },\r\n },\r\n allowPositionals: true,\r\n strict: false,\r\n });\r\n\r\n // With strict:false, parseArgs types each value as string | boolean; we only\r\n // accept the string form (a bare `--connector` flag with no value is invalid).\r\n const connectorId = typeof values.connector === \"string\" ? values.connector : undefined;\r\n if (!connectorId || connectorId.trim() === \"\") {\r\n return fail(\"serve requires --connector <id>\");\r\n }\r\n\r\n // `--scope` is optional and only ever \"user\" | \"project\" (the wrapper emits\r\n // exactly those). An unrecognized value is ignored rather than fatal so a\r\n // future/older wrapper can never break a real tool call over a flag mismatch.\r\n const rawScope = values.scope;\r\n const installScope: TelemetryInstallScope | undefined =\r\n rawScope === \"user\" || rawScope === \"project\" ? rawScope : undefined;\r\n\r\n // `--host` carries the install TARGET platform id (string only). runServe\r\n // validates it against the registry and falls back to runtime detection when\r\n // it is absent or unrecognized — so a future/older wrapper never breaks here.\r\n const hostPlatformOverride =\r\n typeof values.host === \"string\" ? (values.host as PlatformId) : undefined;\r\n\r\n // `--data-dir` pins the framework data-root (string only). When present and\r\n // non-empty, runServe makes the WHOLE child resolve this root — connector\r\n // record lookup AND telemetry store — so the wrap is independent of the child\r\n // env that codex strips. Absent → resolve the data-root the usual way.\r\n const dataDir =\r\n typeof values[\"data-dir\"] === \"string\" && values[\"data-dir\"].trim() !== \"\"\r\n ? values[\"data-dir\"]\r\n : undefined;\r\n\r\n const serverCommand = serverInvocation[0];\r\n if (!serverCommand) {\r\n return fail(\"serve requires a command after `--`\");\r\n }\r\n const serverArgs = serverInvocation.slice(1);\r\n\r\n const code = await runServe({\r\n connectorId,\r\n serverCommand,\r\n serverArgs,\r\n installScope,\r\n hostPlatformOverride,\r\n dataDir,\r\n });\r\n process.exit(code);\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAS,iBAAiB;AAO1B,eAAsB,IAAI,MAAiC;AAGzD,QAAM,WAAW,KAAK,QAAQ,IAAI;AAClC,MAAI,aAAa,IAAI;AACnB,WAAO;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACA,QAAM,WAAW,KAAK,MAAM,GAAG,QAAQ;AACvC,QAAM,mBAAmB,KAAK,MAAM,WAAW,CAAC;AAMhD,QAAM,EAAE,OAAO,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,MACP,WAAW,EAAE,MAAM,SAAS;AAAA,MAC5B,OAAO,EAAE,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA,MAIxB,MAAM,EAAE,MAAM,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,MAKvB,YAAY,EAAE,MAAM,SAAS;AAAA,IAC/B;AAAA,IACA,kBAAkB;AAAA,IAClB,QAAQ;AAAA,EACV,CAAC;AAID,QAAM,cAAc,OAAO,OAAO,cAAc,WAAW,OAAO,YAAY;AAC9E,MAAI,CAAC,eAAe,YAAY,KAAK,MAAM,IAAI;AAC7C,WAAO,KAAK,iCAAiC;AAAA,EAC/C;AAKA,QAAM,WAAW,OAAO;AACxB,QAAM,eACJ,aAAa,UAAU,aAAa,YAAY,WAAW;AAK7D,QAAM,uBACJ,OAAO,OAAO,SAAS,WAAY,OAAO,OAAsB;AAMlE,QAAM,UACJ,OAAO,OAAO,UAAU,MAAM,YAAY,OAAO,UAAU,EAAE,KAAK,MAAM,KACpE,OAAO,UAAU,IACjB;AAEN,QAAM,gBAAgB,iBAAiB,CAAC;AACxC,MAAI,CAAC,eAAe;AAClB,WAAO,KAAK,qCAAqC;AAAA,EACnD;AACA,QAAM,aAAa,iBAAiB,MAAM,CAAC;AAE3C,QAAM,OAAO,MAAM,SAAS;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AACD,UAAQ,KAAK,IAAI;AACnB;","names":[]}