@ken-jo/agent-connector 0.4.7 → 0.4.26

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 (271) hide show
  1. package/README.md +36 -24
  2. package/dist/{action-YCU53FNE.js → action-AZRZ3V7E.js} +14 -14
  3. package/dist/amazon-q-BWSOHTW5.js +571 -0
  4. package/dist/amazon-q-BWSOHTW5.js.map +1 -0
  5. package/dist/{amp-TULUPXXL.js → amp-BQZOL5GR.js} +2 -2
  6. package/dist/{amp-JPBQJJVM.js → amp-TF5X6OGH.js} +18 -50
  7. package/dist/amp-TF5X6OGH.js.map +1 -0
  8. package/dist/antigravity-3XHBPXZK.js +19 -0
  9. package/dist/{antigravity-STHZWMP3.js → antigravity-EA4L225L.js} +2 -2
  10. package/dist/{antigravity-cli-P6HADOAO.js → antigravity-cli-B2HXZFYQ.js} +2 -2
  11. package/dist/{antigravity-cli-D4PCCUG2.js → antigravity-cli-TJGOBUPK.js} +8 -7
  12. package/dist/{antigravity-cli-D4PCCUG2.js.map → antigravity-cli-TJGOBUPK.js.map} +1 -1
  13. package/dist/{chunk-CYOAH23F.js → chunk-25BNMXPP.js} +18 -18
  14. package/dist/{chunk-NLFPH4S2.js → chunk-2RPHDVHW.js} +2 -2
  15. package/dist/{chunk-PFDUGDOA.js → chunk-3I7UG52L.js} +25 -6
  16. package/dist/chunk-3I7UG52L.js.map +1 -0
  17. package/dist/{chunk-F5RX62T7.js → chunk-7QRUZAUG.js} +2 -2
  18. package/dist/{chunk-BCHWFTV4.js → chunk-F4DSMVZ7.js} +2 -2
  19. package/dist/chunk-FBJQGRET.js +38 -0
  20. package/dist/chunk-FBJQGRET.js.map +1 -0
  21. package/dist/{chunk-WZA4CSGJ.js → chunk-H53QZQJI.js} +15 -2
  22. package/dist/chunk-H53QZQJI.js.map +1 -0
  23. package/dist/{chunk-2F5QH3D4.js → chunk-HU6DZZBG.js} +36 -36
  24. package/dist/{chunk-7ECYDK5T.js → chunk-HZDU3J4U.js} +10 -5
  25. package/dist/chunk-HZDU3J4U.js.map +1 -0
  26. package/dist/{chunk-7L6ITC4T.js → chunk-IEGR4TP3.js} +22 -6
  27. package/dist/chunk-IEGR4TP3.js.map +1 -0
  28. package/dist/{chunk-SCVBYSF7.js → chunk-IRUYJD23.js} +28 -28
  29. package/dist/{chunk-6RYPUR6O.js → chunk-IW46JIQM.js} +34 -44
  30. package/dist/chunk-IW46JIQM.js.map +1 -0
  31. package/dist/{chunk-WFXWJITA.js → chunk-JLMD3IGK.js} +2 -2
  32. package/dist/{chunk-TZQBASI7.js → chunk-KD4BE5MW.js} +13 -49
  33. package/dist/chunk-KD4BE5MW.js.map +1 -0
  34. package/dist/{chunk-FAHIMJRU.js → chunk-L7ESV37V.js} +2 -2
  35. package/dist/{chunk-JNM3TPLX.js → chunk-LETB5HCK.js} +2 -2
  36. package/dist/{chunk-G5CQHVQG.js → chunk-M3H7PQWT.js} +13 -16
  37. package/dist/chunk-M3H7PQWT.js.map +1 -0
  38. package/dist/{chunk-JWNT5KW7.js → chunk-O7SDRBVB.js} +3 -1
  39. package/dist/chunk-O7SDRBVB.js.map +1 -0
  40. package/dist/{chunk-YQLQJZ7S.js → chunk-OLI5SD6I.js} +8 -4
  41. package/dist/chunk-OLI5SD6I.js.map +1 -0
  42. package/dist/{chunk-SDPIT4HW.js → chunk-Q5HR4ADS.js} +2 -2
  43. package/dist/{chunk-TRQKHP7D.js → chunk-QY42WGBX.js} +23 -2
  44. package/dist/chunk-QY42WGBX.js.map +1 -0
  45. package/dist/{chunk-I5MLE6S7.js → chunk-TO57WYBB.js} +15 -1
  46. package/dist/chunk-TO57WYBB.js.map +1 -0
  47. package/dist/chunk-UM5S7DKK.js +33 -0
  48. package/dist/chunk-UM5S7DKK.js.map +1 -0
  49. package/dist/{chunk-MDNX7HTN.js → chunk-YEJCNOET.js} +4 -4
  50. package/dist/{chunk-HAIMYUEY.js → chunk-YKVNI44Y.js} +51 -28
  51. package/dist/chunk-YKVNI44Y.js.map +1 -0
  52. package/dist/{chunk-DT6Y7XBI.js → chunk-YRBFSZ2G.js} +17 -39
  53. package/dist/chunk-YRBFSZ2G.js.map +1 -0
  54. package/dist/{chunk-SPWFUHHK.js → chunk-ZVTPSV5Z.js} +11 -10
  55. package/dist/{chunk-SPWFUHHK.js.map → chunk-ZVTPSV5Z.js.map} +1 -1
  56. package/dist/{chunk-N6HH7K6P.js → chunk-ZY25RG4Y.js} +2 -2
  57. package/dist/{claude-code-ROSIILTM.js → claude-code-JLPFUZ4V.js} +18 -41
  58. package/dist/claude-code-JLPFUZ4V.js.map +1 -0
  59. package/dist/{claude-code-W74MNTAC.js → claude-code-NMRKTAP7.js} +2 -2
  60. package/dist/cli/sdk.js +7 -7
  61. package/dist/cli.js +1 -1
  62. package/dist/{cline-JUTO4V27.js → cline-GBP3EVSX.js} +17 -49
  63. package/dist/cline-GBP3EVSX.js.map +1 -0
  64. package/dist/{codebuff-3PMZJJHP.js → codebuff-ETYT5UBL.js} +2 -2
  65. package/dist/{codebuff-2QUHL6HO.js → codebuff-WMKFUVER.js} +11 -42
  66. package/dist/codebuff-WMKFUVER.js.map +1 -0
  67. package/dist/{codex-YBBTIDD4.js → codex-5CZR5XKX.js} +28 -64
  68. package/dist/codex-5CZR5XKX.js.map +1 -0
  69. package/dist/{codex-Q3ATRRX3.js → codex-YAORPCOD.js} +2 -2
  70. package/dist/{continue-W4TU4JSB.js → continue-3AGXWM5W.js} +12 -35
  71. package/dist/continue-3AGXWM5W.js.map +1 -0
  72. package/dist/{copilot-cli-Y74SOP5G.js → copilot-cli-IH4P3GRZ.js} +17 -66
  73. package/dist/copilot-cli-IH4P3GRZ.js.map +1 -0
  74. package/dist/{copilot-cli-SJGIXVSD.js → copilot-cli-MZTAWMPW.js} +2 -2
  75. package/dist/{crush-GMEWLXK5.js → crush-FDBL3JEK.js} +17 -44
  76. package/dist/crush-FDBL3JEK.js.map +1 -0
  77. package/dist/{crush-LN5QFFR2.js → crush-QBXLNN7T.js} +2 -2
  78. package/dist/{cursor-QZ6MTO74.js → cursor-DIW43TRZ.js} +2 -2
  79. package/dist/{cursor-JBS4B3Q4.js → cursor-R5QB4YR4.js} +15 -53
  80. package/dist/cursor-R5QB4YR4.js.map +1 -0
  81. package/dist/{detect-2NIXILMZ.js → detect-L5OZPVFO.js} +4 -4
  82. package/dist/{doctor-QWJBWALA.js → doctor-WDIQ2YFE.js} +16 -15
  83. package/dist/{doctor-QWJBWALA.js.map → doctor-WDIQ2YFE.js.map} +1 -1
  84. package/dist/{droid-W5WF5XEX.js → droid-U3ZBLQFO.js} +2 -2
  85. package/dist/{droid-TJMTNCQE.js → droid-X2QHQL7D.js} +19 -42
  86. package/dist/droid-X2QHQL7D.js.map +1 -0
  87. package/dist/{gemini-cli-RAONGZRG.js → gemini-cli-HCN7XKSX.js} +17 -65
  88. package/dist/gemini-cli-HCN7XKSX.js.map +1 -0
  89. package/dist/{gemini-cli-CIRW37TU.js → gemini-cli-NMVVBO3K.js} +2 -2
  90. package/dist/{goose-A3M5GODH.js → goose-64V46Y2W.js} +2 -2
  91. package/dist/{goose-G4KKM6YU.js → goose-ILMM76JP.js} +21 -57
  92. package/dist/goose-ILMM76JP.js.map +1 -0
  93. package/dist/{hermes-ZYLMOFLZ.js → hermes-F3EGTK6N.js} +2 -2
  94. package/dist/{hermes-PJDTJE6F.js → hermes-YX2ODUZL.js} +17 -55
  95. package/dist/hermes-YX2ODUZL.js.map +1 -0
  96. package/dist/{hook-FDGIQPRC.js → hook-JRDQ56BN.js} +14 -14
  97. package/dist/index.d.ts +2 -2
  98. package/dist/index.js +5 -5
  99. package/dist/{install-TLG3QVP3.js → install-HRCVPRAQ.js} +16 -15
  100. package/dist/{install-TLG3QVP3.js.map → install-HRCVPRAQ.js.map} +1 -1
  101. package/dist/{introspect-Cn3MSA4_.d.ts → introspect-B164-hj3.d.ts} +1 -1
  102. package/dist/{jetbrains-copilot-DNXSLQE5.js → jetbrains-copilot-QESFUN6W.js} +12 -39
  103. package/dist/jetbrains-copilot-QESFUN6W.js.map +1 -0
  104. package/dist/{kilo-FERJ3X46.js → kilo-POTCYIRG.js} +28 -92
  105. package/dist/kilo-POTCYIRG.js.map +1 -0
  106. package/dist/{kilo-NSWAVP6P.js → kilo-SW7BH6EG.js} +2 -2
  107. package/dist/{kilo-cli-TDCONH5G.js → kilo-cli-MO6FSMH2.js} +19 -50
  108. package/dist/kilo-cli-MO6FSMH2.js.map +1 -0
  109. package/dist/{kilo-cli-EVBKUODA.js → kilo-cli-ZF272ZHN.js} +2 -2
  110. package/dist/{kimi-EI3UM3ZV.js → kimi-5FHEXGZD.js} +72 -13
  111. package/dist/kimi-5FHEXGZD.js.map +1 -0
  112. package/dist/{kimi-RIRD4J5J.js → kimi-RXS36OJP.js} +36 -50
  113. package/dist/kimi-RXS36OJP.js.map +1 -0
  114. package/dist/{kiro-X7JVLAN7.js → kiro-VTLX7CMF.js} +12 -33
  115. package/dist/kiro-VTLX7CMF.js.map +1 -0
  116. package/dist/{kiro-UCLSLBW2.js → kiro-WGOI5CGT.js} +2 -2
  117. package/dist/{leaderboard-MXGENYXN.js → leaderboard-ASGR3E2U.js} +6 -6
  118. package/dist/{mimo-code-RFLQ727H.js → mimo-code-F4BWMESO.js} +57 -91
  119. package/dist/mimo-code-F4BWMESO.js.map +1 -0
  120. package/dist/{mux-D77HBSBU.js → mux-2YFCYFM7.js} +11 -41
  121. package/dist/mux-2YFCYFM7.js.map +1 -0
  122. package/dist/{mux-ZMLVAXOO.js → mux-XM6AP35L.js} +2 -2
  123. package/dist/{nemoclaw-LXUTMR56.js → nemoclaw-QDB6O22A.js} +7 -7
  124. package/dist/{omp-CO7IXURG.js → omp-P2JNAEPN.js} +18 -50
  125. package/dist/omp-P2JNAEPN.js.map +1 -0
  126. package/dist/openclaw-3UMBSSZM.js +18 -0
  127. package/dist/{openclaw-IYA7ASL6.js → openclaw-5EQFGOWL.js} +2 -2
  128. package/dist/{opencode-QKZ5EIYU.js → opencode-Q6H4YT66.js} +24 -90
  129. package/dist/opencode-Q6H4YT66.js.map +1 -0
  130. package/dist/{opencode-HWT3RSMN.js → opencode-QGP4ALQY.js} +2 -2
  131. package/dist/{package-IA56LSC3.js → package-IXBSG7HD.js} +11 -11
  132. package/dist/{pi-UFX2OYFV.js → pi-GGDQREVG.js} +2 -2
  133. package/dist/{pi-YGBXYWY5.js → pi-GW25LPC3.js} +6 -6
  134. package/dist/{qwen-code-W7NUCDEN.js → qwen-code-GQILBJ5B.js} +2 -2
  135. package/dist/{qwen-code-E2MSEZK6.js → qwen-code-R6XXEEHJ.js} +13 -34
  136. package/dist/qwen-code-R6XXEEHJ.js.map +1 -0
  137. package/dist/{roo-code-AGGJ473T.js → roo-code-EZPNFC5V.js} +17 -54
  138. package/dist/roo-code-EZPNFC5V.js.map +1 -0
  139. package/dist/{roo-code-ZLKH4A7N.js → roo-code-SUWI4BBN.js} +2 -2
  140. package/dist/runtime/index.d.ts +1 -1
  141. package/dist/runtime/index.js +12 -12
  142. package/dist/sdk/index.d.ts +3 -3
  143. package/dist/sdk/index.js +6 -6
  144. package/dist/sdk/test.d.ts +2 -2
  145. package/dist/sdk/test.js +9 -9
  146. package/dist/{serve-RNUCK5F7.js → serve-CFBQYKRB.js} +14 -14
  147. package/dist/{status-JOX6RLJU.js → status-ASBFEFQQ.js} +11 -10
  148. package/dist/{status-JOX6RLJU.js.map → status-ASBFEFQQ.js.map} +1 -1
  149. package/dist/{statusline-ZVFI5DRT.js → statusline-WKLWSM7I.js} +13 -13
  150. package/dist/{synthetic-UKR6SMGS.js → synthetic-6FRA7P5Q.js} +2 -2
  151. package/dist/{telemetry-3FN6HDVU.js → telemetry-64GCGNIW.js} +10 -10
  152. package/dist/{trae-6L226ZDU.js → trae-6VQW2UVP.js} +12 -41
  153. package/dist/trae-6VQW2UVP.js.map +1 -0
  154. package/dist/{trae-PA26DPBW.js → trae-CPPYASR2.js} +2 -2
  155. package/dist/{types-_6arHbX9.d.ts → types-COSBYpKs.d.ts} +7 -5
  156. package/dist/{uninstall-SCKZYB4J.js → uninstall-KDJYE5ET.js} +16 -15
  157. package/dist/{uninstall-SCKZYB4J.js.map → uninstall-KDJYE5ET.js.map} +1 -1
  158. package/dist/{upgrade-WU3KZWR4.js → upgrade-YQRVYR5U.js} +16 -15
  159. package/dist/{upgrade-WU3KZWR4.js.map → upgrade-YQRVYR5U.js.map} +1 -1
  160. package/dist/{usage-G72SF7JG.js → usage-OV2BDZKF.js} +3 -3
  161. package/dist/{usage-event-DHSEBO5T.js → usage-event-KPI3NEX3.js} +13 -13
  162. package/dist/{vscode-copilot-6EOZDLXC.js → vscode-copilot-UOEEV4P3.js} +17 -67
  163. package/dist/vscode-copilot-UOEEV4P3.js.map +1 -0
  164. package/dist/{warp-N5YYN5BF.js → warp-LUK2BPCU.js} +9 -21
  165. package/dist/warp-LUK2BPCU.js.map +1 -0
  166. package/dist/{warp-JNQA7PBU.js → warp-NRBBJQR2.js} +2 -2
  167. package/dist/{windsurf-4TGSJIVV.js → windsurf-NZ3G42NQ.js} +8 -20
  168. package/dist/windsurf-NZ3G42NQ.js.map +1 -0
  169. package/dist/{zed-6P2UFWXU.js → zed-LGWGZ4EO.js} +13 -23
  170. package/dist/zed-LGWGZ4EO.js.map +1 -0
  171. package/dist/{zed-NNNX5MNT.js → zed-XJFOOKCO.js} +2 -2
  172. package/package.json +7 -2
  173. package/dist/amazon-q-W574ZX35.js +0 -276
  174. package/dist/amazon-q-W574ZX35.js.map +0 -1
  175. package/dist/amp-JPBQJJVM.js.map +0 -1
  176. package/dist/antigravity-VK2Y3FGV.js +0 -18
  177. package/dist/chunk-6RYPUR6O.js.map +0 -1
  178. package/dist/chunk-7ECYDK5T.js.map +0 -1
  179. package/dist/chunk-7L6ITC4T.js.map +0 -1
  180. package/dist/chunk-DT6Y7XBI.js.map +0 -1
  181. package/dist/chunk-G5CQHVQG.js.map +0 -1
  182. package/dist/chunk-HAIMYUEY.js.map +0 -1
  183. package/dist/chunk-I5MLE6S7.js.map +0 -1
  184. package/dist/chunk-JWNT5KW7.js.map +0 -1
  185. package/dist/chunk-PFDUGDOA.js.map +0 -1
  186. package/dist/chunk-TRQKHP7D.js.map +0 -1
  187. package/dist/chunk-TZQBASI7.js.map +0 -1
  188. package/dist/chunk-WZA4CSGJ.js.map +0 -1
  189. package/dist/chunk-YQLQJZ7S.js.map +0 -1
  190. package/dist/claude-code-ROSIILTM.js.map +0 -1
  191. package/dist/cline-JUTO4V27.js.map +0 -1
  192. package/dist/codebuff-2QUHL6HO.js.map +0 -1
  193. package/dist/codex-YBBTIDD4.js.map +0 -1
  194. package/dist/continue-W4TU4JSB.js.map +0 -1
  195. package/dist/copilot-cli-Y74SOP5G.js.map +0 -1
  196. package/dist/crush-GMEWLXK5.js.map +0 -1
  197. package/dist/cursor-JBS4B3Q4.js.map +0 -1
  198. package/dist/droid-TJMTNCQE.js.map +0 -1
  199. package/dist/gemini-cli-RAONGZRG.js.map +0 -1
  200. package/dist/goose-G4KKM6YU.js.map +0 -1
  201. package/dist/hermes-PJDTJE6F.js.map +0 -1
  202. package/dist/jetbrains-copilot-DNXSLQE5.js.map +0 -1
  203. package/dist/kilo-FERJ3X46.js.map +0 -1
  204. package/dist/kilo-cli-TDCONH5G.js.map +0 -1
  205. package/dist/kimi-EI3UM3ZV.js.map +0 -1
  206. package/dist/kimi-RIRD4J5J.js.map +0 -1
  207. package/dist/kiro-X7JVLAN7.js.map +0 -1
  208. package/dist/mimo-code-RFLQ727H.js.map +0 -1
  209. package/dist/mux-D77HBSBU.js.map +0 -1
  210. package/dist/omp-CO7IXURG.js.map +0 -1
  211. package/dist/openclaw-XWJLEW35.js +0 -18
  212. package/dist/opencode-QKZ5EIYU.js.map +0 -1
  213. package/dist/qwen-code-E2MSEZK6.js.map +0 -1
  214. package/dist/roo-code-AGGJ473T.js.map +0 -1
  215. package/dist/trae-6L226ZDU.js.map +0 -1
  216. package/dist/vscode-copilot-6EOZDLXC.js.map +0 -1
  217. package/dist/warp-N5YYN5BF.js.map +0 -1
  218. package/dist/windsurf-4TGSJIVV.js.map +0 -1
  219. package/dist/zed-6P2UFWXU.js.map +0 -1
  220. /package/dist/{action-YCU53FNE.js.map → action-AZRZ3V7E.js.map} +0 -0
  221. /package/dist/{amp-TULUPXXL.js.map → amp-BQZOL5GR.js.map} +0 -0
  222. /package/dist/{antigravity-VK2Y3FGV.js.map → antigravity-3XHBPXZK.js.map} +0 -0
  223. /package/dist/{antigravity-STHZWMP3.js.map → antigravity-EA4L225L.js.map} +0 -0
  224. /package/dist/{antigravity-cli-P6HADOAO.js.map → antigravity-cli-B2HXZFYQ.js.map} +0 -0
  225. /package/dist/{chunk-CYOAH23F.js.map → chunk-25BNMXPP.js.map} +0 -0
  226. /package/dist/{chunk-NLFPH4S2.js.map → chunk-2RPHDVHW.js.map} +0 -0
  227. /package/dist/{chunk-F5RX62T7.js.map → chunk-7QRUZAUG.js.map} +0 -0
  228. /package/dist/{chunk-BCHWFTV4.js.map → chunk-F4DSMVZ7.js.map} +0 -0
  229. /package/dist/{chunk-2F5QH3D4.js.map → chunk-HU6DZZBG.js.map} +0 -0
  230. /package/dist/{chunk-SCVBYSF7.js.map → chunk-IRUYJD23.js.map} +0 -0
  231. /package/dist/{chunk-WFXWJITA.js.map → chunk-JLMD3IGK.js.map} +0 -0
  232. /package/dist/{chunk-FAHIMJRU.js.map → chunk-L7ESV37V.js.map} +0 -0
  233. /package/dist/{chunk-JNM3TPLX.js.map → chunk-LETB5HCK.js.map} +0 -0
  234. /package/dist/{chunk-SDPIT4HW.js.map → chunk-Q5HR4ADS.js.map} +0 -0
  235. /package/dist/{chunk-MDNX7HTN.js.map → chunk-YEJCNOET.js.map} +0 -0
  236. /package/dist/{chunk-N6HH7K6P.js.map → chunk-ZY25RG4Y.js.map} +0 -0
  237. /package/dist/{claude-code-W74MNTAC.js.map → claude-code-NMRKTAP7.js.map} +0 -0
  238. /package/dist/{codebuff-3PMZJJHP.js.map → codebuff-ETYT5UBL.js.map} +0 -0
  239. /package/dist/{codex-Q3ATRRX3.js.map → codex-YAORPCOD.js.map} +0 -0
  240. /package/dist/{copilot-cli-SJGIXVSD.js.map → copilot-cli-MZTAWMPW.js.map} +0 -0
  241. /package/dist/{crush-LN5QFFR2.js.map → crush-QBXLNN7T.js.map} +0 -0
  242. /package/dist/{cursor-QZ6MTO74.js.map → cursor-DIW43TRZ.js.map} +0 -0
  243. /package/dist/{detect-2NIXILMZ.js.map → detect-L5OZPVFO.js.map} +0 -0
  244. /package/dist/{droid-W5WF5XEX.js.map → droid-U3ZBLQFO.js.map} +0 -0
  245. /package/dist/{gemini-cli-CIRW37TU.js.map → gemini-cli-NMVVBO3K.js.map} +0 -0
  246. /package/dist/{goose-A3M5GODH.js.map → goose-64V46Y2W.js.map} +0 -0
  247. /package/dist/{hermes-ZYLMOFLZ.js.map → hermes-F3EGTK6N.js.map} +0 -0
  248. /package/dist/{hook-FDGIQPRC.js.map → hook-JRDQ56BN.js.map} +0 -0
  249. /package/dist/{kilo-NSWAVP6P.js.map → kilo-SW7BH6EG.js.map} +0 -0
  250. /package/dist/{kilo-cli-EVBKUODA.js.map → kilo-cli-ZF272ZHN.js.map} +0 -0
  251. /package/dist/{kiro-UCLSLBW2.js.map → kiro-WGOI5CGT.js.map} +0 -0
  252. /package/dist/{leaderboard-MXGENYXN.js.map → leaderboard-ASGR3E2U.js.map} +0 -0
  253. /package/dist/{mux-ZMLVAXOO.js.map → mux-XM6AP35L.js.map} +0 -0
  254. /package/dist/{nemoclaw-LXUTMR56.js.map → nemoclaw-QDB6O22A.js.map} +0 -0
  255. /package/dist/{openclaw-XWJLEW35.js.map → openclaw-3UMBSSZM.js.map} +0 -0
  256. /package/dist/{openclaw-IYA7ASL6.js.map → openclaw-5EQFGOWL.js.map} +0 -0
  257. /package/dist/{opencode-HWT3RSMN.js.map → opencode-QGP4ALQY.js.map} +0 -0
  258. /package/dist/{package-IA56LSC3.js.map → package-IXBSG7HD.js.map} +0 -0
  259. /package/dist/{pi-UFX2OYFV.js.map → pi-GGDQREVG.js.map} +0 -0
  260. /package/dist/{pi-YGBXYWY5.js.map → pi-GW25LPC3.js.map} +0 -0
  261. /package/dist/{qwen-code-W7NUCDEN.js.map → qwen-code-GQILBJ5B.js.map} +0 -0
  262. /package/dist/{roo-code-ZLKH4A7N.js.map → roo-code-SUWI4BBN.js.map} +0 -0
  263. /package/dist/{serve-RNUCK5F7.js.map → serve-CFBQYKRB.js.map} +0 -0
  264. /package/dist/{statusline-ZVFI5DRT.js.map → statusline-WKLWSM7I.js.map} +0 -0
  265. /package/dist/{synthetic-UKR6SMGS.js.map → synthetic-6FRA7P5Q.js.map} +0 -0
  266. /package/dist/{telemetry-3FN6HDVU.js.map → telemetry-64GCGNIW.js.map} +0 -0
  267. /package/dist/{trae-PA26DPBW.js.map → trae-CPPYASR2.js.map} +0 -0
  268. /package/dist/{usage-G72SF7JG.js.map → usage-OV2BDZKF.js.map} +0 -0
  269. /package/dist/{usage-event-DHSEBO5T.js.map → usage-event-KPI3NEX3.js.map} +0 -0
  270. /package/dist/{warp-JNQA7PBU.js.map → warp-NRBBJQR2.js.map} +0 -0
  271. /package/dist/{zed-NNNX5MNT.js.map → zed-XJFOOKCO.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  ADAPTER_REGISTRY
4
- } from "./chunk-2F5QH3D4.js";
4
+ } from "./chunk-HU6DZZBG.js";
5
5
 
6
6
  // src/adapters/detect.ts
7
7
  async function detectInstalledPlatforms(projectDir) {
@@ -80,4 +80,4 @@ export {
80
80
  detectInstalledPlatforms,
81
81
  detectRuntimeHost
82
82
  };
83
- //# sourceMappingURL=chunk-SDPIT4HW.js.map
83
+ //# sourceMappingURL=chunk-Q5HR4ADS.js.map
@@ -5,12 +5,13 @@ import { createHash } from "crypto";
5
5
  import {
6
6
  chmodSync,
7
7
  existsSync,
8
+ lstatSync,
8
9
  mkdirSync,
9
10
  readFileSync,
10
11
  writeFileSync
11
12
  } from "fs";
12
13
  import { homedir } from "os";
13
- import { basename, join, resolve } from "path";
14
+ import { basename, join, parse, relative, resolve, sep } from "path";
14
15
  function dataRoot() {
15
16
  const override = process.env.AGENT_CONNECTOR_DATA_DIR;
16
17
  if (override && override.trim() !== "") return resolve(override);
@@ -35,6 +36,25 @@ function homeBinPath() {
35
36
  function ensureDir(dir) {
36
37
  if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
37
38
  }
39
+ function firstSymlinkInPath(path) {
40
+ const abs = resolve(path);
41
+ const root = parse(abs).root;
42
+ const rest = relative(root, abs);
43
+ if (rest === "") return null;
44
+ let cur = root;
45
+ for (const part of rest.split(sep)) {
46
+ if (part === "") continue;
47
+ cur = join(cur, part);
48
+ try {
49
+ if (lstatSync(cur).isSymbolicLink()) return cur;
50
+ } catch (err) {
51
+ const code = err.code;
52
+ if (code === "ENOENT") return null;
53
+ throw err;
54
+ }
55
+ }
56
+ return null;
57
+ }
38
58
  function ensureHomeBin(cliEntry, nodePath = process.execPath) {
39
59
  const binPath = homeBinPath();
40
60
  ensureDir(join(dataRoot(), "bin"));
@@ -87,7 +107,8 @@ export {
87
107
  telemetryPath,
88
108
  homeBinPath,
89
109
  ensureDir,
110
+ firstSymlinkInPath,
90
111
  ensureHomeBin,
91
112
  projectIdentity
92
113
  };
93
- //# sourceMappingURL=chunk-TRQKHP7D.js.map
114
+ //# sourceMappingURL=chunk-QY42WGBX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/paths.ts"],"sourcesContent":["/**\n * core/paths — home data-root, stable home binary, and project identity.\n *\n * Operating model (docs/ARCHITECTURE.md §3):\n * • One home data-root holds the single binary + shared telemetry + state.\n * Override with AGENT_CONNECTOR_DATA_DIR (the cross-agent shared-DB key).\n * This relocates FRAMEWORK state only — never platform-native config files.\n * • The home binary lives at a STABLE path so every host's pointer config\n * keeps working across updates (no versioned cache dir → no cache-heal bug).\n * • Per-project data is keyed by a stable project identity (git remote ||\n * normalized absolute path), hashed — not by code location.\n */\n\nimport { createHash } from \"node:crypto\";\nimport {\n chmodSync,\n existsSync,\n lstatSync,\n mkdirSync,\n readFileSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, join, parse, relative, resolve, sep } from \"node:path\";\n\n/** Framework data-root: AGENT_CONNECTOR_DATA_DIR || ~/.agent-connector. */\nexport function dataRoot(): string {\n const override = process.env.AGENT_CONNECTOR_DATA_DIR;\n if (override && override.trim() !== \"\") return resolve(override);\n return join(homedir(), \".agent-connector\");\n}\n\nexport function connectorsDir(): string {\n return join(dataRoot(), \"connectors\");\n}\nexport function connectorDir(id: string): string {\n return join(connectorsDir(), id);\n}\nexport function backupsDir(): string {\n return join(dataRoot(), \"backups\");\n}\nexport function logsDir(): string {\n return join(dataRoot(), \"logs\");\n}\n\n/** Telemetry store path for the selected backend. */\nexport function telemetryPath(store: \"ndjson\" | \"sqlite\" = \"ndjson\"): string {\n return join(dataRoot(), store === \"sqlite\" ? \"telemetry.db\" : \"telemetry.ndjson\");\n}\n\n/** Stable, OS-correct path to the single home binary pointer. */\nexport function homeBinPath(): string {\n const name = process.platform === \"win32\" ? \"agent-connector.cmd\" : \"agent-connector\";\n return join(dataRoot(), \"bin\", name);\n}\n\nexport function ensureDir(dir: string): void {\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n}\n\n/**\n * Return the first existing symbolic-link component in `path`, or null when the\n * existing prefix is symlink-free. Stops at the first missing component so new\n * directories/files can still be created normally.\n */\nexport function firstSymlinkInPath(path: string): string | null {\n const abs = resolve(path);\n const root = parse(abs).root;\n const rest = relative(root, abs);\n if (rest === \"\") return null;\n\n let cur = root;\n for (const part of rest.split(sep)) {\n if (part === \"\") continue;\n cur = join(cur, part);\n try {\n if (lstatSync(cur).isSymbolicLink()) return cur;\n } catch (err) {\n const code = (err as NodeJS.ErrnoException).code;\n if (code === \"ENOENT\") return null;\n throw err;\n }\n }\n return null;\n}\n\n/**\n * Write a stable launcher at homeBinPath() that execs the real CLI entry.\n * Avoids symlinks (Windows constraint) and versioned paths. Idempotent.\n *\n * @param cliEntry absolute path to the installed cli.js\n * @param nodePath node runtime to exec with (defaults to current process.execPath)\n * @returns the stable launcher path\n */\nexport function ensureHomeBin(cliEntry: string, nodePath: string = process.execPath): string {\n const binPath = homeBinPath();\n ensureDir(join(dataRoot(), \"bin\"));\n const node = nodePath.replace(/\\\\/g, \"/\");\n const cli = cliEntry.replace(/\\\\/g, \"/\");\n if (process.platform === \"win32\") {\n writeFileSync(binPath, `@echo off\\r\\n\"${node}\" \"${cli}\" %*\\r\\n`, \"utf8\");\n } else {\n writeFileSync(binPath, `#!/bin/sh\\nexec \"${node}\" \"${cli}\" \"$@\"\\n`, \"utf8\");\n chmodSync(binPath, 0o755);\n }\n return binPath;\n}\n\n/** Read remote.origin.url from a project's .git/config without spawning git. */\nfunction gitRemoteUrl(projectDir: string): string | null {\n const cfg = join(projectDir, \".git\", \"config\");\n if (!existsSync(cfg)) return null;\n try {\n const text = readFileSync(cfg, \"utf8\");\n // Find [remote \"origin\"] ... url = X\n const lines = text.split(/\\r?\\n/);\n let inOrigin = false;\n for (const line of lines) {\n const s = line.trim();\n if (s.startsWith(\"[\")) inOrigin = /^\\[remote\\s+\"origin\"\\]$/.test(s);\n else if (inOrigin) {\n const m = s.match(/^url\\s*=\\s*(.+)$/);\n if (m && m[1]) return m[1].trim();\n }\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n\nexport interface ProjectIdentity {\n /** Hashed stable key used to partition telemetry/state. */\n key: string;\n /** Human-readable label (git remote or directory name). */\n label: string;\n /** Absolute project directory. */\n dir: string;\n}\n\n/**\n * Derive a stable project identity. Prefers the git origin URL (stable across\n * clones/locations); falls back to the normalized absolute path.\n */\nexport function projectIdentity(projectDir: string): ProjectIdentity {\n const dir = resolve(projectDir);\n const remote = gitRemoteUrl(dir);\n const basis = remote ?? dir;\n const key = createHash(\"sha256\").update(basis).digest(\"hex\").slice(0, 16);\n return { key, label: remote ?? basename(dir), dir };\n}\n"],"mappings":"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","names":[]}
@@ -79,6 +79,19 @@ function buildServeWrapperCommand(homeBinPath, connectorId, realCommand, realArg
79
79
  args: [...flags, "--", realCommand, ...realArgs]
80
80
  };
81
81
  }
82
+ function buildWrappedStdio(ctx, server, platformId, command, args) {
83
+ if (!shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
84
+ return { command, args };
85
+ }
86
+ return buildServeWrapperCommand(
87
+ ctx.homeBinPath,
88
+ ctx.connector.id,
89
+ command,
90
+ args,
91
+ ctx.scope,
92
+ platformId
93
+ );
94
+ }
82
95
  function resolveSpawnCommand(command, deps = {}) {
83
96
  const platform = deps.platform ?? process.platform;
84
97
  if (platform !== "win32") return { file: command, needsShell: false };
@@ -135,7 +148,8 @@ export {
135
148
  isHostNativeUsageEnabled,
136
149
  shouldWrapForTelemetry,
137
150
  buildServeWrapperCommand,
151
+ buildWrappedStdio,
138
152
  resolveSpawnCommand,
139
153
  detectLaunchMethod
140
154
  };
141
- //# sourceMappingURL=chunk-I5MLE6S7.js.map
155
+ //# sourceMappingURL=chunk-TO57WYBB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/spawn.ts"],"sourcesContent":["/**\n * core/spawn — cross-platform command construction.\n *\n * Borrowed from context-mode (issues #369/#372/#548/#738): bare `node` is\n * unreliable on Windows Git Bash (MSYS) and MSYS rewrites absolute paths on\n * non-C: drives. Always use the resolved runtime path, forward slashes, and\n * double-quoting. No-ops on macOS/Linux.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport type { InstallScope, PlatformId, ServerDef } from \"./types.js\";\nimport type { InstallContext } from \"../adapters/spi.js\";\nimport type {\n LaunchMethod,\n TelemetryInstallScope,\n} from \"../telemetry/types.js\";\n\n/**\n * Narrow the framework's 5-value {@link InstallScope} down to the two telemetry\n * slicing buckets: only a `project`-local install is `project`; everything else\n * (system/user/profile/managed) is global and reads as `user`.\n */\nexport function narrowInstallScope(scope: InstallScope): TelemetryInstallScope {\n return scope === \"project\" ? \"project\" : \"user\";\n}\n\n/** Build `\"<nodePath>\" \"<scriptPath>\"`. */\nexport function buildNodeCommand(\n scriptPath: string,\n opts?: { nodePath?: string },\n): string {\n const nodePath = (opts?.nodePath ?? process.execPath).replace(/\\\\/g, \"/\");\n const safe = scriptPath.replace(/\\\\/g, \"/\");\n return `\"${nodePath}\" \"${safe}\"`;\n}\n\n/**\n * Strict inverse of buildNodeCommand. Returns the two quoted tokens, or null if\n * `cmd` was not produced by buildNodeCommand (no fragile last-whitespace tail\n * grabbing — that was the #548 doubled-path bug when paths contained spaces).\n */\nexport function parseNodeCommand(\n cmd: string,\n): { nodePath: string; scriptPath: string } | null {\n if (typeof cmd !== \"string\" || cmd.length === 0) return null;\n const m = cmd.match(/^\"([^\"]+)\"\\s+\"([^\"]+)\"\\s*$/);\n if (!m || !m[1] || !m[2]) return null;\n return { nodePath: m[1], scriptPath: m[2] };\n}\n\n/** Quote a single argument for inclusion in a host hook command string. */\nexport function quoteArg(arg: string): string {\n return `\"${arg.replace(/\\\\/g, \"/\")}\"`;\n}\n\n/**\n * True when `hay` (slash-normalized) has the quoted home-bin path IMMEDIATELY\n * followed by `verb` — i.e. the verb sits in its command SLOT (right after the\n * home binary), not merely somewhere in the argument list. This distinguishes\n * `\"<bin>\" statusline …` from `\"<bin>\" action … statusline …`: the action verb\n * takes a free-form `actionId` positional that can legitimately equal another\n * verb's name (`statusline` / `usage-event` / `hook`), and only the SLOT\n * position identifies the real verb. `homeBinNorm` is the slash-normalized\n * home-bin path the caller already derived.\n */\nfunction hasVerbSlot(hay: string, homeBinNorm: string, verb: string): boolean {\n return hay.includes(`\"${homeBinNorm}\" ${verb} `);\n}\n\n/**\n * Build the universal hook command a host config points at:\n * \"<homeBin>\" hook <platformId> <event> --connector <id>\n * Pointing every host at the one stable home binary is how a single update\n * propagates everywhere (docs/ARCHITECTURE.md §3 R1).\n */\nexport function buildHomeBinHookCommand(\n homeBinPath: string,\n platformId: string,\n event: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} hook ${platformId} ${event} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is a home-bin hook command for exactly `connectorId`.\n *\n * Critical: the connector id is the LAST token of the hook command\n * (`... --connector <id>`), so a naive `command.includes(\"--connector \" + id)`\n * collides on shared-prefix ids — `--connector acme-db` contains\n * `--connector acme`, which would let uninstalling `acme` strip `acme-db`'s\n * hooks. We anchor the id token: the character after it must be end-of-string,\n * whitespace, or a closing double-quote (the JSON-embedded case). Connector ids\n * are kebab-case (ID_RE) so they never contain whitespace or quotes themselves.\n */\nexport function isHomeBinHookCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // The stored command was forward-slashed by quoteArg(); homeBinPath() yields\n // NATIVE (back)slashes on Windows (node:path join). Normalize BOTH sides so the\n // ownership substring test holds on win32 (without this, detection always\n // returns false there → duplicate hooks on re-install + orphans on uninstall).\n // No-op on POSIX.\n const hay = command.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinPath.replace(/\\\\/g, \"/\"))) return false;\n const token = `--connector ${connectorId}`;\n let from = 0;\n for (;;) {\n const idx = hay.indexOf(token, from);\n if (idx < 0) return false;\n const after = hay.charAt(idx + token.length);\n if (after === \"\" || after === '\"' || /\\s/.test(after)) return true;\n from = idx + token.length;\n }\n}\n\n/**\n * Build the OPT-IN host-native usage-event command an AfterModel / PostInvocation\n * hook points at:\n * \"<homeBin>\" usage-event <platformId> --connector <id>\n * Mirrors {@link buildHomeBinHookCommand} (same anchoring rules apply) but routes\n * to the hidden `usage-event` entrypoint, which records a DISTINCT `model_turn`\n * row instead of dispatching a connector handler.\n */\nexport function buildUsageEventCommand(\n homeBinPath: string,\n platformId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} usage-event ${platformId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR host-native usage-event command for exactly\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\n * shared-prefix id can't collide; additionally requires the ` usage-event ` verb\n * so it is never confused with a plain `hook` command during uninstall.\n */\nexport function isUsageEventCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"usage-event\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Build the home-bin statusline command a host's status line config points at:\n * \"<homeBin>\" statusline <platformId> --connector <id>\n * Mirrors {@link buildHomeBinHookCommand} / {@link buildUsageEventCommand} (the\n * same single-home-binary indirection) but routes to the `statusline`\n * entrypoint, which renders the connector's HUD line for the host.\n */\nexport function buildHomeBinStatuslineCommand(\n homeBinPath: string,\n platformId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} statusline ${platformId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR home-bin statusline command for exactly\n * `connectorId`. Same end-of-token anchoring as {@link isHomeBinHookCommand} so a\n * shared-prefix id can't collide; additionally requires the ` statusline ` verb\n * so it is never confused with a plain `hook` / `usage-event` command.\n */\nexport function isHomeBinStatuslineCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"statusline\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Build the home-bin action command a future host affordance (slash command /\n * keybinding) points at:\n * \"<homeBin>\" action <platformId> <actionId> --connector <id>\n * Mirrors {@link buildHomeBinStatuslineCommand} (the same single-home-binary\n * indirection) but routes to the `action` entrypoint, which re-imports the\n * connector and runs the named action's run(ctx). v1 ships only this command\n * builder + the runtime verb; no adapter EMITS the affordance yet.\n */\nexport function buildHomeBinActionCommand(\n homeBinPath: string,\n platformId: string,\n actionId: string,\n connectorId: string,\n): string {\n return `${quoteArg(homeBinPath)} action ${platformId} ${actionId} --connector ${connectorId}`;\n}\n\n/**\n * True when `command` is OUR home-bin action command for exactly `connectorId`.\n * Same end-of-token anchoring as {@link isHomeBinHookCommand} so a shared-prefix\n * id can't collide; additionally requires the ` action ` verb so it is never\n * confused with a plain `hook` / `usage-event` / `statusline` command.\n */\nexport function isHomeBinActionCommand(\n command: string | undefined,\n homeBinPath: string,\n connectorId: string,\n): boolean {\n if (!command) return false;\n // Normalize separators like isHomeBinHookCommand (win32 ownership detection).\n const hay = command.replace(/\\\\/g, \"/\");\n const homeBinNorm = homeBinPath.replace(/\\\\/g, \"/\");\n if (!hay.includes(homeBinNorm)) return false;\n if (!hasVerbSlot(hay, homeBinNorm, \"action\")) return false;\n return isHomeBinHookCommand(command, homeBinPath, connectorId);\n}\n\n/**\n * Single source of truth for \"is OPT-IN host-native turn-usage capture enabled\n * for this connector?\" — read by the Gemini / Antigravity adapters at install\n * time to decide whether to ALSO write the AfterModel / PostInvocation usage hook.\n * Enabled when the connector opts in via telemetry.hostNativeUsage OR when the\n * install-time env switch AGENT_CONNECTOR_HOST_NATIVE=1 forces it on. Off by\n * default (privacy: host-native capture is never installed silently).\n */\nexport function isHostNativeUsageEnabled(\n telemetry: { enabled: boolean; hostNativeUsage?: boolean },\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n if (telemetry.enabled !== true) return false;\n if (env.AGENT_CONNECTOR_HOST_NATIVE === \"1\") return true;\n return telemetry.hostNativeUsage === true;\n}\n\n/**\n * Single source of truth for \"should this server be wrapped by `serve` for\n * telemetry?\" — so every adapter behaves identically even for a server that\n * skipped normalizeServer (e.g. a per-platform override). On by default for an\n * stdio server with a command, unless explicitly disabled or telemetry is off.\n */\nexport function shouldWrapForTelemetry(\n server: ServerDef,\n telemetry: { enabled: boolean },\n): boolean {\n return (\n server.wrapForTelemetry !== false &&\n telemetry.enabled === true &&\n server.transport === \"stdio\" &&\n typeof server.command === \"string\" &&\n server.command !== \"\"\n );\n}\n\n/**\n * Build the telemetry-wrapping server command:\n * \"<homeBin>\" serve --connector <id> --scope <scope> --host <platformId> -- <realCommand> <realArgs...>\n * Used when a stdio server opts into transparent telemetry capture.\n *\n * `scope` records the install dimension (global user vs project-local) on every\n * telemetry row so usage can be sliced by it later. It is OPTIONAL for backward\n * compatibility: when omitted, the `--scope` flag is not emitted and the runtime\n * treats the scope as \"unknown\".\n *\n * `platformId` bakes the install TARGET platform into the wrapper so the proxy\n * stamps `hostPlatform` correctly even under a headless spawn where runtime env\n * markers are absent (detectRuntimeHost only knows claude-code/cursor/codex and\n * otherwise mis-attributes). Emitted as `--host <platformId>` in the FLAG\n * section (before `--`). It is OPTIONAL + backward-compatible: when omitted the\n * `--host` flag is not emitted and the runtime falls back to env detection.\n */\nexport function buildServeWrapperCommand(\n homeBinPath: string,\n connectorId: string,\n realCommand: string,\n realArgs: string[],\n scope?: InstallScope,\n platformId?: PlatformId,\n): { command: string; args: string[] } {\n const flags = [\"serve\", \"--connector\", connectorId];\n if (scope !== undefined) flags.push(\"--scope\", narrowInstallScope(scope));\n if (platformId !== undefined) flags.push(\"--host\", platformId);\n return {\n command: homeBinPath,\n args: [...flags, \"--\", realCommand, ...realArgs],\n };\n}\n\n/**\n * Telemetry serve-wrap for a stdio command: when the connector opts in, route\n * `command`/`args` through `<homeBin> serve --connector <id> -- …`; otherwise\n * return them unchanged. Consolidates the per-host wrap snippet — the caller\n * keeps its own command/args seeding + downstream env-resolution + entry shaping.\n */\nexport function buildWrappedStdio(\n ctx: Pick<InstallContext, \"homeBinPath\" | \"connector\" | \"scope\">,\n server: ServerDef,\n platformId: PlatformId,\n command: string,\n args: string[],\n): { command: string; args: string[] } {\n if (!shouldWrapForTelemetry(server, ctx.connector.telemetry)) {\n return { command, args };\n }\n return buildServeWrapperCommand(\n ctx.homeBinPath,\n ctx.connector.id,\n command,\n args,\n ctx.scope,\n platformId,\n );\n}\n\n/** Injectable deps for {@link resolveSpawnCommand} (so the win32 branch is unit-testable on POSIX). */\nexport interface SpawnResolveDeps {\n platform?: NodeJS.Platform;\n /** PATH value (`;`-separated on Windows). */\n pathEnv?: string;\n /** PATHEXT value (`;`-separated). */\n pathExt?: string;\n /** File-existence probe (defaults to fs.existsSync). */\n exists?: (p: string) => boolean;\n}\n\n/** How a child command should be handed to spawn() on this platform. */\nexport interface SpawnResolution {\n /** The command to pass to spawn() (an absolute path on win32 when resolved). */\n file: string;\n /**\n * Whether spawn() MUST use `shell: true`. On native Windows a `.cmd`/`.bat`\n * shim (npx.cmd, pnpm.cmd, the agent-connector.cmd launcher) cannot be run by\n * raw CreateProcess — Node throws EINVAL since the 2024 security fix unless a\n * shell is used. `.exe` resolves directly with no shell.\n */\n needsShell: boolean;\n}\n\n/**\n * Resolve a child command for spawn() across platforms. NO-OP on macOS/Linux\n * (returns the command unchanged, no shell). On native Windows it fixes the two\n * spawn failure modes for bare package runners:\n * 1. raw CreateProcess ignores PATHEXT, so spawn(\"npx\") → ENOENT even though\n * `npx.cmd` is on PATH. We search PATH × PATHEXT and return the resolved\n * absolute path.\n * 2. a resolved `.cmd`/`.bat` still cannot be launched without a shell, so we\n * flag `needsShell` for those (and `.exe`/`.com` run directly).\n * A bare name that PATH search misses falls back to `{ file: command,\n * needsShell: true }` so cmd.exe's own PATHEXT lookup still finds it.\n */\nexport function resolveSpawnCommand(\n command: string,\n deps: SpawnResolveDeps = {},\n): SpawnResolution {\n const platform = deps.platform ?? process.platform;\n if (platform !== \"win32\") return { file: command, needsShell: false };\n\n const isBatch = (s: string): boolean => /\\.(cmd|bat)$/i.test(s);\n\n // Already a path or already has an extension → don't search; only decide shell.\n if (/[\\\\/]/.test(command) || /\\.[a-z0-9]+$/i.test(command)) {\n return { file: command, needsShell: isBatch(command) };\n }\n\n const exists = deps.exists ?? existsSync;\n const pathEnv = deps.pathEnv ?? process.env.PATH ?? process.env.Path ?? \"\";\n const pathExt = deps.pathExt ?? process.env.PATHEXT ?? \".COM;.EXE;.BAT;.CMD\";\n const dirs = pathEnv.split(\";\").filter((d) => d !== \"\");\n const exts = pathExt.split(\";\").filter((e) => e !== \"\");\n for (const dir of dirs) {\n for (const ext of exts) {\n const candidate = join(dir, command + ext);\n if (exists(candidate)) return { file: candidate, needsShell: isBatch(ext) };\n }\n }\n // Not found on PATH — let cmd.exe resolve it (handles shim dirs we may miss).\n return { file: command, needsShell: true };\n}\n\n/** Basenames (case-insensitive, sans common extensions) of the ephemeral package runners. */\nconst PACKAGE_RUNNERS: Record<string, Extract<LaunchMethod, \"npx\" | \"bunx\" | \"uvx\">> = {\n npx: \"npx\",\n bunx: \"bunx\",\n uvx: \"uvx\",\n};\n\n/** Basenames of language interpreters that launch a local script. */\nconst INTERPRETERS: ReadonlySet<string> = new Set([\"node\", \"bun\", \"deno\"]);\n\n/**\n * Strip a directory prefix and a trailing executable extension to get the bare\n * program name. Tolerates both POSIX and Windows separators (the wrapped command\n * may be an absolute Windows path) and lowercases for case-insensitive matching.\n */\nfunction commandBasename(realCommand: string): string {\n const noDir = realCommand.replace(/\\\\/g, \"/\").split(\"/\").pop() ?? realCommand;\n return noDir.replace(/\\.(exe|cmd|bat|com)$/i, \"\").toLowerCase();\n}\n\n/**\n * Classify how the real MCP server is launched, for the \"launch-method\" slicing\n * dimension. Package runners (npx/bunx/uvx) and interpreters (node/bun/deno) are\n * detected by the command basename. A remote (http) server is not launched\n * locally, so the caller — which alone knows the transport — passes\n * `isRemote: true` to force \"http\". Anything else resolves to \"binary\".\n */\nexport function detectLaunchMethod(\n realCommand: string,\n realArgs: string[],\n opts?: { isRemote?: boolean },\n): LaunchMethod {\n void realArgs; // reserved: args may later refine node-vs-script heuristics\n if (opts?.isRemote === true) return \"http\";\n if (typeof realCommand !== \"string\" || realCommand.trim() === \"\") {\n return \"unknown\";\n }\n const base = commandBasename(realCommand);\n if (base === \"\") return \"unknown\";\n const runner = PACKAGE_RUNNERS[base];\n if (runner !== undefined) return runner;\n if (INTERPRETERS.has(base)) return \"node\";\n return \"binary\";\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/host-paths.ts
4
+ import { homedir } from "os";
5
+ import { join, resolve } from "path";
6
+ function xdgConfigHome() {
7
+ const xdg = process.env.XDG_CONFIG_HOME;
8
+ return xdg && xdg.trim() !== "" ? resolve(xdg) : join(homedir(), ".config");
9
+ }
10
+ function roamingAppData() {
11
+ const appData = process.env.APPDATA;
12
+ return appData && appData.trim() !== "" ? resolve(appData) : join(homedir(), "AppData", "Roaming");
13
+ }
14
+ function localAppData() {
15
+ const local = process.env.LOCALAPPDATA;
16
+ return local && local.trim() !== "" ? resolve(local) : join(homedir(), "AppData", "Local");
17
+ }
18
+ function codexConfigHome() {
19
+ const env = process.env.CODEX_HOME;
20
+ if (env && env.trim() !== "") {
21
+ if (env.startsWith("~")) return join(homedir(), env.replace(/^~[/\\]?/, ""));
22
+ return resolve(env);
23
+ }
24
+ return join(homedir(), ".codex");
25
+ }
26
+
27
+ export {
28
+ xdgConfigHome,
29
+ roamingAppData,
30
+ localAppData,
31
+ codexConfigHome
32
+ };
33
+ //# sourceMappingURL=chunk-UM5S7DKK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/host-paths.ts"],"sourcesContent":["// ─────────────────────────────────────────────────────────────────────────\n// host-paths.ts — shared OS user-config-dir base resolvers\n//\n// Several adapters resolve the SAME per-OS \"user config base\" directory with\n// the same logic (XDG on posix; %APPDATA%/%LOCALAPPDATA% on Windows, each with\n// a ~/AppData fallback). These helpers consolidate that resolution so the\n// per-host adapters only carry their host-specific SUFFIX. The result is\n// byte-identical for absolute/clean config-dir inputs (the realistic case);\n// a non-canonical env value (relative, trailing slash, `..`) is normalized via\n// `resolve()` rather than passed through bare — a safe canonicalization.\n//\n// Scope note: these are the USER-CONFIG-DIR bases (where a host keeps its\n// settings/config files). The agent-connector *data-root* paths (our own\n// per-project state) live in core/paths.ts — do NOT conflate the two.\n//\n// Host-specific config-home resolvers that are SHARED across modules (e.g.\n// `codexConfigHome`, used by BOTH the codex adapter and marketplace detection)\n// DO live here, so the writer and the probe can never disagree on the dir.\n// Single-caller host envs (PI_CODING_AGENT_DIR, OPENCLAW_*) stay in their own\n// adapter.\n// ─────────────────────────────────────────────────────────────────────────\n\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\n\n/** $XDG_CONFIG_HOME when set & non-empty, else ~/.config. */\nexport function xdgConfigHome(): string {\n const xdg = process.env.XDG_CONFIG_HOME;\n return xdg && xdg.trim() !== \"\" ? resolve(xdg) : join(homedir(), \".config\");\n}\n\n/** %APPDATA% (Roaming) when set & non-empty, else ~/AppData/Roaming. */\nexport function roamingAppData(): string {\n const appData = process.env.APPDATA;\n return appData && appData.trim() !== \"\"\n ? resolve(appData)\n : join(homedir(), \"AppData\", \"Roaming\");\n}\n\n/** %LOCALAPPDATA% when set & non-empty, else ~/AppData/Local. */\nexport function localAppData(): string {\n const local = process.env.LOCALAPPDATA;\n return local && local.trim() !== \"\"\n ? resolve(local)\n : join(homedir(), \"AppData\", \"Local\");\n}\n\n/** Codex's config home: $CODEX_HOME (tilde-expanded, then resolved) when set\n * & non-empty, else ~/.codex. Shared by the codex adapter (writer) and the\n * marketplace detection probe so they never disagree on the config dir. */\nexport function codexConfigHome(): string {\n const env = process.env.CODEX_HOME;\n if (env && env.trim() !== \"\") {\n if (env.startsWith(\"~\")) return join(homedir(), env.replace(/^~[/\\\\]?/, \"\"));\n return resolve(env);\n }\n return join(homedir(), \".codex\");\n}\n"],"mappings":";;;AAsBA,SAAS,eAAe;AACxB,SAAS,MAAM,eAAe;AAGvB,SAAS,gBAAwB;AACtC,QAAM,MAAM,QAAQ,IAAI;AACxB,SAAO,OAAO,IAAI,KAAK,MAAM,KAAK,QAAQ,GAAG,IAAI,KAAK,QAAQ,GAAG,SAAS;AAC5E;AAGO,SAAS,iBAAyB;AACvC,QAAM,UAAU,QAAQ,IAAI;AAC5B,SAAO,WAAW,QAAQ,KAAK,MAAM,KACjC,QAAQ,OAAO,IACf,KAAK,QAAQ,GAAG,WAAW,SAAS;AAC1C;AAGO,SAAS,eAAuB;AACrC,QAAM,QAAQ,QAAQ,IAAI;AAC1B,SAAO,SAAS,MAAM,KAAK,MAAM,KAC7B,QAAQ,KAAK,IACb,KAAK,QAAQ,GAAG,WAAW,OAAO;AACxC;AAKO,SAAS,kBAA0B;AACxC,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,OAAO,IAAI,KAAK,MAAM,IAAI;AAC5B,QAAI,IAAI,WAAW,GAAG,EAAG,QAAO,KAAK,QAAQ,GAAG,IAAI,QAAQ,YAAY,EAAE,CAAC;AAC3E,WAAO,QAAQ,GAAG;AAAA,EACpB;AACA,SAAO,KAAK,QAAQ,GAAG,QAAQ;AACjC;","names":[]}
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REGISTERED_PLATFORM_IDS
4
- } from "./chunk-2F5QH3D4.js";
4
+ } from "./chunk-HU6DZZBG.js";
5
5
  import {
6
6
  CONFIG_PATCH_SEGMENT_RE,
7
7
  configPatchNamespaceViolation,
8
8
  isJsonValue,
9
9
  isValidConfigPatchKey
10
- } from "./chunk-FAHIMJRU.js";
10
+ } from "./chunk-L7ESV37V.js";
11
11
  import {
12
12
  MANAGED_BLOCK_BEGIN_TOKEN,
13
13
  MANAGED_BLOCK_END_TOKEN,
14
14
  MEMORY_CONTENT_HARD_CAP_BYTES
15
- } from "./chunk-N6HH7K6P.js";
15
+ } from "./chunk-ZY25RG4Y.js";
16
16
 
17
17
  // src/core/define-connector.ts
18
18
  import { isAbsolute, normalize } from "path";
@@ -495,4 +495,4 @@ export {
495
495
  defineConfigPatch,
496
496
  defineNativeHook
497
497
  };
498
- //# sourceMappingURL=chunk-MDNX7HTN.js.map
498
+ //# sourceMappingURL=chunk-YEJCNOET.js.map
@@ -5,21 +5,21 @@ import {
5
5
  newRecordId,
6
6
  openStore,
7
7
  worstConfidence
8
- } from "./chunk-BCHWFTV4.js";
8
+ } from "./chunk-F4DSMVZ7.js";
9
9
  import {
10
10
  log
11
11
  } from "./chunk-KHO5WNTP.js";
12
12
  import {
13
13
  loadRegisteredConnector,
14
14
  readRegisteredMeta
15
- } from "./chunk-YQLQJZ7S.js";
15
+ } from "./chunk-OLI5SD6I.js";
16
16
  import {
17
17
  REGISTERED_PLATFORM_IDS,
18
18
  loadAdapter
19
- } from "./chunk-2F5QH3D4.js";
19
+ } from "./chunk-HU6DZZBG.js";
20
20
  import {
21
21
  projectIdentity
22
- } from "./chunk-TRQKHP7D.js";
22
+ } from "./chunk-QY42WGBX.js";
23
23
 
24
24
  // src/runtime/telemetry-accessor.ts
25
25
  var ZERO = {
@@ -28,34 +28,56 @@ var ZERO = {
28
28
  totalTokens: 0,
29
29
  calls: 0
30
30
  };
31
- function buildTelemetryAccessor(connectorId) {
32
- return async () => {
33
- if (process.env.AGENT_CONNECTOR_TELEMETRY === "0") return { ...ZERO };
31
+ function readTelemetryUsageSummary(connectorId) {
32
+ if (process.env.AGENT_CONNECTOR_TELEMETRY === "0") return { ...ZERO };
33
+ try {
34
+ const store = openStore({});
34
35
  try {
35
- const store = openStore({});
36
- try {
37
- let inputTokens = 0;
38
- let outputTokens = 0;
39
- let calls = 0;
40
- for (const row of store.query({ connectorId })) {
41
- inputTokens += Number.isFinite(row.inputTokens) ? row.inputTokens : 0;
42
- outputTokens += Number.isFinite(row.outputTokens) ? row.outputTokens : 0;
43
- calls += 1;
44
- }
45
- return {
46
- inputTokens,
47
- outputTokens,
48
- totalTokens: inputTokens + outputTokens,
49
- calls
50
- };
51
- } finally {
52
- store.close();
36
+ let inputTokens = 0;
37
+ let outputTokens = 0;
38
+ let calls = 0;
39
+ for (const row of store.query({ connectorId })) {
40
+ inputTokens += Number.isFinite(row.inputTokens) ? row.inputTokens : 0;
41
+ outputTokens += Number.isFinite(row.outputTokens) ? row.outputTokens : 0;
42
+ calls += 1;
53
43
  }
54
- } catch {
55
- return { ...ZERO };
44
+ return {
45
+ inputTokens,
46
+ outputTokens,
47
+ totalTokens: inputTokens + outputTokens,
48
+ calls
49
+ };
50
+ } finally {
51
+ store.close();
56
52
  }
53
+ } catch {
54
+ return { ...ZERO };
55
+ }
56
+ }
57
+ function buildTelemetryAccessor(connectorId) {
58
+ return async () => {
59
+ return readTelemetryUsageSummary(connectorId);
57
60
  };
58
61
  }
62
+ function attachLazyTelemetryUsage(ctx, connectorId, read = readTelemetryUsageSummary) {
63
+ let cached;
64
+ let hasCached = false;
65
+ Object.defineProperty(ctx, "usage", {
66
+ configurable: true,
67
+ enumerable: true,
68
+ get() {
69
+ if (!hasCached) {
70
+ cached = read(connectorId);
71
+ hasCached = true;
72
+ }
73
+ return cached;
74
+ },
75
+ set(value) {
76
+ cached = value;
77
+ hasCached = true;
78
+ }
79
+ });
80
+ }
59
81
 
60
82
  // src/telemetry/measure.ts
61
83
  var MODALITY_ESTIMATE = {
@@ -340,6 +362,7 @@ async function runNativeHook(opts) {
340
362
 
341
363
  export {
342
364
  buildTelemetryAccessor,
365
+ attachLazyTelemetryUsage,
343
366
  measureToolCall,
344
367
  measureToolDefs,
345
368
  eventMatcherSubject,
@@ -348,4 +371,4 @@ export {
348
371
  isNativeHookDeclared,
349
372
  runNativeHook
350
373
  };
351
- //# sourceMappingURL=chunk-HAIMYUEY.js.map
374
+ //# sourceMappingURL=chunk-YKVNI44Y.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/runtime/telemetry-accessor.ts","../src/telemetry/measure.ts","../src/runtime/hook-entrypoint.ts"],"sourcesContent":["/**\n * runtime/telemetry-accessor — build the handler-facing {@link TelemetryAccessor}.\n *\n * Every runtime entrypoint (hook / statusline / action) stamps `ctx.telemetry`\n * (or `evt.telemetry`) with the accessor built here so a connector handler can\n * read ITS OWN recorded usage on demand (`await ctx.telemetry?.()`), without the\n * handler reaching into the telemetry store directly.\n *\n * The accessor is LAZY (it opens the store only when called) and DEFENSIVE:\n * - AGENT_CONNECTOR_TELEMETRY=0 → resolves zeros without touching disk;\n * - any read error → resolves zeros (NEVER throws into a handler — the hook\n * runtime is fail-open, the statusline fail-safe, and even the action\n * surface must not have a usage read crash an otherwise-fine run).\n *\n * COST: each accessor call, or the first read of a lazy `ctx.usage`, reads the\n * connector's telemetry file in full (the NDJSON store has no since/limit bound)\n * and linear-scans it. Cheap for normal stores, but a handler on a HOT path\n * should call it only when it needs usage.\n */\n\nimport type { TelemetryAccessor, TelemetryUsageSummary } from \"../core/types.js\";\nimport { openStore } from \"../telemetry/store.js\";\n\n/** The empty summary returned when telemetry is off or a read fails. */\nconst ZERO: TelemetryUsageSummary = {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n calls: 0,\n};\n\n/**\n * Synchronously sum every stored row's inputTokens/outputTokens for the\n * connector and count rows (`calls`). Honors the AGENT_CONNECTOR_TELEMETRY=0\n * kill switch (zeros, no disk touch) and swallows any error (zeros).\n */\nexport function readTelemetryUsageSummary(connectorId: string): TelemetryUsageSummary {\n if (process.env.AGENT_CONNECTOR_TELEMETRY === \"0\") return { ...ZERO };\n try {\n const store = openStore({});\n try {\n let inputTokens = 0;\n let outputTokens = 0;\n let calls = 0;\n // COERCE each addend to a finite number: query() tolerates malformed\n // LINES but does not validate field shapes, so a legacy/hand-edited row\n // with a missing (→ NaN) or string (→ concat) token field must not\n // poison the summary's numeric contract. A non-finite token reads as 0.\n for (const row of store.query({ connectorId })) {\n inputTokens += Number.isFinite(row.inputTokens) ? row.inputTokens : 0;\n outputTokens += Number.isFinite(row.outputTokens) ? row.outputTokens : 0;\n calls += 1;\n }\n return {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n calls,\n };\n } finally {\n store.close();\n }\n } catch {\n // Never throw into a handler — a usage read failure resolves to zeros.\n return { ...ZERO };\n }\n}\n\n/**\n * Build a {@link TelemetryAccessor} bound to `connectorId`. The returned async\n * function uses {@link readTelemetryUsageSummary}; it never throws.\n */\nexport function buildTelemetryAccessor(connectorId: string): TelemetryAccessor {\n return async (): Promise<TelemetryUsageSummary> => {\n return readTelemetryUsageSummary(connectorId);\n };\n}\n\n/**\n * Install a cached lazy `usage` property on a statusline context. This preserves\n * synchronous `ctx.usage` reads for render functions without forcing every\n * status refresh to scan the telemetry store when the render never uses usage.\n */\nexport function attachLazyTelemetryUsage(\n ctx: { usage?: TelemetryUsageSummary },\n connectorId: string,\n read: (connectorId: string) => TelemetryUsageSummary = readTelemetryUsageSummary,\n): void {\n let cached: TelemetryUsageSummary | undefined;\n let hasCached = false;\n\n Object.defineProperty(ctx, \"usage\", {\n configurable: true,\n enumerable: true,\n get() {\n if (!hasCached) {\n cached = read(connectorId);\n hasCached = true;\n }\n return cached;\n },\n set(value: TelemetryUsageSummary | undefined) {\n cached = value;\n hasCached = true;\n },\n });\n}\n","/**\n * telemetry/measure — pure measurement helpers over a single MCP tool call.\n *\n * The framework tokenizes its OWN bytes: the tool-call arguments going in, the\n * tool result coming out, and the fixed tool-definition schemas. These helpers\n * turn those into {@link TokenCount}s using the default {@link Tokenizer}.\n *\n * Honesty rules:\n * • Binary modalities (image/audio/resource blobs) are NOT tokenized — base64\n * would massively over-count. Each gets a flat per-modality estimate, and\n * because that estimate is itself an approximation the combined confidence\n * is pulled down to at least \"tokenizer-approx\".\n * • When combining several counts, the reported confidence is the WORST\n * (least-confident) of the inputs — never report \"exact\" for a mixed bag.\n *\n * Everything here is pure: no IO, no mutation of inputs.\n */\n\nimport { getTokenizer } from \"./tokenizer.js\";\nimport { worstConfidence } from \"./types.js\";\nimport type {\n ConfidenceSource,\n ModelFamily,\n TokenCount,\n Tokenizer,\n} from \"./types.js\";\n\n/** Per-call measurement: tokens in, tokens out, and combined confidence. */\nexport interface ToolCallMeasurement {\n inputTokens: number;\n outputTokens: number;\n source: ConfidenceSource;\n}\n\n/**\n * Flat token estimates for non-text content blocks. These mirror common host\n * accounting (an image tile is roughly ~85 tokens at low detail); they are\n * deliberately coarse — we never tokenize the underlying base64 payload.\n */\nconst MODALITY_ESTIMATE: Record<string, number> = {\n image: 85,\n audio: 85,\n resource: 85,\n};\n/** Fallback estimate for an unknown non-text block type. */\nconst UNKNOWN_BLOCK_ESTIMATE = 85;\n\n// Confidence ordering + the worst-of comparison live in ./types (the single\n// source of truth, imported as `worstConfidence` above). Re-exported here so\n// callers that already import `worstConfidence` from this module keep working\n// as a new ConfidenceSource value (e.g. tokenizer-calibrated) slots into the\n// shared ordering.\nexport { worstConfidence };\n\n/** Reduce a list of sources to the single worst (least-confident) one. */\nfunction combineSources(sources: readonly ConfidenceSource[]): ConfidenceSource {\n // Default to the most-confident floor so an empty list combines to the only\n // other source it is paired with; in practice callers always pass ≥1 source.\n let worst: ConfidenceSource = \"host-native\";\n for (const s of sources) worst = worstConfidence(worst, s);\n return worst;\n}\n\n// ── Structural shapes we read from a tool result (kept local + narrow) ───────\n\n/** A text content block: `{ type: \"text\", text: \"...\" }`. */\ninterface TextBlock {\n type: \"text\";\n text?: unknown;\n}\n/** Any content block; only text blocks expose a `text` field we tokenize. */\ninterface ContentBlock {\n type?: unknown;\n text?: unknown;\n}\n/** The portion of an MCP tool result we measure. */\ninterface ToolResultLike {\n content?: unknown;\n structuredContent?: unknown;\n}\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null;\n}\n\nfunction isTextBlock(block: ContentBlock): block is TextBlock {\n return block.type === \"text\";\n}\n\n/**\n * Measure one tool call.\n *\n * Input = canonical JSON of `args`.\n * Output = tokens over the TEXTUAL parts of `result`:\n * • If `result.content` is an array of blocks, text blocks are tokenized via\n * their `text` field and non-text blocks add a flat per-modality estimate\n * (no base64 tokenization).\n * • `result.structuredContent`, when present, is tokenized as canonical JSON.\n * • Anything else (string / arbitrary object) is tokenized as canonical JSON.\n *\n * The reported `source` is the worst of the input and output sources.\n */\nexport function measureToolCall(\n args: unknown,\n result: unknown,\n family: ModelFamily,\n tok: Tokenizer = getTokenizer(),\n): ToolCallMeasurement {\n const input = tok.countValue(args, family);\n const output = measureResult(result, family, tok);\n return {\n inputTokens: input.tokens,\n outputTokens: output.tokens,\n source: worstConfidence(input.source, output.source),\n };\n}\n\n/** Tokenize the textual + structured parts of a tool result. */\nfunction measureResult(\n result: unknown,\n family: ModelFamily,\n tok: Tokenizer,\n): TokenCount {\n if (!isObject(result)) {\n // Plain string or scalar result — count its canonical form directly.\n return tok.countValue(result, family);\n }\n\n const res = result as ToolResultLike;\n const sources: ConfidenceSource[] = [];\n let tokens = 0;\n\n if (Array.isArray(res.content)) {\n for (const raw of res.content) {\n if (!isObject(raw)) continue;\n const block = raw as ContentBlock;\n if (isTextBlock(block)) {\n const text = typeof block.text === \"string\" ? block.text : \"\";\n const c = tok.count(text, family);\n tokens += c.tokens;\n sources.push(c.source);\n } else {\n // image / audio / resource / unknown → flat estimate, no base64 BPE.\n const key = typeof block.type === \"string\" ? block.type : \"\";\n tokens += MODALITY_ESTIMATE[key] ?? UNKNOWN_BLOCK_ESTIMATE;\n // A flat estimate is an approximation, never \"exact\".\n sources.push(\"tokenizer-approx\");\n }\n }\n } else if (res.content !== undefined) {\n // content present but not an array (e.g. a bare string) → count it whole.\n const c = tok.countValue(res.content, family);\n tokens += c.tokens;\n sources.push(c.source);\n }\n\n if (res.structuredContent !== undefined) {\n const c = tok.countValue(res.structuredContent, family);\n tokens += c.tokens;\n sources.push(c.source);\n }\n\n // Nothing measurable found → count the whole object as a fallback so we never\n // silently report zero for a non-empty result.\n if (sources.length === 0) {\n return tok.countValue(result, family);\n }\n\n return { tokens, source: combineSources(sources) };\n}\n\n/**\n * Measure the fixed tool-definition overhead: tokenize the JSON of the entire\n * `tools/list` array once. `tools` is the raw array of tool descriptors as the\n * server advertises them (shape is host/SDK-specific, so it is treated as\n * opaque JSON here).\n */\nexport function measureToolDefs(\n tools: readonly unknown[],\n family: ModelFamily,\n tok: Tokenizer = getTokenizer(),\n): TokenCount {\n return tok.countValue(tools, family);\n}\n\n/**\n * Measure one RUNTIME hook dispatch (the new `hook` developer-axis surface).\n *\n * Input = canonical JSON of the inbound normalized event payload the handler\n * reads (the host-provided fields: toolInput / prompt / raw / etc.).\n * Output = canonical JSON of what the handler RETURNS that becomes context or a\n * decision the host consumes (additionalContext / updatedInput / reason\n * and the rest of the normalized {@link HookResponse}).\n *\n * Uses the SAME tokenizer + worst-of confidence combination as the proxy. Pure:\n * no IO, no mutation. The two values are tokenized whole (a hook payload has no\n * binary content blocks to special-case, unlike a tool result).\n */\nexport function measureHook(\n eventPayload: unknown,\n handlerReturn: unknown,\n family: ModelFamily,\n tok: Tokenizer = getTokenizer(),\n): ToolCallMeasurement {\n const input = tok.countValue(eventPayload, family);\n const output = tok.countValue(handlerReturn, family);\n return {\n inputTokens: input.tokens,\n outputTokens: output.tokens,\n source: worstConfidence(input.source, output.source),\n };\n}\n","/**\n * runtime/hook-entrypoint — the universal json-stdio hook dispatcher.\n *\n * Every json-stdio host points its hook config at the single stable home binary\n * (`<homeBin> hook <platformId> <event> --connector <id>`, built by\n * core/spawn.buildHomeBinHookCommand). The CLI reads stdin and calls\n * {@link runHook} with the parsed flags + the raw stdin string. This module:\n *\n * 1. Loads the registered connector (live handlers) and the host adapter.\n * 2. Parses the host's stdin payload into a normalized event via the adapter.\n * 3. Finds the connector's handler for the event, honoring the tool matcher.\n * 4. Runs the handler, normalizes its return, and formats the adapter's native\n * reply.\n *\n * Fail-open is the safety contract: ANY error degrades to exit 0 (\"allow\") so a\n * framework or handler bug can never wedge a host's tool call — EXCEPT when the\n * event is PreToolUse or PermissionRequest and the handler explicitly denied,\n * in which case the deny (a deliberate security decision) is preserved rather\n * than swallowed.\n */\n\nimport type {\n HookEventName,\n HookResponse,\n NativeHookDef,\n NativeHookEvent,\n PlatformId,\n ResolvedConnector,\n} from \"../core/types.js\";\nimport { log } from \"../core/logger.js\";\nimport {\n loadRegisteredConnector,\n readRegisteredMeta,\n} from \"../core/load-connector.js\";\nimport { loadAdapter, REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\nimport { buildTelemetryAccessor } from \"./telemetry-accessor.js\";\nimport type { NormalizedEvent } from \"../adapters/spi.js\";\nimport { projectIdentity } from \"../core/paths.js\";\nimport { measureHook } from \"../telemetry/measure.js\";\nimport { openStore, newRecordId } from \"../telemetry/store.js\";\nimport { getTokenizer, inferModelFamily } from \"../telemetry/tokenizer.js\";\n\n/** Flags + stdin the CLI hands to {@link runHook}. */\nexport interface RunHookOptions {\n /** Host platform id from the hook command (`hook <platformId> ...`). */\n platformId: string;\n /** Canonical lifecycle event name from the hook command. */\n event: HookEventName;\n /** Connector id from `--connector <id>`. */\n connectorId: string;\n /** Raw stdin payload (host-native JSON). Empty string is tolerated → `{}`. */\n stdin: string;\n}\n\n/** Process-level result the CLI translates into exit code + stdout/stderr. */\nexport interface RunHookResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n\n/** A pass-through \"allow\" reply with exit 0 and no payload. */\nconst ALLOW: RunHookResult = { exitCode: 0 };\n\n/**\n * The string a connector matcher filters on, when the event carries one:\n * tool events (PreToolUse / PostToolUse / PermissionRequest /\n * PostToolUseFailure) expose `toolName`; subagent events expose `agentType`.\n * Returns undefined when the event has neither (no filtering) — including a\n * SubagentStop arriving WITHOUT agent_type, which some hosts fail to populate;\n * filtering out such an event would silently drop a real stop, so we run the\n * handler instead (fail-open).\n */\nexport function eventMatcherSubject(evt: NormalizedEvent): string | undefined {\n const name = (evt as { toolName?: unknown }).toolName;\n if (typeof name === \"string\") return name;\n const agentType = (evt as { agentType?: unknown }).agentType;\n if (typeof agentType === \"string\") return agentType;\n return undefined;\n}\n\n/**\n * Tolerantly parse the host's stdin payload. Empty / whitespace-only input is a\n * legitimate \"no payload\" signal from some hosts and resolves to `{}`. Malformed\n * JSON also degrades to `{}` rather than throwing — fail-open is the contract.\n */\nfunction parseStdin(stdin: string): unknown {\n const trimmed = stdin.trim();\n if (trimmed === \"\") return {};\n try {\n return JSON.parse(trimmed);\n } catch {\n return {};\n }\n}\n\n/**\n * Compile the connector's matcher (a regex string) for a tool event. A missing\n * or empty matcher matches everything (returns null → no filtering). An invalid\n * regex degrades to \"match everything\" so a typo never blocks tool calls.\n */\nexport function compileMatcher(matcher: string | undefined): RegExp | null {\n if (!matcher || matcher === \"\") return null;\n try {\n return new RegExp(matcher);\n } catch {\n return null;\n }\n}\n\n/**\n * Normalize a handler return into a concrete HookResponse. A void/non-object\n * return becomes `{}` — NO decision — which every adapter formats as\n * pass-through allow (`response.decision ?? \"allow\"`). Deliberately NOT\n * `{decision:\"allow\"}`: on PermissionRequest an explicit \"allow\" is an ACTIVE\n * grant that suppresses the host's permission dialog, and a handler that\n * returns nothing must fall through to the dialog, never silently grant.\n */\nfunction normalizeResponse(value: HookResponse | void): HookResponse {\n if (value == null || typeof value !== \"object\") return {};\n return value;\n}\n\n/**\n * Resolve the host platform to stamp on a hook telemetry row. Mirrors the serve\n * `--host` plumbing: the install-target platform id is baked into the hook\n * command (`hook <platformId> <event> …`) so `opts.platformId` is authoritative,\n * but an explicit env override (AGENT_CONNECTOR_HOST) wins when it names a known\n * platform. Falls back to the event's adapter-stamped hostPlatform, then\n * \"unknown\" — never throws.\n */\nfunction resolveHookHostPlatform(\n platformId: string,\n evt: NormalizedEvent | NativeHookEvent,\n): PlatformId {\n const override = process.env.AGENT_CONNECTOR_HOST;\n if (\n override !== undefined &&\n REGISTERED_PLATFORM_IDS.has(override as PlatformId)\n ) {\n return override as PlatformId;\n }\n if (REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)) {\n return platformId as PlatformId;\n }\n const fromEvent = (evt as { hostPlatform?: unknown }).hostPlatform;\n if (\n typeof fromEvent === \"string\" &&\n REGISTERED_PLATFORM_IDS.has(fromEvent as PlatformId)\n ) {\n return fromEvent as PlatformId;\n }\n return \"unknown\";\n}\n\n/**\n * Record one RUNTIME hook dispatch as a `hook` developer-axis telemetry row.\n *\n * input = the inbound event payload the handler reads (normalized event, or\n * the {@link NativeHookEvent} envelope for native passthrough hooks);\n * output = what the handler returned (a normalized {@link HookResponse}, or the\n * verbatim native reply object). Tokenized with the SAME tokenizer the\n * proxy uses. For a native hook `opts.event` is the host-native name.\n *\n * MUST be fail-open (the hook runtime is fail-open by contract): any error here\n * is swallowed so a measurement bug can NEVER break a host's hook. Honors the\n * AGENT_CONNECTOR_TELEMETRY=0 kill switch (skips entirely; the store's append is\n * already a no-op under it, but we also skip the tokenize work).\n */\nfunction recordHookTelemetry(\n opts: { platformId: string; event: string; connectorId: string },\n connector: ResolvedConnector,\n evt: NormalizedEvent | NativeHookEvent,\n response: unknown,\n): void {\n if (process.env.AGENT_CONNECTOR_TELEMETRY === \"0\") return;\n try {\n const family = inferModelFamily(\"\", connector.telemetry.modelFamilyHint);\n const measurement = measureHook(evt, response, family, getTokenizer());\n\n const sessionId =\n typeof (evt as { sessionId?: unknown }).sessionId === \"string\"\n ? ((evt as { sessionId: string }).sessionId)\n : \"\";\n const evtProjectDir = (evt as { projectDir?: unknown }).projectDir;\n const projectDir =\n typeof evtProjectDir === \"string\" && evtProjectDir !== \"\"\n ? evtProjectDir\n : process.cwd();\n const id = projectIdentity(projectDir);\n\n const store = openStore({});\n try {\n store.append({\n id: newRecordId(0),\n ts: Date.now(),\n connectorId: opts.connectorId,\n toolName: opts.event, // for a hook row the per-item name IS the event\n scope: \"hook\",\n surfaceKind: \"hook\",\n hostPlatform: resolveHookHostPlatform(opts.platformId, evt),\n sessionId,\n projectKey: id.key,\n projectDir: id.dir,\n inputTokens: measurement.inputTokens,\n outputTokens: measurement.outputTokens,\n confidenceSource: measurement.source,\n isError: false,\n });\n } finally {\n store.close();\n }\n } catch {\n // Fail-open: a telemetry error must NEVER break the hook runtime.\n }\n}\n\n/**\n * Dispatch one host hook invocation. Always resolves (never rejects): every\n * failure path returns a concrete {@link RunHookResult} so the CLI can exit\n * cleanly. See the module header for the fail-open contract.\n */\nexport async function runHook(opts: RunHookOptions): Promise<RunHookResult> {\n const { platformId, event, connectorId, stdin } = opts;\n\n try {\n const connector = await loadRegisteredConnector(connectorId);\n const adapter = await loadAdapter(platformId);\n\n // mcp-only hosts (and any adapter without runtime dispatch) cannot parse a\n // hook payload — nothing to do, allow.\n if (!adapter || !adapter.parseEvent || !adapter.formatReply) {\n return ALLOW;\n }\n\n const raw = parseStdin(stdin);\n const evt = adapter.parseEvent(event, raw);\n // The hook command carries the authoritative connector id; stamp it on the\n // event so handlers see the connector they were dispatched for.\n evt.connectorId = connectorId;\n // Unify the hook event with HostCtx: the adapter's parseEvent has no\n // capabilities/scope/telemetry at parse time (they are runtime-only), so the\n // runtime ALWAYS backfills them before the handler runs. capabilities comes\n // from the adapter; scope is recovered from the registered metadata (sync);\n // telemetry is the lazy per-connector usage accessor. The SAME three\n // assignments run on the error path (failOpenOrPreserveDeny) for symmetry.\n evt.capabilities = adapter.capabilities;\n evt.scope = readRegisteredMeta(connectorId)?.scope;\n evt.telemetry = buildTelemetryAccessor(connectorId);\n\n const definition = connector.hooks[event];\n if (!definition || typeof definition.handler !== \"function\") {\n // The connector declares no handler for this event — allow.\n return ALLOW;\n }\n\n // Per-host handler override: when dispatching for host X, `hosts[X].handler`\n // wins over the top-level handler; a host not listed (or a per-host entry\n // that is somehow not a function) falls back to the top-level handler.\n // Selection NEVER throws — fail-open is preserved.\n // NOTE: keyed on the RAW install-baked platformId (the host this entrypoint\n // was registered for), NOT resolveHookHostPlatform's AGENT_CONNECTOR_HOST\n // override — that override only re-labels the telemetry row. The error path\n // (failOpenOrPreserveDeny) resolves the IDENTICAL handler the same way, so a\n // per-host deny is preserved consistently.\n const perHost = definition.hosts?.[platformId as PlatformId]?.handler;\n const handler = typeof perHost === \"function\" ? perHost : definition.handler;\n\n // Matcher: if set and the event's subject (tool name, or agent type for\n // Subagent* events) does not match, allow (the hook is simply not\n // interested in this tool/agent). The matcher is the definition's — a\n // per-host handler shares the top-level matcher.\n const subject = eventMatcherSubject(evt);\n if (subject !== undefined) {\n const re = compileMatcher(definition.matcher);\n if (re && !re.test(subject)) return ALLOW;\n }\n\n // Run the resolved handler. Its return is normalized (void → allow) and\n // handed to the adapter to render the host-native reply.\n const handlerResult = await handler(\n // The adapter parsed `evt` as exactly this event's payload type; the\n // HooksConfig handler for the same event expects that payload.\n evt as never,\n );\n const response = normalizeResponse(handlerResult);\n\n // Developer-axis telemetry for the RUNTIME `hook` surface. Fail-open: never\n // lets a measurement error break the hook (handled inside the helper).\n recordHookTelemetry(opts, connector, evt, response);\n\n const reply = adapter.formatReply(event, response);\n return {\n exitCode: reply.exitCode,\n ...(reply.stdout !== undefined ? { stdout: reply.stdout } : {}),\n ...(reply.stderr !== undefined ? { stderr: reply.stderr } : {}),\n };\n } catch (err) {\n // Fail-open: a framework/handler error must not wedge the host's tool call.\n // The ONE exception is a PreToolUse / PermissionRequest deny — a deliberate\n // block we honor even if a later step threw. We re-derive that decision\n // defensively from the adapter so a throw AFTER the deny still surfaces it.\n const message = err instanceof Error ? err.message : String(err);\n log.error(`hook ${platformId}/${event} (${connectorId}) failed:`, message);\n return failOpenOrPreserveDeny(opts, message);\n }\n}\n\n/**\n * Events whose explicit deny survives the fail-open error path. Both are\n * permission gates — a deny there is a deliberate security decision that must\n * never be silently downgraded to allow. (Stop-class denies are persistence\n * conveniences, not security boundaries, so they stay fail-open.)\n */\nconst DENY_PRESERVE_EVENTS: ReadonlySet<HookEventName> = new Set([\n \"PreToolUse\",\n \"PermissionRequest\",\n]);\n\n/**\n * Error path. Returns fail-open allow, UNLESS this is a deny-preserving event\n * (PreToolUse / PermissionRequest) whose handler explicitly denied — in which\n * case the deny is reconstructed and preserved (a security decision is never\n * silently downgraded to allow).\n *\n * Best-effort: if anything in the deny reconstruction itself throws, we fall\n * back to allow (we never escalate an error into a spurious block).\n */\nasync function failOpenOrPreserveDeny(\n opts: RunHookOptions,\n errorMessage: string,\n): Promise<RunHookResult> {\n if (!DENY_PRESERVE_EVENTS.has(opts.event)) return ALLOW;\n try {\n const connector = await loadRegisteredConnector(opts.connectorId);\n const adapter = await loadAdapter(opts.platformId);\n if (!adapter?.parseEvent || !adapter.formatReply) return ALLOW;\n\n const definition = connector.hooks[opts.event];\n if (!definition || typeof definition.handler !== \"function\") return ALLOW;\n\n // Reconstruct the deny from the SAME handler the main path would have run —\n // the per-host override if one is declared for this host, else the top-level\n // handler. Otherwise a per-host deny could be silently downgraded on the\n // error path.\n const perHost = definition.hosts?.[opts.platformId as PlatformId]?.handler;\n const handler = typeof perHost === \"function\" ? perHost : definition.handler;\n\n const raw = parseStdin(opts.stdin);\n const evt = adapter.parseEvent(opts.event, raw);\n evt.connectorId = opts.connectorId;\n // Backfill the HostCtx fields here too (symmetry with the main path), so a\n // per-host deny reconstructed on the error path still carries capabilities/\n // scope/telemetry — a handler that branches on them denies identically.\n evt.capabilities = adapter.capabilities;\n evt.scope = readRegisteredMeta(opts.connectorId)?.scope;\n evt.telemetry = buildTelemetryAccessor(opts.connectorId);\n\n const subject = eventMatcherSubject(evt);\n if (subject !== undefined) {\n const re = compileMatcher(definition.matcher);\n if (re && !re.test(subject)) return ALLOW;\n }\n\n const response = normalizeResponse(await handler(evt as never));\n if (response.decision !== \"deny\") return ALLOW;\n\n const reply = adapter.formatReply(opts.event, response);\n return {\n exitCode: reply.exitCode,\n ...(reply.stdout !== undefined ? { stdout: reply.stdout } : {}),\n ...(reply.stderr !== undefined\n ? { stderr: reply.stderr }\n : { stderr: errorMessage }),\n };\n } catch {\n // Reconstruction failed — never escalate an internal error into a block.\n return ALLOW;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Native (passthrough) hooks — host events OUTSIDE the normalized union\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Flags + stdin for {@link runNativeHook}. `event` is HOST-NATIVE (non-union). */\nexport interface RunNativeHookOptions {\n /** Host platform id from the hook command (`hook <platformId> ...`). */\n platformId: string;\n /** Host-native event name, verbatim (e.g. \"TaskCreated\"). */\n event: string;\n /** Connector id from `--connector <id>`. */\n connectorId: string;\n /** Raw stdin payload (host-native JSON). Empty string is tolerated → `{}`. */\n stdin: string;\n}\n\n/** The connector's native hook definition for `platformId`/`event`, if any. */\nfunction nativeHookDef(\n connector: ResolvedConnector,\n platformId: string,\n event: string,\n): NativeHookDef | undefined {\n return connector.platforms[platformId as PlatformId]?.nativeHooks?.[event];\n}\n\n/**\n * True when the registered connector declares `event` under\n * `platforms[platformId].nativeHooks` with a live handler. Used by the hook CLI\n * to decide whether a non-union event name is accepted (declared → dispatch via\n * {@link runNativeHook}) or rejected with the strict unknown-event error.\n * Fail-safe: any load error reads as \"not declared\".\n */\nexport async function isNativeHookDeclared(\n platformId: string,\n event: string,\n connectorId: string,\n): Promise<boolean> {\n try {\n const connector = await loadRegisteredConnector(connectorId);\n return typeof nativeHookDef(connector, platformId, event)?.handler === \"function\";\n } catch {\n return false;\n }\n}\n\n/**\n * Dispatch one NATIVE (passthrough) hook invocation. No normalized parse, no\n * HookResponse mapping, no runtime matcher evaluation (the host's own matcher\n * already filtered — the def's matcher string was written verbatim into the\n * host config at install):\n *\n * stdin JSON → NativeHookEvent{raw} → handler → VERBATIM JSON stdout (exit 0).\n *\n * void/undefined return → exit 0 with no output. Fail-open: ANY throw degrades\n * to exit 0 with no output — exit-2 blocking semantics are not modeled in v1.\n * Telemetry: records the same scope:\"hook\" developer-axis row as normalized\n * hooks, with the NATIVE event name as the per-item name.\n */\nexport async function runNativeHook(\n opts: RunNativeHookOptions,\n): Promise<RunHookResult> {\n const { platformId, event, connectorId, stdin } = opts;\n try {\n const connector = await loadRegisteredConnector(connectorId);\n const def = nativeHookDef(connector, platformId, event);\n if (!def || typeof def.handler !== \"function\") {\n // Not declared for this platform — nothing to do, allow.\n return ALLOW;\n }\n\n const raw = parseStdin(stdin);\n // Best-effort session/project extraction from the json-stdio common shape\n // (Claude Code: session_id / cwd). Everything else stays in `raw` untouched.\n const sessionId =\n typeof (raw as { session_id?: unknown })?.session_id === \"string\"\n ? (raw as { session_id: string }).session_id\n : \"\";\n const cwd = (raw as { cwd?: unknown })?.cwd;\n const evt: NativeHookEvent = {\n event,\n hostPlatform: REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)\n ? (platformId as PlatformId)\n : \"unknown\",\n sessionId,\n ...(typeof cwd === \"string\" && cwd !== \"\" ? { projectDir: cwd } : {}),\n raw,\n };\n\n const result = await def.handler(evt);\n\n // Same scope:\"hook\" telemetry row as normalized hooks (fail-open inside).\n recordHookTelemetry(opts, connector, evt, result === undefined ? {} : result);\n\n if (result === undefined) return ALLOW; // void → exit 0, no output\n const json = JSON.stringify(result);\n // Non-JSON-serializable returns (functions/symbols) degrade to silence.\n if (json === undefined) return ALLOW;\n return { exitCode: 0, stdout: json };\n } catch (err) {\n // Fail-open, unconditionally: native hooks have no deny-preserve carve-out\n // (there is no normalized decision to reconstruct).\n const message = err instanceof Error ? err.message : String(err);\n log.error(\n `native hook ${platformId}/${event} (${connectorId}) failed:`,\n message,\n );\n return ALLOW;\n }\n}\n"],"mappings":"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","names":[]}
@@ -5,11 +5,13 @@ import {
5
5
  import {
6
6
  BaseAdapter,
7
7
  parseJsonc
8
- } from "./chunk-PFDUGDOA.js";
8
+ } from "./chunk-3I7UG52L.js";
9
9
  import {
10
- buildServeWrapperCommand,
11
- shouldWrapForTelemetry
12
- } from "./chunk-I5MLE6S7.js";
10
+ renderSkillMd
11
+ } from "./chunk-IEGR4TP3.js";
12
+ import {
13
+ buildWrappedStdio
14
+ } from "./chunk-TO57WYBB.js";
13
15
 
14
16
  // src/adapters/openclaw/index.ts
15
17
  import {
@@ -251,18 +253,7 @@ var OpenClawAdapter = class extends BaseAdapter {
251
253
  if (server.transport === "stdio") {
252
254
  let command = server.command ?? "";
253
255
  let args = [...server.args ?? []];
254
- if (shouldWrapForTelemetry(server, ctx.connector.telemetry)) {
255
- const wrapped = buildServeWrapperCommand(
256
- ctx.homeBinPath,
257
- ctx.connector.id,
258
- command,
259
- args,
260
- ctx.scope,
261
- this.id
262
- );
263
- command = wrapped.command;
264
- args = wrapped.args;
265
- }
256
+ ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));
266
257
  const entry2 = {
267
258
  command: resolveEnvRefsDeep(command)
268
259
  };
@@ -637,7 +628,7 @@ var OpenClawAdapter = class extends BaseAdapter {
637
628
  for (const skill of connector.skills) {
638
629
  const dir = this.skillDir(ctx, skill.name);
639
630
  changes.push(
640
- this.writeContentFile(join(dir, "SKILL.md"), this.renderSkill(skill), ctx.dryRun)
631
+ this.writeContentFile(join(dir, "SKILL.md"), renderSkillMd(skill), ctx.dryRun)
641
632
  );
642
633
  for (const [rel, contents] of Object.entries(skill.resources ?? {})) {
643
634
  const target = this.resolveWithin(dir, rel);
@@ -672,26 +663,6 @@ var OpenClawAdapter = class extends BaseAdapter {
672
663
  }
673
664
  return changes;
674
665
  }
675
- /**
676
- * Render a skill's SKILL.md: frontmatter (name, description + optional model,
677
- * allowed-tools, disable-model-invocation) + body. UNIFORM with codex /
678
- * claude-code — only the parent dir differs (single-line frontmatter keys;
679
- * OpenClaw follows the AgentSkills spec).
680
- */
681
- renderSkill(skill) {
682
- const frontmatter = {
683
- name: skill.name,
684
- description: skill.description
685
- };
686
- if (skill.model !== void 0) frontmatter.model = skill.model;
687
- const allow = skill.tools?.allow;
688
- if (allow && allow.length > 0) frontmatter["allowed-tools"] = allow.join(", ");
689
- if (skill.disableModelInvocation !== void 0) {
690
- frontmatter["disable-model-invocation"] = skill.disableModelInvocation;
691
- }
692
- if (skill.extra) Object.assign(frontmatter, skill.extra);
693
- return this.renderFrontmatterMd(frontmatter, skill.body);
694
- }
695
666
  // ── ts-plugin synthesis ────────────────────────────────────────────────
696
667
  /**
697
668
  * Build ONE self-contained ESM plugin module for OpenClaw.
@@ -719,13 +690,20 @@ var OpenClawAdapter = class extends BaseAdapter {
719
690
  * Build the openclaw.plugin.json manifest the gateway reads inside a
720
691
  * plugins.load.paths directory. It names the plugin and points at the ESM
721
692
  * module entry (index.mjs) so the loader knows what to import.
693
+ *
694
+ * `configSchema` is REQUIRED: `openclaw config validate` (and `openclaw mcp
695
+ * list`) REJECT a manifest without it ("plugin manifest requires
696
+ * configSchema"). Our plugin takes no user config, so we emit the empty
697
+ * closed object schema from openclaw's own minimal manifest example
698
+ * ({ type: "object", additionalProperties: false }).
722
699
  */
723
700
  buildPluginManifest(ctx) {
724
701
  const manifest = {
725
702
  id: ctx.connector.id,
726
703
  name: ctx.connector.displayName || ctx.connector.id,
727
704
  main: this.pluginFileName(),
728
- enabled: true
705
+ enabled: true,
706
+ configSchema: { type: "object", additionalProperties: false }
729
707
  };
730
708
  return `${JSON.stringify(manifest, null, 2)}
731
709
  `;
@@ -1060,4 +1038,4 @@ export {
1060
1038
  adapter,
1061
1039
  openclaw_default
1062
1040
  };
1063
- //# sourceMappingURL=chunk-DT6Y7XBI.js.map
1041
+ //# sourceMappingURL=chunk-YRBFSZ2G.js.map