@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
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  aggregateBy,
4
4
  dedupe
5
- } from "./chunk-XD7MY6HB.js";
5
+ } from "./chunk-7PSNXUFK.js";
6
6
 
7
7
  // src/usage/registry.ts
8
8
  var USAGE_READER_REGISTRY = [
@@ -11,142 +11,142 @@ var USAGE_READER_REGISTRY = [
11
11
  platformId: "claude-code",
12
12
  format: "jsonl",
13
13
  kind: "local",
14
- load: () => import("./claude-code-NMRKTAP7.js").then((m) => m.default)
14
+ load: () => import("./claude-code-FS42PXZO.js").then((m) => m.default)
15
15
  },
16
16
  {
17
17
  platformId: "codex",
18
18
  format: "jsonl",
19
19
  kind: "local",
20
- load: () => import("./codex-YAORPCOD.js").then((m) => m.default)
20
+ load: () => import("./codex-DKBAAUCO.js").then((m) => m.default)
21
21
  },
22
22
  {
23
23
  platformId: "gemini-cli",
24
24
  format: "jsonl",
25
25
  kind: "local",
26
- load: () => import("./gemini-cli-NMVVBO3K.js").then((m) => m.default)
26
+ load: () => import("./gemini-cli-Y6RJMU24.js").then((m) => m.default)
27
27
  },
28
28
  {
29
29
  platformId: "qwen-code",
30
30
  format: "jsonl",
31
31
  kind: "local",
32
- load: () => import("./qwen-code-GQILBJ5B.js").then((m) => m.default)
32
+ load: () => import("./qwen-code-26CSFDX6.js").then((m) => m.default)
33
33
  },
34
34
  {
35
35
  platformId: "copilot-cli",
36
36
  format: "jsonl",
37
37
  kind: "local",
38
- load: () => import("./copilot-cli-MZTAWMPW.js").then((m) => m.default)
38
+ load: () => import("./copilot-cli-CLBJACQ5.js").then((m) => m.default)
39
39
  },
40
40
  {
41
41
  platformId: "pi",
42
42
  format: "jsonl",
43
43
  kind: "local",
44
- load: () => import("./pi-GGDQREVG.js").then((m) => m.default)
44
+ load: () => import("./pi-DLKCPOJE.js").then((m) => m.default)
45
45
  },
46
46
  {
47
47
  platformId: "kimi",
48
48
  format: "jsonl",
49
49
  kind: "local",
50
- load: () => import("./kimi-5FHEXGZD.js").then((m) => m.default)
50
+ load: () => import("./kimi-MSIDEMCI.js").then((m) => m.default)
51
51
  },
52
52
  {
53
53
  platformId: "openclaw",
54
54
  format: "jsonl",
55
55
  kind: "local",
56
- load: () => import("./openclaw-5EQFGOWL.js").then((m) => m.default)
56
+ load: () => import("./openclaw-KAFTNLR2.js").then((m) => m.default)
57
57
  },
58
58
  // U2 — JSON readers
59
59
  {
60
60
  platformId: "amp",
61
61
  format: "json",
62
62
  kind: "local",
63
- load: () => import("./amp-BQZOL5GR.js").then((m) => m.default)
63
+ load: () => import("./amp-CEWOSWQO.js").then((m) => m.default)
64
64
  },
65
65
  {
66
66
  platformId: "droid",
67
67
  format: "json",
68
68
  kind: "local",
69
- load: () => import("./droid-U3ZBLQFO.js").then((m) => m.default)
69
+ load: () => import("./droid-PFQ2PZSF.js").then((m) => m.default)
70
70
  },
71
71
  {
72
72
  platformId: "codebuff",
73
73
  format: "json",
74
74
  kind: "local",
75
- load: () => import("./codebuff-ETYT5UBL.js").then((m) => m.default)
75
+ load: () => import("./codebuff-6KWBW6CT.js").then((m) => m.default)
76
76
  },
77
77
  {
78
78
  platformId: "mux",
79
79
  format: "json",
80
80
  kind: "local",
81
- load: () => import("./mux-XM6AP35L.js").then((m) => m.default)
81
+ load: () => import("./mux-7PIJ7HUQ.js").then((m) => m.default)
82
82
  },
83
83
  {
84
84
  platformId: "roo-code",
85
85
  format: "json",
86
86
  kind: "local",
87
- load: () => import("./roo-code-SUWI4BBN.js").then((m) => m.default)
87
+ load: () => import("./roo-code-HSAE2CJU.js").then((m) => m.default)
88
88
  },
89
89
  {
90
90
  platformId: "kilo",
91
91
  format: "json",
92
92
  kind: "local",
93
- load: () => import("./kilo-SW7BH6EG.js").then((m) => m.default)
93
+ load: () => import("./kilo-SMHPOHJ5.js").then((m) => m.default)
94
94
  },
95
95
  {
96
96
  platformId: "kiro",
97
97
  format: "json",
98
98
  kind: "local",
99
- load: () => import("./kiro-WGOI5CGT.js").then((m) => m.default)
99
+ load: () => import("./kiro-NYRRBIKW.js").then((m) => m.default)
100
100
  },
101
101
  // U3 — SQLite readers (via sql.js wasm)
102
102
  {
103
103
  platformId: "opencode",
104
104
  format: "sqlite",
105
105
  kind: "local",
106
- load: () => import("./opencode-QGP4ALQY.js").then((m) => m.default)
106
+ load: () => import("./opencode-Z65JYILL.js").then((m) => m.default)
107
107
  },
108
108
  {
109
109
  platformId: "goose",
110
110
  format: "sqlite",
111
111
  kind: "local",
112
- load: () => import("./goose-64V46Y2W.js").then((m) => m.default)
112
+ load: () => import("./goose-K2HKUTBK.js").then((m) => m.default)
113
113
  },
114
114
  {
115
115
  platformId: "hermes",
116
116
  format: "sqlite",
117
117
  kind: "local",
118
- load: () => import("./hermes-F3EGTK6N.js").then((m) => m.default)
118
+ load: () => import("./hermes-MF3NX4ZY.js").then((m) => m.default)
119
119
  },
120
120
  {
121
121
  platformId: "kilo-cli",
122
122
  format: "sqlite",
123
123
  kind: "local",
124
- load: () => import("./kilo-cli-ZF272ZHN.js").then((m) => m.default)
124
+ load: () => import("./kilo-cli-T2SRRRJS.js").then((m) => m.default)
125
125
  },
126
126
  {
127
127
  platformId: "synthetic",
128
128
  format: "sqlite",
129
129
  kind: "local",
130
- load: () => import("./synthetic-6FRA7P5Q.js").then((m) => m.default)
130
+ load: () => import("./synthetic-LUT6V6SD.js").then((m) => m.default)
131
131
  },
132
132
  {
133
133
  platformId: "crush",
134
134
  format: "sqlite",
135
135
  kind: "local",
136
- load: () => import("./crush-QBXLNN7T.js").then((m) => m.default)
136
+ load: () => import("./crush-A5C5USRL.js").then((m) => m.default)
137
137
  },
138
138
  {
139
139
  platformId: "zed",
140
140
  format: "sqlite",
141
141
  kind: "local",
142
- load: () => import("./zed-XJFOOKCO.js").then((m) => m.default)
142
+ load: () => import("./zed-XXCNYOIN.js").then((m) => m.default)
143
143
  },
144
144
  // U4 — synced/cloud readers (read tokscale local cache if present, else skip)
145
145
  {
146
146
  platformId: "cursor",
147
147
  format: "synced-cache",
148
148
  kind: "synced",
149
- load: () => import("./cursor-DIW43TRZ.js").then((m) => m.default)
149
+ load: () => import("./cursor-D5SWDVSW.js").then((m) => m.default)
150
150
  },
151
151
  {
152
152
  // Antigravity IDE: the native `~/.gemini/antigravity/conversations/<uuid>.pb`
@@ -156,7 +156,7 @@ var USAGE_READER_REGISTRY = [
156
156
  platformId: "antigravity",
157
157
  format: "synced-cache",
158
158
  kind: "synced",
159
- load: () => import("./antigravity-EA4L225L.js").then((m) => m.default)
159
+ load: () => import("./antigravity-LHFEFNMC.js").then((m) => m.default)
160
160
  },
161
161
  {
162
162
  // Antigravity CLI (`agy`): SHARES the IDE's protobuf (.pb) store (no separate
@@ -165,19 +165,19 @@ var USAGE_READER_REGISTRY = [
165
165
  platformId: "antigravity-cli",
166
166
  format: "synced-cache",
167
167
  kind: "synced",
168
- load: () => import("./antigravity-cli-B2HXZFYQ.js").then((m) => m.default)
168
+ load: () => import("./antigravity-cli-MOKFSWOU.js").then((m) => m.default)
169
169
  },
170
170
  {
171
171
  platformId: "trae",
172
172
  format: "synced-cache",
173
173
  kind: "synced",
174
- load: () => import("./trae-CPPYASR2.js").then((m) => m.default)
174
+ load: () => import("./trae-SIQI3C66.js").then((m) => m.default)
175
175
  },
176
176
  {
177
177
  platformId: "warp",
178
178
  format: "synced-cache",
179
179
  kind: "synced",
180
- load: () => import("./warp-NRBBJQR2.js").then((m) => m.default)
180
+ load: () => import("./warp-5YBSP7FP.js").then((m) => m.default)
181
181
  }
182
182
  ];
183
183
  var REGISTRY_BY_ID = new Map(
@@ -354,4 +354,4 @@ export {
354
354
  hostLeaderboard,
355
355
  formatHostLeaderboard
356
356
  };
357
- //# sourceMappingURL=chunk-NLE2J5P4.js.map
357
+ //# sourceMappingURL=chunk-7HHW23AC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/registry.ts","../src/usage/scan.ts","../src/usage/leaderboard.ts"],"sourcesContent":["/**\r\n * usage/registry — the single source of truth for HOST usage readers.\r\n *\r\n * Mirrors adapters/registry.ts: each platform is ONE entry with a lazy `load()`\r\n * thunk resolving the reader module's default export. Adding a platform is a\r\n * single new entry here plus one `readers/<id>.ts` file — `getUsageReader` /\r\n * `allUsageReaders` and the scan orchestrator all derive from this list.\r\n *\r\n * `format` and `kind` are declared on the factory so the scan layer can describe\r\n * a reader (e.g. note a \"synced\" reader as skipped) without importing it.\r\n */\r\n\r\nimport type { PlatformId } from \"../core/types.js\";\r\nimport type { UsageReader, UsageReaderFactory } from \"./types.js\";\r\n\r\n/**\r\n * Authoritative list of usage readers. To add a platform: drop\r\n * `src/usage/readers/<id>.ts` (default-exporting a {@link UsageReader}) and add\r\n * one entry below.\r\n */\r\nexport const USAGE_READER_REGISTRY: readonly UsageReaderFactory[] = [\r\n // U1 — JSONL readers\r\n {\r\n platformId: \"claude-code\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/claude-code.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"codex\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/codex.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"gemini-cli\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/gemini-cli.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"qwen-code\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/qwen-code.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"copilot-cli\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/copilot-cli.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"pi\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/pi.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"kimi\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/kimi.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"openclaw\",\r\n format: \"jsonl\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/openclaw.js\").then((m) => m.default),\r\n },\r\n // U2 — JSON readers\r\n {\r\n platformId: \"amp\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/amp.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"droid\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/droid.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"codebuff\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/codebuff.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"mux\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/mux.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"roo-code\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/roo-code.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"kilo\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/kilo.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"kiro\",\r\n format: \"json\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/kiro.js\").then((m) => m.default),\r\n },\r\n // U3 — SQLite readers (via sql.js wasm)\r\n {\r\n platformId: \"opencode\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/opencode.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"goose\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/goose.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"hermes\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/hermes.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"kilo-cli\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/kilo-cli.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"synthetic\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/synthetic.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"crush\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/crush.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"zed\",\r\n format: \"sqlite\",\r\n kind: \"local\",\r\n load: () => import(\"./readers/zed.js\").then((m) => m.default),\r\n },\r\n // U4 — synced/cloud readers (read tokscale local cache if present, else skip)\r\n {\r\n platformId: \"cursor\",\r\n format: \"synced-cache\",\r\n kind: \"synced\",\r\n load: () => import(\"./readers/cursor.js\").then((m) => m.default),\r\n },\r\n {\r\n // Antigravity IDE: the native `~/.gemini/antigravity/conversations/<uuid>.pb`\r\n // store is PROTOBUF with no public schema (CONFIRMED by install) → not\r\n // parseable. So this is a SYNCED reader: it reads the tokscale synced-cache\r\n // if present, else [] (\"requires sync\"). The native dir is detection-only.\r\n platformId: \"antigravity\",\r\n format: \"synced-cache\",\r\n kind: \"synced\",\r\n load: () => import(\"./readers/antigravity.js\").then((m) => m.default),\r\n },\r\n {\r\n // Antigravity CLI (`agy`): SHARES the IDE's protobuf (.pb) store (no separate\r\n // dir, no public schema) → not parseable. SYNCED reader: tokscale cache if\r\n // present, else [] (\"requires sync\").\r\n platformId: \"antigravity-cli\",\r\n format: \"synced-cache\",\r\n kind: \"synced\",\r\n load: () => import(\"./readers/antigravity-cli.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"trae\",\r\n format: \"synced-cache\",\r\n kind: \"synced\",\r\n load: () => import(\"./readers/trae.js\").then((m) => m.default),\r\n },\r\n {\r\n platformId: \"warp\",\r\n format: \"synced-cache\",\r\n kind: \"synced\",\r\n load: () => import(\"./readers/warp.js\").then((m) => m.default),\r\n },\r\n];\r\n\r\n/** O(1) lookup index, built once at module-load time. */\r\nconst REGISTRY_BY_ID: ReadonlyMap<PlatformId, UsageReaderFactory> = new Map(\r\n USAGE_READER_REGISTRY.map((factory) => [factory.platformId, factory] as const),\r\n);\r\n\r\n/** Look up the lazy factory for a platform id, or undefined when unregistered. */\r\nexport function getUsageReaderFactory(id: PlatformId | string): UsageReaderFactory | undefined {\r\n return REGISTRY_BY_ID.get(id as PlatformId);\r\n}\r\n\r\n/** Resolve a platform id to its reader singleton, or undefined when unregistered. */\r\nexport async function getUsageReader(id: PlatformId | string): Promise<UsageReader | undefined> {\r\n const factory = getUsageReaderFactory(id);\r\n return factory ? factory.load() : undefined;\r\n}\r\n\r\n/** Load every registered reader (imports run in parallel; preserves order). */\r\nexport async function allUsageReaders(): Promise<UsageReader[]> {\r\n return Promise.all(USAGE_READER_REGISTRY.map((factory) => factory.load()));\r\n}\r\n","/**\r\n * usage/scan — orchestrate every registered reader into one deduped record set.\r\n *\r\n * Iterates USAGE_READER_REGISTRY (optionally filtered by platform), loads and\r\n * runs each reader, and folds the results together. Per-reader robustness:\r\n * • a reader that throws (it shouldn't — readers are fail-open) is CAUGHT and\r\n * recorded as skipped, never aborting the whole scan;\r\n * • a \"synced\" reader that returns no rows is noted as skipped(\"requires sync\")\r\n * so the report can honestly explain why a cloud platform shows nothing;\r\n * • a reader that simply has no local data returns [] silently (no root).\r\n *\r\n * After collection: global cross-source dedupe, then a final sinceMs filter\r\n * (readers also honor sinceMs, but the scan re-filters as a backstop).\r\n */\r\n\r\nimport type { PlatformId } from \"../core/types.js\";\r\nimport type { UsageReader, UsageReaderFactory, UsageRecord } from \"./types.js\";\r\nimport { dedupe } from \"./aggregate.js\";\r\nimport { USAGE_READER_REGISTRY } from \"./registry.js\";\r\n\r\n/** A platform the scan could not (fully) read, with a human reason. */\r\nexport interface SkippedPlatform {\r\n platformId: PlatformId;\r\n reason: string;\r\n}\r\n\r\n/** Options controlling a scan. */\r\nexport interface ScanOptions {\r\n /** Lower-bound epoch ms; records older than this are dropped. */\r\n sinceMs?: number;\r\n /** Restrict to these platforms; omit/empty to scan every registered reader. */\r\n platforms?: PlatformId[];\r\n}\r\n\r\n/** The result of a scan: deduped records + notes on anything skipped. */\r\nexport interface ScanResult {\r\n records: UsageRecord[];\r\n skipped: SkippedPlatform[];\r\n}\r\n\r\n/**\r\n * Scan host usage across the selected readers. Returns deduped, since-filtered\r\n * records plus a `skipped` list (load/read failures and synced-but-uncached\r\n * platforms). Never throws — a single bad reader is isolated.\r\n */\r\nexport async function scanUsage(opts: ScanOptions = {}): Promise<ScanResult> {\r\n const { sinceMs, platforms } = opts;\r\n const wanted = platforms && platforms.length > 0 ? new Set(platforms) : undefined;\r\n\r\n const factories = USAGE_READER_REGISTRY.filter(\r\n (f) => wanted === undefined || wanted.has(f.platformId),\r\n );\r\n\r\n const collected: UsageRecord[] = [];\r\n const skipped: SkippedPlatform[] = [];\r\n\r\n // Run readers concurrently; each result is independent.\r\n const results = await Promise.all(\r\n factories.map(async (factory) => readOne(factory, sinceMs)),\r\n );\r\n\r\n for (const r of results) {\r\n if (r.skipped) skipped.push(r.skipped);\r\n // Loop-push, never push(...spread): a reader over a large host history can\r\n // return hundreds of thousands of records, and spreading them as call\r\n // arguments overflows the stack (RangeError) — hit on a real machine the\r\n // first time the claude-code reader saw a multi-week log directory.\r\n for (const rec of r.records) collected.push(rec);\r\n }\r\n\r\n const deduped = dedupe(collected);\r\n const filtered =\r\n sinceMs === undefined ? deduped : deduped.filter((rec) => rec.ts >= sinceMs);\r\n\r\n return { records: filtered, skipped };\r\n}\r\n\r\n/** Load + run a single reader, isolating any failure into a skip note. */\r\nasync function readOne(\r\n factory: UsageReaderFactory,\r\n sinceMs: number | undefined,\r\n): Promise<{ records: UsageRecord[]; skipped?: SkippedPlatform }> {\r\n let reader: UsageReader;\r\n try {\r\n reader = await factory.load();\r\n } catch (err) {\r\n return {\r\n records: [],\r\n skipped: { platformId: factory.platformId, reason: `failed to load reader: ${errMsg(err)}` },\r\n };\r\n }\r\n\r\n let records: UsageRecord[];\r\n try {\r\n records = await reader.read(sinceMs === undefined ? {} : { sinceMs });\r\n } catch (err) {\r\n return {\r\n records: [],\r\n skipped: { platformId: factory.platformId, reason: `read error: ${errMsg(err)}` },\r\n };\r\n }\r\n\r\n if (records.length === 0 && factory.kind === \"synced\") {\r\n return {\r\n records: [],\r\n skipped: {\r\n platformId: factory.platformId,\r\n reason: \"requires sync (no local cache found)\",\r\n },\r\n };\r\n }\r\n\r\n return { records };\r\n}\r\n\r\nfunction errMsg(err: unknown): string {\r\n return err instanceof Error ? err.message : String(err);\r\n}\r\n","/**\r\n * usage/leaderboard — the USER / HOST leaderboard, derived from the host usage\r\n * readers (src/usage/*).\r\n *\r\n * Where {@link import(\"../telemetry/leaderboard.js\")} answers \"which MCP server\r\n * costs the most\" from the bytes WE wrap, this answers \"which CLI / host spent\r\n * the most\" from each agent's OWN native session logs. Origin is always\r\n * `host-native`; it is NEVER summed with the serve-proxy MCP leaderboard (they\r\n * measure different things: server bytes vs whole-conversation usage).\r\n *\r\n * Thin wrapper over {@link scanUsage} + {@link aggregateBy}: the ranking is just\r\n * the platform (or model) group-by, which `aggregateBy` already sorts by total\r\n * tokens desc. A dedicated formatter notes synced / host-estimated platforms.\r\n */\r\n\r\nimport type { SkippedPlatform } from \"./scan.js\";\r\nimport type { PlatformId } from \"../core/types.js\";\r\nimport type { UsageRecord, UsageSummary } from \"./types.js\";\r\nimport { aggregateBy } from \"./aggregate.js\";\r\nimport { scanUsage } from \"./scan.js\";\r\n\r\n/** Options for the host leaderboard queries. */\r\nexport interface HostLeaderboardOptions {\r\n /** Lower-bound epoch ms (inclusive); forwarded to {@link scanUsage}. */\r\n sinceMs?: number;\r\n /** Restrict to these platforms; omit/empty to scan every registered reader. */\r\n platforms?: PlatformId[];\r\n /** Rank dimension. \"platform\" (default) is the headline host leaderboard. */\r\n by?: \"platform\" | \"model\";\r\n}\r\n\r\n/** The host leaderboard result: ranked rows plus any honest skip notes. */\r\nexport interface HostLeaderboardResult {\r\n /** The ranking dimension actually used. */\r\n by: \"platform\" | \"model\";\r\n /** Ranked summary rows (sorted by total tokens desc by aggregateBy). */\r\n rows: UsageSummary[];\r\n /** Platforms the scan could not (fully) read (synced-but-uncached, errors). */\r\n skipped: SkippedPlatform[];\r\n}\r\n\r\n/**\r\n * The USER / HOST leaderboard: scan every host reader, then rank by platform\r\n * (the default — \"which CLI/host spent the most\") or by model. Returns the\r\n * ranked rows and the scan's skip notes so the formatter can stay honest about\r\n * cloud platforms that require a sync we do not perform.\r\n */\r\nexport async function hostLeaderboard(\r\n opts: HostLeaderboardOptions = {},\r\n): Promise<HostLeaderboardResult> {\r\n const by = opts.by ?? \"platform\";\r\n const scanOpts: { sinceMs?: number; platforms?: PlatformId[] } = {};\r\n if (opts.sinceMs !== undefined) scanOpts.sinceMs = opts.sinceMs;\r\n if (opts.platforms !== undefined && opts.platforms.length > 0) {\r\n scanOpts.platforms = opts.platforms;\r\n }\r\n const { records, skipped } = await scanUsage(scanOpts);\r\n const rows = aggregateBy(records, by);\r\n return { by, rows, skipped };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Formatting (mirrors usage/report.ts style: aligned table + honesty legend)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Compact integer formatting with thousands separators. */\r\nfunction fmtInt(n: number): string {\r\n return n.toLocaleString(\"en-US\");\r\n}\r\n\r\n/** Right-pad (left-aligned columns). */\r\nfunction padRight(s: string, width: number): string {\r\n return s.length >= width ? s : s + \" \".repeat(width - s.length);\r\n}\r\n\r\n/** Left-pad (right-aligned numeric columns). */\r\nfunction padLeft(s: string, width: number): string {\r\n return s.length >= width ? s : \" \".repeat(width - s.length) + s;\r\n}\r\n\r\n/**\r\n * Format the host leaderboard as an aligned, ranked table:\r\n * RANK | PLATFORM|MODEL | IN | OUT | CACHE_R | CACHE_W | REASON | TOTAL | SESS | CONF\r\n * with a TOTAL footer (worst confidence across rows), an estimate legend, and\r\n * skip notes for synced-but-uncached platforms.\r\n */\r\nexport function formatHostLeaderboard(\r\n result: HostLeaderboardResult,\r\n): string {\r\n const keyHeader = result.by === \"model\" ? \"MODEL\" : \"PLATFORM\";\r\n const headers = [\r\n \"RANK\",\r\n keyHeader,\r\n \"IN\",\r\n \"OUT\",\r\n \"CACHE_R\",\r\n \"CACHE_W\",\r\n \"REASON\",\r\n \"TOTAL\",\r\n \"SESS\",\r\n \"CONF\",\r\n ];\r\n\r\n // aggregateBy already sorts by total desc; re-sort defensively for stability.\r\n const sorted = [...result.rows].sort(\r\n (a, b) => b.total - a.total || b.lastTs - a.lastTs,\r\n );\r\n\r\n const dataRows = sorted.map((r, i) => [\r\n `${i + 1}`,\r\n r.key,\r\n fmtInt(r.tokens.input),\r\n fmtInt(r.tokens.output),\r\n fmtInt(r.tokens.cacheRead),\r\n fmtInt(r.tokens.cacheWrite),\r\n fmtInt(r.tokens.reasoning),\r\n fmtInt(r.total),\r\n fmtInt(r.sessions),\r\n r.confidence,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.input += r.tokens.input;\r\n acc.output += r.tokens.output;\r\n acc.cacheRead += r.tokens.cacheRead;\r\n acc.cacheWrite += r.tokens.cacheWrite;\r\n acc.reasoning += r.tokens.reasoning;\r\n acc.total += r.total;\r\n acc.sessions += r.sessions;\r\n return acc;\r\n },\r\n { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0, total: 0, sessions: 0 },\r\n );\r\n const totalRow = [\r\n \"\",\r\n \"TOTAL\",\r\n fmtInt(totals.input),\r\n fmtInt(totals.output),\r\n fmtInt(totals.cacheRead),\r\n fmtInt(totals.cacheWrite),\r\n fmtInt(totals.reasoning),\r\n fmtInt(totals.total),\r\n fmtInt(totals.sessions),\r\n \"\",\r\n ];\r\n\r\n const widths = headers.map((h, col) => {\r\n let w = h.length;\r\n for (const row of dataRows) w = Math.max(w, (row[col] ?? \"\").length);\r\n w = Math.max(w, (totalRow[col] ?? \"\").length);\r\n return w;\r\n });\r\n\r\n // Left-align RANK (0), the KEY column (1), and CONF (9); numbers right.\r\n const leftCols = new Set<number>([0, 1, 9]);\r\n const renderRow = (cells: string[]): string =>\r\n cells\r\n .map((c, col) =>\r\n leftCols.has(col) ? padRight(c, widths[col] ?? 0) : padLeft(c, widths[col] ?? 0),\r\n )\r\n .join(\" \")\r\n .trimEnd();\r\n\r\n const ruleWidth = widths.reduce((a, b) => a + b, 0) + 2 * (widths.length - 1);\r\n const rule = \"-\".repeat(ruleWidth);\r\n\r\n const lines: string[] = [];\r\n lines.push(renderRow(headers));\r\n lines.push(rule);\r\n if (dataRows.length === 0) {\r\n lines.push(\"(no host usage found)\");\r\n } else {\r\n for (const row of dataRows) lines.push(renderRow(row));\r\n }\r\n lines.push(rule);\r\n lines.push(renderRow(totalRow));\r\n\r\n // Honesty legend — estimated rows and skipped synced platforms.\r\n if (sorted.some((r) => r.confidence === \"host-estimated\")) {\r\n lines.push(\"\");\r\n lines.push(\r\n \"note: host-estimated rows are derived (e.g. char/4 or cost-only), \" +\r\n \"not exact host-reported token counts.\",\r\n );\r\n }\r\n if (result.skipped.length > 0) {\r\n lines.push(\"\");\r\n lines.push(\"skipped (synced/host-estimated platforms):\");\r\n for (const s of result.skipped) lines.push(` - ${s.platformId}: ${s.reason}`);\r\n }\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n"],"mappings":"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","names":[]}
@@ -340,4 +340,4 @@ export {
340
340
  dedupe,
341
341
  aggregateBy
342
342
  };
343
- //# sourceMappingURL=chunk-XD7MY6HB.js.map
343
+ //# sourceMappingURL=chunk-7PSNXUFK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/normalize.ts","../src/usage/aggregate.ts"],"sourcesContent":["/**\r\n * usage/normalize — model/provider/workspace normalization.\r\n *\r\n * `normalizeModelForGrouping` and `inferProvider` are FAITHFUL ports of\r\n * tokscale's order-dependent logic (tokscale-core/src/lib.rs\r\n * normalize_model_for_grouping + provider_identity.rs inferred_provider_from_model).\r\n * The matching order is load-bearing — keep the steps in sequence.\r\n *\r\n * `normalizeWorkspaceKey` / `workspaceLabelFromKey` port tokscale\r\n * sessions/mod.rs (same slash-collapsing + UNC-prefix handling) so a cwd string\r\n * from a host log maps to the same stable project key tokscale would produce.\r\n */\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Model normalization (port of lib.rs normalize_model_for_grouping)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nconst REASONING_TIERS: ReadonlySet<string> = new Set([\r\n \"minimal\",\r\n \"low\",\r\n \"medium\",\r\n \"high\",\r\n \"xhigh\",\r\n \"auto\",\r\n \"none\",\r\n]);\r\n\r\n/**\r\n * Strip a `(level)` reasoning-effort suffix, returning the base model — or null\r\n * when the suffix is not one of the recognized tiers. Port of\r\n * strip_parenthesized_reasoning_tier: the base must be non-empty and already\r\n * trimmed (no surrounding whitespace).\r\n */\r\nfunction stripParenthesizedReasoningTier(modelId: string): string | null {\r\n if (!modelId.endsWith(\")\")) return null;\r\n const withoutClosing = modelId.slice(0, -1);\r\n const open = withoutClosing.lastIndexOf(\"(\");\r\n if (open < 0) return null;\r\n const base = withoutClosing.slice(0, open);\r\n const tier = withoutClosing.slice(open + 1);\r\n if (base === \"\" || base.trim() !== base) return null;\r\n if (!REASONING_TIERS.has(tier)) return null;\r\n return base;\r\n}\r\n\r\n/**\r\n * Map an `anthropic/claude-<major>-<minor>-<family>` id to the canonical\r\n * `claude-<family>-<major>-<minor>` form. Returns null when the shape does not\r\n * match exactly (too many parts, unknown family). Port of\r\n * normalize_anthropic_prefixed_claude_model.\r\n */\r\nfunction normalizeAnthropicPrefixedClaudeModel(modelId: string): string | null {\r\n const prefix = \"anthropic/claude-\";\r\n if (!modelId.startsWith(prefix)) return null;\r\n const rest = modelId.slice(prefix.length);\r\n const parts = rest.split(\"-\");\r\n const major = parts[0];\r\n const minor = parts[1];\r\n const family = parts[2];\r\n if (major === undefined || minor === undefined || family === undefined) return null;\r\n if (parts.length > 3) return null; // too many parts\r\n if (family !== \"opus\" && family !== \"sonnet\" && family !== \"haiku\") return null;\r\n return `claude-${family}-${major}-${minor}`;\r\n}\r\n\r\n/**\r\n * Normalize a raw model id to a stable grouping key. ORDER MATTERS — this is the\r\n * exact tokscale sequence:\r\n * 1. lowercase;\r\n * 2. strip a recognized `(tier)` reasoning suffix;\r\n * 3. strip a trailing `-YYYYMMDD` 8-digit date (only when len > 9 and the\r\n * 9th-from-end char is '-');\r\n * 4. for claude ids, replace dots between two digits with dashes\r\n * (e.g. \"claude-3.5-sonnet\" → \"claude-3-5-sonnet\");\r\n * 5. canonicalize an `anthropic/claude-*` prefix.\r\n */\r\nexport function normalizeModelForGrouping(modelId: string): string {\r\n let name = modelId.toLowerCase();\r\n\r\n const base = stripParenthesizedReasoningTier(name);\r\n if (base !== null) name = base;\r\n\r\n if (name.length > 9) {\r\n const potentialDate = name.slice(name.length - 8);\r\n const allDigits = /^[0-9]{8}$/.test(potentialDate);\r\n if (allDigits && name.charCodeAt(name.length - 9) === 0x2d /* '-' */) {\r\n name = name.slice(0, name.length - 9);\r\n }\r\n }\r\n\r\n if (name.includes(\"claude\")) {\r\n const chars = [...name];\r\n let result = \"\";\r\n for (let i = 0; i < chars.length; i++) {\r\n const c = chars[i] as string;\r\n const prev = chars[i - 1];\r\n const next = chars[i + 1];\r\n if (\r\n c === \".\" &&\r\n i > 0 &&\r\n i < chars.length - 1 &&\r\n prev !== undefined &&\r\n next !== undefined &&\r\n isAsciiDigit(prev) &&\r\n isAsciiDigit(next)\r\n ) {\r\n result += \"-\";\r\n } else {\r\n result += c;\r\n }\r\n }\r\n name = result;\r\n }\r\n\r\n const canonical = normalizeAnthropicPrefixedClaudeModel(name);\r\n if (canonical !== null) name = canonical;\r\n\r\n return name;\r\n}\r\n\r\nfunction isAsciiDigit(c: string): boolean {\r\n return c >= \"0\" && c <= \"9\";\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Provider inference (port of provider_identity.rs inferred_provider_from_model)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Whether `needle` occurs in `haystack` not flanked by alphanumerics on either\r\n * side (so \"o1\" matches \"o1-preview\" but not \"protocol1\"). Port of\r\n * contains_delimited.\r\n */\r\nfunction containsDelimited(haystack: string, needle: string): boolean {\r\n let from = 0;\r\n for (;;) {\r\n const pos = haystack.indexOf(needle, from);\r\n if (pos < 0) return false;\r\n const beforeOk = pos === 0 || !isAlphaNum(haystack.charCodeAt(pos - 1));\r\n const afterPos = pos + needle.length;\r\n const afterOk = afterPos === haystack.length || !isAlphaNum(haystack.charCodeAt(afterPos));\r\n if (beforeOk && afterOk) return true;\r\n from = pos + 1;\r\n }\r\n}\r\n\r\nfunction isAlphaNum(code: number): boolean {\r\n return (\r\n (code >= 0x30 && code <= 0x39) || // 0-9\r\n (code >= 0x41 && code <= 0x5a) || // A-Z\r\n (code >= 0x61 && code <= 0x7a) // a-z\r\n );\r\n}\r\n\r\n/**\r\n * Infer a canonical provider id from a model id. ORDER MATTERS — first match\r\n * wins, exactly as tokscale's inferred_provider_from_model. Returns null when no\r\n * family matches (caller supplies a platform default).\r\n */\r\nexport function inferProvider(model: string): string | null {\r\n const lower = model.toLowerCase();\r\n\r\n if (\r\n lower.includes(\"claude\") ||\r\n lower.includes(\"anthropic\") ||\r\n containsDelimited(lower, \"opus\") ||\r\n containsDelimited(lower, \"sonnet\") ||\r\n containsDelimited(lower, \"haiku\")\r\n ) {\r\n return \"anthropic\";\r\n }\r\n if (\r\n lower.includes(\"gpt\") ||\r\n lower.includes(\"openai\") ||\r\n containsDelimited(lower, \"o1\") ||\r\n containsDelimited(lower, \"o3\") ||\r\n containsDelimited(lower, \"o4\")\r\n ) {\r\n return \"openai\";\r\n }\r\n if (lower.includes(\"gemini\") || lower.includes(\"google\")) return \"google\";\r\n if (lower.includes(\"grok\")) return \"xai\";\r\n if (lower.includes(\"deepseek\")) return \"deepseek\";\r\n if (lower.includes(\"minimax\")) return \"minimax\";\r\n if (lower.includes(\"mistral\") || lower.includes(\"mixtral\")) return \"mistral\";\r\n if (lower.includes(\"llama\") || containsDelimited(lower, \"meta\")) return \"meta\";\r\n if (lower.includes(\"qwen\")) return \"qwen\";\r\n return null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Agent-name normalization (port of sessions/mod.rs normalize_agent_name +\r\n// normalize_opencode_agent_name). The opencode reader MUST normalize the agent\r\n// before its dedup fingerprint, or fork-copied history (which differs only in a\r\n// raw agent string) escapes dedup and double-counts.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n// U+200B ZWSP, U+200C ZWNJ, U+200D ZWJ, U+FEFF BOM/ZWNBSP.\r\nconst ZERO_WIDTH_RE = /[​‌‍]/g;\r\n\r\n/** Strip zero-width chars oh-my-openagent uses as invisible sort prefixes. */\r\nfunction stripZeroWidthChars(s: string): string {\r\n ZERO_WIDTH_RE.lastIndex = 0;\r\n return ZERO_WIDTH_RE.test(s) ? s.replace(ZERO_WIDTH_RE, \"\") : s;\r\n}\r\n\r\nconst AGENT_PREFIXES = [\"astrape:\", \"oh-my-claudecode:\", \"oh-my-codex:\"] as const;\r\n\r\n/** Strip a known namespace prefix (case-insensitive), else return as-is. */\r\nfunction stripAgentPrefix(name: string): string {\r\n for (const prefix of AGENT_PREFIXES) {\r\n if (name.length >= prefix.length && name.slice(0, prefix.length).toLowerCase() === prefix) {\r\n return name.slice(prefix.length);\r\n }\r\n }\r\n return name;\r\n}\r\n\r\n/** Collapse internal whitespace runs to single spaces (port of canonicalize_agent_name). */\r\nfunction canonicalizeAgentName(name: string): string {\r\n return name.split(/\\s+/).filter((w) => w !== \"\").join(\" \");\r\n}\r\n\r\n/** Titlecase one word, with UI/UX/API kept uppercase (port of titlecase_word). */\r\nfunction titlecaseWord(word: string): string {\r\n const lower = word.toLowerCase();\r\n if (lower === \"ui\") return \"UI\";\r\n if (lower === \"ux\") return \"UX\";\r\n if (lower === \"api\") return \"API\";\r\n if (word === \"\") return \"\";\r\n const chars = [...word];\r\n const first = chars[0] as string;\r\n return first.toUpperCase() + chars.slice(1).join(\"\");\r\n}\r\n\r\n/** Titlecase an agent name across '-' and whitespace boundaries (port of titlecase_agent). */\r\nfunction titlecaseAgent(name: string): string {\r\n if (name === \"\") return \"\";\r\n return name\r\n .split(\"-\")\r\n .flatMap((part) => part.split(/\\s+/))\r\n .filter((w) => w !== \"\")\r\n .map(titlecaseWord)\r\n .join(\" \");\r\n}\r\n\r\n/** Port of normalize_agent_name. */\r\nexport function normalizeAgentName(agent: string): string {\r\n const cleaned = stripZeroWidthChars(agent);\r\n const trimmed = cleaned.trim();\r\n const stripped = stripAgentPrefix(trimmed);\r\n const canonical = canonicalizeAgentName(stripped);\r\n const agentLower = canonical.toLowerCase();\r\n\r\n if (agentLower.includes(\"plan\")) {\r\n if (agentLower.includes(\"omo\") || agentLower.includes(\"sisyphus\")) {\r\n return \"Planner-Sisyphus\";\r\n }\r\n return titlecaseAgent(canonical);\r\n }\r\n if (agentLower === \"omo\" || agentLower === \"sisyphus\") return \"Sisyphus\";\r\n if (agentLower === \"orchestrator-sisyphus\") return \"Atlas\";\r\n return titlecaseAgent(canonical);\r\n}\r\n\r\n/** Port of normalize_oh_my_opencode_agent_name (returns undefined when no match). */\r\nfunction normalizeOhMyOpencodeAgentName(agentLower: string): string | undefined {\r\n switch (agentLower) {\r\n case \"sisyphus (ultraworker)\":\r\n case \"sisyphus - ultraworker\":\r\n case \"sisyphus ultraworker\":\r\n case \"sisyphus\":\r\n return \"Sisyphus\";\r\n case \"hephaestus (deep agent)\":\r\n case \"hephaestus - deep agent\":\r\n case \"hephaestus deep agent\":\r\n case \"hephaestus\":\r\n return \"Hephaestus\";\r\n case \"prometheus (plan builder)\":\r\n case \"prometheus - plan builder\":\r\n case \"prometheus plan builder\":\r\n case \"prometheus (planner)\":\r\n case \"prometheus\":\r\n return \"Prometheus\";\r\n case \"atlas (plan executor)\":\r\n case \"atlas - plan executor\":\r\n case \"atlas plan executor\":\r\n case \"atlas\":\r\n return \"Atlas\";\r\n case \"metis (plan consultant)\":\r\n case \"metis - plan consultant\":\r\n case \"metis plan consultant\":\r\n case \"metis\":\r\n return \"Metis\";\r\n case \"momus (plan critic)\":\r\n case \"momus - plan critic\":\r\n case \"momus plan critic\":\r\n case \"momus (plan reviewer)\":\r\n case \"momus\":\r\n return \"Momus\";\r\n case \"orchestrator-sisyphus\":\r\n return \"Atlas\";\r\n case \"sisyphus-junior\":\r\n return \"Sisyphus-Junior\";\r\n case \"planner-sisyphus\":\r\n return \"Planner-Sisyphus\";\r\n default:\r\n return undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Port of normalize_opencode_agent_name (sessions/mod.rs:88-154). Applies the\r\n * shared cleaning pipeline, then the oh-my-opencode agent table, then falls back\r\n * to normalizeAgentName. Used by the opencode reader BEFORE its dedup fingerprint\r\n * so fork copies collapse (matching opencode.rs:272).\r\n */\r\nexport function normalizeOpencodeAgentName(agent: string): string {\r\n const cleaned = stripZeroWidthChars(agent);\r\n const trimmed = cleaned.trim();\r\n const stripped = stripAgentPrefix(trimmed);\r\n const canonical = canonicalizeAgentName(stripped);\r\n const agentLower = canonical.toLowerCase();\r\n\r\n const ohMy = normalizeOhMyOpencodeAgentName(agentLower);\r\n if (ohMy !== undefined) return ohMy;\r\n\r\n return normalizeAgentName(canonical);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Workspace key / label (port of sessions/mod.rs)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Normalize an arbitrary cwd/dir string to a stable workspace key. Port of\r\n * normalize_workspace_key: backslashes → forward slashes, collapse repeated\r\n * slashes, strip a trailing slash (preserving a leading `//` UNC prefix).\r\n * Returns undefined for an empty input.\r\n */\r\nexport function normalizeWorkspaceKey(raw: string): string | undefined {\r\n const trimmed = raw.trim();\r\n if (trimmed === \"\") return undefined;\r\n\r\n const preserveUnc = trimmed.startsWith(\"\\\\\\\\\") || trimmed.startsWith(\"//\");\r\n let normalized = trimmed.replace(/\\\\/g, \"/\");\r\n\r\n if (preserveUnc) {\r\n let body = normalized.replace(/^\\/+/, \"\");\r\n while (body.includes(\"//\")) body = body.replace(/\\/\\//g, \"/\");\r\n normalized = `//${body}`;\r\n } else {\r\n while (normalized.includes(\"//\")) normalized = normalized.replace(/\\/\\//g, \"/\");\r\n }\r\n\r\n const minLen = preserveUnc ? 2 : 1;\r\n if (normalized.length > minLen) {\r\n normalized = normalized.replace(/\\/+$/, \"\");\r\n }\r\n\r\n return normalized === \"\" ? undefined : normalized;\r\n}\r\n\r\n/**\r\n * Human-readable label from a workspace key: the last non-empty path segment.\r\n * Port of workspace_label_from_key. Returns undefined when no segment remains.\r\n */\r\nexport function workspaceLabelFromKey(key: string): string | undefined {\r\n const segments = key.split(\"/\");\r\n for (let i = segments.length - 1; i >= 0; i--) {\r\n const seg = segments[i];\r\n if (seg !== undefined && seg !== \"\") return seg;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Convert a cwd/dir string to both its normalized key and label in one call.\r\n * Both fields are undefined when the input does not yield a usable key.\r\n */\r\nexport function workspaceFromPath(raw: string): {\r\n projectKey?: string;\r\n projectLabel?: string;\r\n} {\r\n const key = normalizeWorkspaceKey(raw);\r\n if (key === undefined) return {};\r\n const label = workspaceLabelFromKey(key);\r\n return label === undefined ? { projectKey: key } : { projectKey: key, projectLabel: label };\r\n}\r\n","/**\r\n * usage/aggregate — token math, cross-source de-dup, and group-by rollups.\r\n *\r\n * Ports tokscale's shared aggregation model (docs/research/usage-shared-model.md\r\n * §4–5): a TokenBreakdown total is the sum of all five dimensions; dedup keeps\r\n * the FIRST occurrence per dedupKey in insertion order (un-keyed records always\r\n * pass through); group-by folds records into UsageSummary rows summing tokens /\r\n * cost / messages, counting distinct sessions, tracking the worst confidence and\r\n * the latest timestamp, sorted by total desc.\r\n */\r\n\r\nimport type {\r\n TokenBreakdown,\r\n UsageConfidence,\r\n UsageGroupBy,\r\n UsageRecord,\r\n UsageSummary,\r\n} from \"./types.js\";\r\nimport { normalizeModelForGrouping } from \"./normalize.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Token helpers\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** A fresh all-zero TokenBreakdown. */\r\nexport function emptyTokens(): TokenBreakdown {\r\n return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, reasoning: 0 };\r\n}\r\n\r\n/** Element-wise sum of two breakdowns into a NEW object (operands untouched). */\r\nexport function addTokens(a: TokenBreakdown, b: TokenBreakdown): TokenBreakdown {\r\n return {\r\n input: a.input + b.input,\r\n output: a.output + b.output,\r\n cacheRead: a.cacheRead + b.cacheRead,\r\n cacheWrite: a.cacheWrite + b.cacheWrite,\r\n reasoning: a.reasoning + b.reasoning,\r\n };\r\n}\r\n\r\n/** Scalar total across all five token dimensions. */\r\nexport function sumTokens(t: TokenBreakdown): number {\r\n return t.input + t.output + t.cacheRead + t.cacheWrite + t.reasoning;\r\n}\r\n\r\n/** Accumulate `b` into `a` in place (used inside the rollup fold). */\r\nfunction addTokensInPlace(a: TokenBreakdown, b: TokenBreakdown): void {\r\n a.input += b.input;\r\n a.output += b.output;\r\n a.cacheRead += b.cacheRead;\r\n a.cacheWrite += b.cacheWrite;\r\n a.reasoning += b.reasoning;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Confidence\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Least-trustworthy (0) → most-trustworthy. host-estimated is the weaker. */\r\nconst CONFIDENCE_RANK: Record<UsageConfidence, number> = {\r\n \"host-estimated\": 0,\r\n \"host-reported\": 1,\r\n};\r\n\r\n/** The worse (least-confident) of two provenance labels. */\r\nexport function worstConfidence(a: UsageConfidence, b: UsageConfidence): UsageConfidence {\r\n return CONFIDENCE_RANK[b] < CONFIDENCE_RANK[a] ? b : a;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// De-duplication\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Cross-source de-dup. Keep the FIRST record seen per `dedupKey` in insertion\r\n * order; records without a dedupKey always pass through (the per-reader dedup is\r\n * the real safeguard — this is the global backstop, per shared-model §5 and\r\n * design §6). Deterministic: same input order → same output.\r\n */\r\nexport function dedupe(records: UsageRecord[]): UsageRecord[] {\r\n const seen = new Set<string>();\r\n const out: UsageRecord[] = [];\r\n for (const rec of records) {\r\n const key = rec.dedupKey;\r\n if (key === undefined || key === \"\") {\r\n out.push(rec); // un-keyed → always include\r\n continue;\r\n }\r\n if (!seen.has(key)) {\r\n seen.add(key);\r\n out.push(rec);\r\n }\r\n // duplicate key → drop (keep-first)\r\n }\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Group-by aggregation\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Local YYYY-MM-DD for an epoch-ms timestamp (matches tokscale's local-tz date). */\r\nfunction localDay(ts: number): string {\r\n const d = new Date(ts);\r\n const y = d.getFullYear();\r\n const m = `${d.getMonth() + 1}`.padStart(2, \"0\");\r\n const day = `${d.getDate()}`.padStart(2, \"0\");\r\n return `${y}-${m}-${day}`;\r\n}\r\n\r\n/** The grouping key value for a record under the requested dimension. */\r\nfunction groupKey(rec: UsageRecord, by: UsageGroupBy): string {\r\n switch (by) {\r\n case \"platform\":\r\n return rec.platformId;\r\n case \"project\":\r\n return rec.projectLabel ?? rec.projectKey ?? \"(no project)\";\r\n case \"session\":\r\n return rec.sessionId;\r\n case \"model\":\r\n return normalizeModelForGrouping(rec.modelId);\r\n case \"day\":\r\n return localDay(rec.ts);\r\n }\r\n}\r\n\r\ninterface MutableSummary extends UsageSummary {\r\n /** Distinct session ids folded into this group (counted at finalization). */\r\n _sessions: Set<string>;\r\n}\r\n\r\n/**\r\n * Roll records up into {@link UsageSummary} rows by the chosen dimension. Tokens,\r\n * cost, and message counts sum; `sessions` counts distinct session ids; the row\r\n * carries the worst confidence and the latest timestamp seen. Sorted by total\r\n * tokens descending (ties broken by recency).\r\n */\r\nexport function aggregateBy(records: UsageRecord[], by: UsageGroupBy): UsageSummary[] {\r\n const groups = new Map<string, MutableSummary>();\r\n\r\n for (const rec of records) {\r\n const key = groupKey(rec, by);\r\n let g = groups.get(key);\r\n if (g === undefined) {\r\n g = {\r\n key,\r\n tokens: emptyTokens(),\r\n total: 0,\r\n sessions: 0,\r\n messages: 0,\r\n confidence: rec.confidence,\r\n lastTs: rec.ts,\r\n _sessions: new Set<string>(),\r\n };\r\n groups.set(key, g);\r\n }\r\n\r\n addTokensInPlace(g.tokens, rec.tokens);\r\n g.messages += rec.messageCount;\r\n g._sessions.add(rec.sessionId);\r\n g.confidence = worstConfidence(g.confidence, rec.confidence);\r\n if (rec.ts > g.lastTs) g.lastTs = rec.ts;\r\n if (rec.cost !== undefined) g.cost = (g.cost ?? 0) + rec.cost;\r\n }\r\n\r\n const rows: UsageSummary[] = [];\r\n for (const g of groups.values()) {\r\n const { _sessions, ...summary } = g;\r\n summary.total = sumTokens(summary.tokens);\r\n summary.sessions = _sessions.size;\r\n rows.push(summary);\r\n }\r\n\r\n rows.sort((a, b) => b.total - a.total || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REGISTERED_PLATFORM_IDS
4
- } from "./chunk-D4ELPBB5.js";
4
+ } from "./chunk-NDMNMAKP.js";
5
5
  import {
6
6
  CONFIG_PATCH_SEGMENT_RE,
7
7
  configPatchNamespaceViolation,
8
8
  isJsonValue,
9
9
  isValidConfigPatchKey
10
- } from "./chunk-NBYKLUF6.js";
10
+ } from "./chunk-KFPSJRHR.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-UMQ6NBQR.js";
15
+ } from "./chunk-ILWHLGIC.js";
16
16
  import {
17
17
  CONNECTOR_ID_RE,
18
18
  isValidConnectorId
19
- } from "./chunk-GZGLCCEE.js";
19
+ } from "./chunk-QYOUQCC6.js";
20
20
 
21
21
  // src/core/package-metadata.ts
22
22
  import { AsyncLocalStorage } from "async_hooks";
@@ -643,6 +643,8 @@ function normalizeServer(server) {
643
643
 
644
644
  export {
645
645
  withConnectorPackageMetadata,
646
+ findNearestPackageJson,
647
+ readConnectorPackageMetadataFromPackageJson,
646
648
  readConnectorPackageMetadataNearFile,
647
649
  deriveHostAliasFromPackageName,
648
650
  deriveHostAliasFromMcpName,
@@ -668,4 +670,4 @@ export {
668
670
  defineConfigPatch,
669
671
  defineNativeHook
670
672
  };
671
- //# sourceMappingURL=chunk-5IOTP7LQ.js.map
673
+ //# sourceMappingURL=chunk-7ZFK2WEO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/package-metadata.ts","../src/core/define-connector.ts","../src/core/mcp-standard.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { dirname, join, resolve } from \"node:path\";\r\n\r\nimport type {\r\n McpPackageIdentity,\r\n ResolvedMcpPackageIdentity,\r\n ServerDef,\r\n} from \"./types.js\";\r\n\r\nconst GENERIC_PACKAGE_BASENAMES = new Set([\r\n \"mcp\",\r\n \"server\",\r\n \"mcp-server\",\r\n \"connector\",\r\n \"tool\",\r\n \"tools\",\r\n \"cli\",\r\n]);\r\n\r\nexport interface ConnectorPackageMetadata {\r\n /** Package-derived MCP identity used to derive host aliases and install ids. */\r\n mcp?: McpPackageIdentity;\r\n /** package.json version used as the connector version default. */\r\n version?: string;\r\n}\r\n\r\nconst PACKAGE_METADATA_CONTEXT = new AsyncLocalStorage<ConnectorPackageMetadata>();\r\n\r\nfunction kebab(raw: string): string {\r\n return raw\r\n .trim()\r\n .replace(/^@/, \"\")\r\n .replace(/[\\\\/_.\\s]+/g, \"-\")\r\n .replace(/[^a-zA-Z0-9-]+/g, \"-\")\r\n .replace(/-{2,}/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\")\r\n .toLowerCase();\r\n}\r\n\r\nfunction scopedPackageParts(packageName: string): {\r\n scope?: string;\r\n basename: string;\r\n} {\r\n const raw = packageName.trim();\r\n if (raw.startsWith(\"@\")) {\r\n const [scope, basename] = raw.slice(1).split(\"/\");\r\n return { scope: scope ? kebab(scope) : undefined, basename: basename ?? \"\" };\r\n }\r\n return { basename: raw };\r\n}\r\n\r\nfunction cleanMcpBasename(raw: string): string {\r\n let name = kebab(raw);\r\n name = name.replace(/^mcp-server-/, \"\");\r\n name = name.replace(/^server-/, \"\");\r\n name = name.replace(/-mcp-server$/, \"\");\r\n name = name.replace(/-mcp$/, \"\");\r\n name = name.replace(/-server$/, \"\");\r\n return kebab(name);\r\n}\r\n\r\nfunction isGeneric(name: string | undefined): boolean {\r\n return !name || GENERIC_PACKAGE_BASENAMES.has(name);\r\n}\r\n\r\nfunction cleanString(value: unknown): string | undefined {\r\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\r\n}\r\n\r\nfunction objectKeys(value: unknown): string[] {\r\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\r\n return Object.keys(value).filter((key) => key.trim());\r\n}\r\n\r\nfunction packageBinName(bin: unknown, packageName: string | undefined): string | undefined {\r\n if (typeof bin === \"string\") {\r\n return packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\r\n }\r\n\r\n const keys = objectKeys(bin);\r\n if (keys.length === 0) return undefined;\r\n if (keys.length === 1) return keys[0];\r\n\r\n const packageAlias = packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\r\n if (packageAlias && keys.includes(packageAlias)) return packageAlias;\r\n\r\n const unscoped = packageName?.startsWith(\"@\") ? packageName.split(\"/\")[1] : packageName;\r\n const cleanUnscoped = unscoped ? cleanMcpBasename(unscoped) : undefined;\r\n if (cleanUnscoped && keys.includes(cleanUnscoped)) return cleanUnscoped;\r\n\r\n return undefined;\r\n}\r\n\r\nexport function currentMcpPackageIdentity(): McpPackageIdentity | undefined {\r\n return currentConnectorPackageMetadata()?.mcp;\r\n}\r\n\r\nexport function currentConnectorPackageMetadata():\r\n | ConnectorPackageMetadata\r\n | undefined {\r\n return PACKAGE_METADATA_CONTEXT.getStore();\r\n}\r\n\r\nexport async function withConnectorPackageMetadata<T>(\r\n metadata: ConnectorPackageMetadata | undefined,\r\n run: () => Promise<T>,\r\n): Promise<T> {\r\n if (!metadata || Object.keys(metadata).length === 0) return run();\r\n return PACKAGE_METADATA_CONTEXT.run(metadata, run);\r\n}\r\n\r\nexport async function withMcpPackageIdentity<T>(\r\n identity: McpPackageIdentity | undefined,\r\n run: () => Promise<T>,\r\n): Promise<T> {\r\n if (!identity || Object.keys(identity).length === 0) return run();\r\n return withConnectorPackageMetadata({ mcp: identity }, run);\r\n}\r\n\r\nexport function findNearestPackageJson(startDir: string): string | undefined {\r\n let dir = resolve(startDir);\r\n for (;;) {\r\n const candidate = join(dir, \"package.json\");\r\n if (existsSync(candidate)) return candidate;\r\n\r\n const parent = dirname(dir);\r\n if (parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n}\r\n\r\nexport function readMcpPackageIdentityFromPackageJson(\r\n packageJsonPath: string,\r\n): McpPackageIdentity {\r\n return readConnectorPackageMetadataFromPackageJson(packageJsonPath).mcp ?? {};\r\n}\r\n\r\nexport function readConnectorPackageMetadataFromPackageJson(\r\n packageJsonPath: string,\r\n): ConnectorPackageMetadata {\r\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\r\n name?: unknown;\r\n version?: unknown;\r\n mcpName?: unknown;\r\n mcp?: unknown;\r\n bin?: unknown;\r\n };\r\n const packageName = cleanString(parsed.name);\r\n const version = cleanString(parsed.version);\r\n const mcp =\r\n parsed.mcp && typeof parsed.mcp === \"object\" && !Array.isArray(parsed.mcp)\r\n ? (parsed.mcp as { name?: unknown; mcpName?: unknown })\r\n : undefined;\r\n const mcpName =\r\n cleanString(parsed.mcpName) ??\r\n cleanString(mcp?.mcpName) ??\r\n cleanString(mcp?.name);\r\n const bin = packageBinName(parsed.bin, packageName);\r\n\r\n const identity: McpPackageIdentity = {\r\n ...(packageName ? { packageName } : {}),\r\n ...(mcpName ? { mcpName } : {}),\r\n ...(bin ? { bin } : {}),\r\n };\r\n\r\n return {\r\n ...(Object.keys(identity).length > 0 ? { mcp: identity } : {}),\r\n ...(version ? { version } : {}),\r\n };\r\n}\r\n\r\nexport function readMcpPackageIdentityNearFile(\r\n filePath: string,\r\n): McpPackageIdentity | undefined {\r\n return readConnectorPackageMetadataNearFile(filePath)?.mcp;\r\n}\r\n\r\nexport function readConnectorPackageMetadataNearFile(\r\n filePath: string,\r\n): ConnectorPackageMetadata | undefined {\r\n const packageJsonPath = findNearestPackageJson(dirname(filePath));\r\n if (!packageJsonPath) return undefined;\r\n try {\r\n const metadata = readConnectorPackageMetadataFromPackageJson(packageJsonPath);\r\n return Object.keys(metadata).length > 0 ? metadata : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/** Derive the host-facing MCP server key from a package name. */\r\nexport function deriveHostAliasFromPackageName(\r\n packageName: string,\r\n): string | undefined {\r\n const { scope, basename } = scopedPackageParts(packageName);\r\n const fromBasename = cleanMcpBasename(basename);\r\n if (!isGeneric(fromBasename)) return fromBasename;\r\n const fromScope = scope ? cleanMcpBasename(scope) : undefined;\r\n return isGeneric(fromScope) ? undefined : fromScope;\r\n}\r\n\r\n/** Derive the host-facing MCP server key from an MCP registry name. */\r\nexport function deriveHostAliasFromMcpName(\r\n mcpName: string,\r\n): string | undefined {\r\n const [namespace, name] = mcpName.trim().split(\"/\");\r\n const fromName = cleanMcpBasename(name ?? namespace ?? \"\");\r\n if (!isGeneric(fromName)) return fromName;\r\n\r\n const namespaceParts = (namespace ?? \"\").split(\".\").filter(Boolean);\r\n const fromNamespace = cleanMcpBasename(namespaceParts.at(-1) ?? \"\");\r\n return isGeneric(fromNamespace) ? undefined : fromNamespace;\r\n}\r\n\r\n/** Infer an npm package from common npx-style stdio server definitions. */\r\nexport function inferNpmPackageFromServer(\r\n server: ServerDef | undefined,\r\n): string | undefined {\r\n if (!server || server.transport !== \"stdio\") return undefined;\r\n if (typeof server.command !== \"string\" || server.command.trim() === \"\") {\r\n return undefined;\r\n }\r\n const runner = kebab(server.command.split(/[\\\\/]/).pop() ?? server.command);\r\n if (![\"npx\", \"npm\", \"pnpm\", \"yarn\", \"bun\"].includes(runner)) return undefined;\r\n\r\n const args = server.args ?? [];\r\n for (let i = 0; i < args.length; i += 1) {\r\n const arg = args[i]!;\r\n if (arg === \"--\") continue;\r\n if (arg === \"exec\" || arg === \"dlx\" || arg === \"x\") continue;\r\n if (arg === \"-y\" || arg === \"--yes\" || arg === \"--no-install\") continue;\r\n if (arg === \"--package\" || arg === \"-p\") {\r\n i += 1;\r\n continue;\r\n }\r\n if (arg.startsWith(\"-\")) continue;\r\n return arg;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function resolveMcpPackageIdentity(input: {\r\n id?: string;\r\n mcp?: McpPackageIdentity;\r\n server?: ServerDef;\r\n}): ResolvedMcpPackageIdentity {\r\n const packageName =\r\n input.mcp?.packageName ?? inferNpmPackageFromServer(input.server);\r\n const hostAlias =\r\n input.mcp?.hostAlias ??\r\n (input.mcp?.mcpName\r\n ? deriveHostAliasFromMcpName(input.mcp.mcpName)\r\n : undefined) ??\r\n (packageName ? deriveHostAliasFromPackageName(packageName) : undefined) ??\r\n (input.mcp?.bin ? cleanMcpBasename(input.mcp.bin) : undefined);\r\n\r\n return {\r\n ...(packageName ? { packageName } : {}),\r\n ...(input.mcp?.mcpName ? { mcpName: input.mcp.mcpName } : {}),\r\n ...(input.mcp?.bin ? { bin: input.mcp.bin } : {}),\r\n ...(hostAlias ? { hostAlias } : {}),\r\n };\r\n}\r\n","/**\r\n * core/define-connector — the public write-once entry point.\r\n *\r\n * Validates a ConnectorConfig and normalizes it into a ResolvedConnector with\r\n * every optional field resolved to a default. Validation is intentionally\r\n * dependency-free (no zod) to keep the single-binary install lean.\r\n */\r\n\r\nimport { isAbsolute, normalize } from \"node:path\";\r\n\r\nimport type {\r\n ActionDef,\r\n CommandDef,\r\n ConfigPatchDef,\r\n ConnectorConfig,\r\n HookDefinition,\r\n HookEventName,\r\n HooksConfig,\r\n MemoryDef,\r\n NativeHookDef,\r\n PlatformId,\r\n PublishConfig,\r\n ResolvedConnector,\r\n SkillDef,\r\n StatuslineDef,\r\n SubagentDef,\r\n} from \"./types.js\";\r\nimport { REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\r\nimport { REGISTRY_NAMESPACE_RE } from \"./mcp-standard.js\";\r\nimport { CONNECTOR_ID_RE, isValidConnectorId } from \"./ids.js\";\r\nimport {\r\n currentConnectorPackageMetadata,\r\n resolveMcpPackageIdentity,\r\n} from \"./package-metadata.js\";\r\nimport {\r\n MANAGED_BLOCK_BEGIN_TOKEN,\r\n MANAGED_BLOCK_END_TOKEN,\r\n MEMORY_CONTENT_HARD_CAP_BYTES,\r\n} from \"./managed-block.js\";\r\nimport {\r\n CONFIG_PATCH_SEGMENT_RE,\r\n configPatchNamespaceViolation,\r\n isJsonValue,\r\n isValidConfigPatchKey,\r\n} from \"./config-patch-ledger.js\";\r\n\r\n/** kebab-case name regex shared by command/skill/subagent names. */\r\nconst SURFACE_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\r\n\r\n/** Max length of a skill description (Agent Skills open standard). */\r\nconst SKILL_DESCRIPTION_MAX = 1024;\r\n\r\n// NOTE: canonical ordering — append new events at the END (hookEvents ordering\r\n// is pinned by tests and feeds install-file ordering). Exported so the\r\n// hook-dispatch gate + Claude-bundle event sets can be drift-tested against it.\r\nexport const ALL_EVENTS: HookEventName[] = [\r\n \"SessionStart\",\r\n \"SessionEnd\",\r\n \"UserPromptSubmit\",\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"Stop\",\r\n \"Notification\",\r\n \"PermissionRequest\",\r\n \"PostToolUseFailure\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n \"PostCompact\",\r\n];\r\n\r\n/** Thrown on an invalid connector configuration. */\r\nexport class ConnectorConfigError extends Error {\r\n constructor(message: string) {\r\n super(`Invalid connector config: ${message}`);\r\n this.name = \"ConnectorConfigError\";\r\n }\r\n}\r\n\r\nfunction declaredEvents(hooks: HooksConfig | undefined): HookEventName[] {\r\n if (!hooks) return [];\r\n return ALL_EVENTS.filter((e) => typeof hooks[e]?.handler === \"function\");\r\n}\r\n\r\n/**\r\n * Validate + normalize a connector definition.\r\n * Returns a ResolvedConnector that adapters and the CLI consume directly.\r\n */\r\nexport function defineConnector(config: ConnectorConfig): ResolvedConnector {\r\n if (!config || typeof config !== \"object\") {\r\n throw new ConnectorConfigError(\"config must be an object\");\r\n }\r\n\r\n const packageMetadata = currentConnectorPackageMetadata();\r\n const packageIdentity = packageMetadata?.mcp;\r\n if (packageIdentity && Object.keys(packageIdentity).length > 0) {\r\n config = {\r\n ...config,\r\n mcp: {\r\n ...packageIdentity,\r\n ...config.mcp,\r\n },\r\n };\r\n }\r\n\r\n const mcpIdentity = resolveMcpPackageIdentity(config);\r\n const connectorId = config.id ?? mcpIdentity.hostAlias;\r\n if (!isValidConnectorId(connectorId)) {\r\n throw new ConnectorConfigError(\r\n `id must be kebab-case matching ${CONNECTOR_ID_RE} or derivable from mcp/package metadata (got ${JSON.stringify(config.id)})`,\r\n );\r\n }\r\n const hasCommands = Array.isArray(config.commands) && config.commands.length > 0;\r\n const hasSkills = Array.isArray(config.skills) && config.skills.length > 0;\r\n const hasSubagents = Array.isArray(config.subagents) && config.subagents.length > 0;\r\n const hasMemory = Array.isArray(config.memory) && config.memory.length > 0;\r\n // A statusline (a HUD) is a legitimate sole payload — a connector whose whole\r\n // job is rendering a status line. SINGULAR (one per connector), so a plain\r\n // presence check (object with a render handler — validated in normalizeStatusline).\r\n const hasStatusline = config.statusline != null;\r\n // Actions (each a user-invokable run handler) are a legitimate sole payload —\r\n // a connector whose whole job is shipping dispatchable actions.\r\n const hasActions = Array.isArray(config.actions) && config.actions.length > 0;\r\n // A platform-scoped nativeHooks declaration is a legitimate sole payload\r\n // (a hooks-only connector wired entirely through native passthrough events).\r\n const hasNativeHooks = Object.values(config.platforms ?? {}).some(\r\n (override) =>\r\n override?.nativeHooks != null && Object.keys(override.nativeHooks).length > 0,\r\n );\r\n // Likewise a platform-scoped configPatch declaration (a connector whose whole\r\n // job is asserting a host config key, e.g. an experimental feature flag).\r\n const hasConfigPatch = Object.values(config.platforms ?? {}).some(\r\n (override) => Array.isArray(override?.configPatch) && override.configPatch.length > 0,\r\n );\r\n if (\r\n !config.server &&\r\n !config.hooks &&\r\n !hasCommands &&\r\n !hasSkills &&\r\n !hasSubagents &&\r\n !hasMemory &&\r\n !hasStatusline &&\r\n !hasActions &&\r\n !hasNativeHooks &&\r\n !hasConfigPatch\r\n ) {\r\n throw new ConnectorConfigError(\r\n \"a connector must declare at least one of `server`, `hooks`, `commands`, `skills`, `subagents`, `memory`, `statusline`, `actions`, \" +\r\n \"or a per-platform `nativeHooks` / `configPatch` declaration\",\r\n );\r\n }\r\n\r\n if (config.server) {\r\n const s = config.server;\r\n if (s.transport === \"stdio\") {\r\n if (!s.command || typeof s.command !== \"string\") {\r\n throw new ConnectorConfigError(\r\n \"server.command is required for stdio transport\",\r\n );\r\n }\r\n } else {\r\n if (!s.url || typeof s.url !== \"string\") {\r\n throw new ConnectorConfigError(\r\n `server.url is required for ${s.transport} transport`,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Validate hook handlers are functions, plus any per-host override map.\r\n if (config.hooks) {\r\n for (const ev of ALL_EVENTS) {\r\n const def = config.hooks[ev];\r\n if (def != null && typeof def.handler !== \"function\") {\r\n throw new ConnectorConfigError(`hooks.${ev}.handler must be a function`);\r\n }\r\n // Per-host override map: every key must be a registered platform id and\r\n // every entry's handler a function (author-time hard error, not skip-warn).\r\n validateHostsMap(def?.hosts, `hooks.${ev}.hosts`, \"handler\");\r\n }\r\n }\r\n\r\n // Validate per-platform native passthrough hooks (handlers live in this same\r\n // config module, exactly like normalized hooks — the resolved connector keeps\r\n // `platforms` verbatim, so live handlers survive resolution and are recovered\r\n // at runtime by re-importing the module via the registry's modulePath).\r\n validateNativeHooks(config.platforms);\r\n\r\n // Validate per-platform declarative config patches (pure JSON — persisted\r\n // whole; semantics are FIXED set-if-absent/skip-warn, so only the shape is\r\n // validated here; the host adapter enforces its sensitive-key denylist).\r\n validateConfigPatches(config.platforms);\r\n\r\n const commands = normalizeCommands(config.commands);\r\n const skills = normalizeSkills(config.skills);\r\n const subagents = normalizeSubagents(config.subagents);\r\n const memory = normalizeMemory(config.memory);\r\n const statusline = normalizeStatusline(config.statusline);\r\n const actions = normalizeActions(config.actions);\r\n\r\n const t = config.telemetry ?? {};\r\n\r\n const resolved: ResolvedConnector = {\r\n id: connectorId,\r\n ...(Object.keys(mcpIdentity).length > 0 ? { mcp: mcpIdentity } : {}),\r\n displayName: config.displayName ?? connectorId,\r\n version: config.version ?? packageMetadata?.version ?? \"0.0.0\",\r\n ...(config.server ? { server: normalizeServer(config.server) } : {}),\r\n hooks: config.hooks ?? {},\r\n hookEvents: declaredEvents(config.hooks),\r\n telemetry: {\r\n enabled: t.enabled ?? true,\r\n modelFamilyHint: t.modelFamilyHint ?? \"auto\",\r\n measureToolDefs: t.measureToolDefs ?? true,\r\n // OPT-IN: host-native turn-usage capture is OFF unless explicitly enabled\r\n // in config (or forced on at install via AGENT_CONNECTOR_HOST_NATIVE=1).\r\n hostNativeUsage: t.hostNativeUsage ?? false,\r\n store: t.store ?? \"ndjson\",\r\n calibration: {\r\n anthropicCountTokens: t.calibration?.anthropicCountTokens ?? false,\r\n },\r\n },\r\n commands,\r\n skills,\r\n subagents,\r\n memory,\r\n ...(statusline ? { statusline } : {}),\r\n actions,\r\n platforms: config.platforms ?? {},\r\n targets: config.targets ?? \"auto\",\r\n ...(config.publish ? { publish: normalizePublish(config.publish) } : {}),\r\n };\r\n\r\n return resolved;\r\n}\r\n\r\n/** The 13 normalized event names, for the nativeHooks collision check. */\r\nconst NORMALIZED_EVENT_SET: ReadonlySet<string> = new Set(ALL_EVENTS);\r\n\r\n/**\r\n * Validate a per-host override map (`hosts?:`) declared on a hook definition or\r\n * on the statusline. Shared by the hook-validation loop and normalizeStatusline:\r\n * - the value must be a plain object keyed by platform id;\r\n * - every key MUST be a REGISTERED platform id (REGISTERED_PLATFORM_IDS) —\r\n * an unknown id is an author-time ConnectorConfigError (NOT a skip-warn:\r\n * a typo'd host would otherwise silently never fire);\r\n * - every entry's implementation field (`handler` for hooks, `render` for\r\n * statusline, `run` for actions) MUST be a function (it is re-imported from\r\n * the connector module at runtime, like the top-level handler/render/run).\r\n * `undefined` (no map) is valid and skipped.\r\n */\r\nfunction validateHostsMap(\r\n map: unknown,\r\n surfaceLabel: string,\r\n implField: \"handler\" | \"render\" | \"run\",\r\n): void {\r\n if (map == null) return;\r\n if (typeof map !== \"object\" || Array.isArray(map)) {\r\n throw new ConnectorConfigError(\r\n `${surfaceLabel} must be an object keyed by platform id`,\r\n );\r\n }\r\n for (const [platformId, entry] of Object.entries(map as Record<string, unknown>)) {\r\n if (!REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)) {\r\n const valid = [...REGISTERED_PLATFORM_IDS].sort().join(\", \");\r\n throw new ConnectorConfigError(\r\n `unknown platform id \"${platformId}\" in hosts map for ${surfaceLabel}; valid ids: ${valid}`,\r\n );\r\n }\r\n if (\r\n entry == null ||\r\n typeof entry !== \"object\" ||\r\n typeof (entry as Record<string, unknown>)[implField] !== \"function\"\r\n ) {\r\n throw new ConnectorConfigError(\r\n `${surfaceLabel}.${platformId}.${implField} must be a function`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Validate every `platforms[<id>].nativeHooks` declaration:\r\n * - the value must be an object keyed by HOST-NATIVE event name;\r\n * - an event name must NOT collide with the normalized {@link HookEventName}\r\n * union (those belong in the cross-platform `hooks` API, which gets\r\n * normalization, matcher evaluation, and HookResponse mapping);\r\n * - each handler must be a function (it is re-imported from the config module\r\n * at runtime, like normalized hook handlers);\r\n * - `matcher`, when present, must be a string (written verbatim into the\r\n * host's hook config — the host evaluates it).\r\n */\r\nfunction validateNativeHooks(platforms: ConnectorConfig[\"platforms\"]): void {\r\n if (platforms == null) return;\r\n for (const [platformId, override] of Object.entries(platforms)) {\r\n const native = override?.nativeHooks;\r\n if (native == null) continue;\r\n const where = `platforms.${platformId}.nativeHooks`;\r\n if (typeof native !== \"object\" || Array.isArray(native)) {\r\n throw new ConnectorConfigError(\r\n `${where} must be an object keyed by host-native event name`,\r\n );\r\n }\r\n for (const [event, def] of Object.entries(native)) {\r\n if (NORMALIZED_EVENT_SET.has(event)) {\r\n throw new ConnectorConfigError(\r\n `${where}.${event} collides with the normalized hook event \"${event}\"; ` +\r\n `declare it under \\`hooks.${event}\\` (the normalized, cross-platform hooks API) instead`,\r\n );\r\n }\r\n if (def == null || typeof def !== \"object\" || typeof def.handler !== \"function\") {\r\n throw new ConnectorConfigError(`${where}.${event}.handler must be a function`);\r\n }\r\n if (def.matcher !== undefined && typeof def.matcher !== \"string\") {\r\n throw new ConnectorConfigError(`${where}.${event}.matcher must be a string`);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Validate every `platforms[<id>].configPatch` declaration:\r\n * - the value must be an array of patch objects;\r\n * - `key` must be a dotted LEAF path whose segments match\r\n * {@link CONFIG_PATCH_SEGMENT_RE} — no dots-in-key, no array indices;\r\n * - `key` must not collide with the agent-connector-modeled namespace\r\n * (`hooks*` → hooks/nativeHooks; `mcpServers*` & friends → server/extra);\r\n * - duplicate keys within one platform's list are rejected (a duplicate\r\n * would double-apply / fight itself on refcounts);\r\n * - `value` must be JSON-serializable data (it is persisted whole in the\r\n * connector record and in the ownership ledger);\r\n * - `reason` is REQUIRED (printed in the install diff and every skip-warn);\r\n * - `docsUrl`, when present, must be a string.\r\n * The HOST-side sensitive-key denylist is deliberately NOT validated here —\r\n * it lives in (and is documented by) each supporting adapter.\r\n */\r\nfunction validateConfigPatches(platforms: ConnectorConfig[\"platforms\"]): void {\r\n if (platforms == null) return;\r\n for (const [platformId, override] of Object.entries(platforms)) {\r\n const patches = override?.configPatch;\r\n if (patches == null) continue;\r\n const where = `platforms.${platformId}.configPatch`;\r\n if (!Array.isArray(patches)) {\r\n throw new ConnectorConfigError(`${where} must be an array of patch objects`);\r\n }\r\n const seen = new Set<string>();\r\n patches.forEach((patch, i) => {\r\n if (patch == null || typeof patch !== \"object\" || Array.isArray(patch)) {\r\n throw new ConnectorConfigError(`${where}[${i}] must be an object`);\r\n }\r\n if (!isValidConfigPatchKey(patch.key)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].key must be a dotted LEAF path whose segments match ` +\r\n `${CONFIG_PATCH_SEGMENT_RE} (no dots-in-key, no array indices); ` +\r\n `got ${JSON.stringify(patch.key)}`,\r\n );\r\n }\r\n const violation = configPatchNamespaceViolation(patch.key);\r\n if (violation) {\r\n throw new ConnectorConfigError(`${where}[${i}].key ${violation}`);\r\n }\r\n if (seen.has(patch.key)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}] duplicate key \"${patch.key}\"`,\r\n );\r\n }\r\n seen.add(patch.key);\r\n if (!isJsonValue(patch.value)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].value must be JSON-serializable data ` +\r\n `(string/finite number/boolean/null/array/plain object)`,\r\n );\r\n }\r\n if (typeof patch.reason !== \"string\" || patch.reason.trim() === \"\") {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].reason is required (a human-readable why, printed in ` +\r\n `the install diff and every skip-warn)`,\r\n );\r\n }\r\n if (patch.docsUrl !== undefined && typeof patch.docsUrl !== \"string\") {\r\n throw new ConnectorConfigError(`${where}[${i}].docsUrl must be a string`);\r\n }\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Validate the optional `publish` block (registry server.json + MCPB bundle\r\n * distribution metadata). Light, dependency-free: we only reject shapes that\r\n * would emit a clearly INVALID standard artifact. The per-format required-field\r\n * checks (e.g. server.json needs registryNamespace, mcpb needs author.name)\r\n * live in the emitters so a connector that never publishes pays nothing.\r\n */\r\nfunction normalizePublish(publish: PublishConfig): PublishConfig {\r\n if (typeof publish !== \"object\" || Array.isArray(publish)) {\r\n throw new ConnectorConfigError(\"publish must be an object\");\r\n }\r\n if (publish.registryNamespace !== undefined) {\r\n const ns = publish.registryNamespace;\r\n if (typeof ns !== \"string\" || !REGISTRY_NAMESPACE_RE.test(ns)) {\r\n throw new ConnectorConfigError(\r\n `publish.registryNamespace must be a reverse-DNS namespace matching ${REGISTRY_NAMESPACE_RE} ` +\r\n `(e.g. \"io.github.acme\" or \"com.acme\"); got ${JSON.stringify(ns)}`,\r\n );\r\n }\r\n }\r\n if (publish.packageName !== undefined && typeof publish.packageName !== \"string\") {\r\n throw new ConnectorConfigError(\"publish.packageName must be a string\");\r\n }\r\n if (publish.author !== undefined) {\r\n const a = publish.author;\r\n if (typeof a !== \"object\" || a == null || typeof a.name !== \"string\" || a.name === \"\") {\r\n throw new ConnectorConfigError(\"publish.author.name must be a non-empty string\");\r\n }\r\n }\r\n return { ...publish };\r\n}\r\n\r\n/** Validate a surface name (kebab-case) or throw a ConnectorConfigError. */\r\nfunction assertSurfaceName(\r\n surface: string,\r\n name: unknown,\r\n index: number,\r\n field = \"name\",\r\n): string {\r\n if (typeof name !== \"string\" || !SURFACE_NAME_RE.test(name)) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].${field} must be kebab-case matching ${SURFACE_NAME_RE} (got ${JSON.stringify(name)})`,\r\n );\r\n }\r\n return name;\r\n}\r\n\r\n/** Require a non-empty string field on a surface entry. */\r\nfunction assertNonEmptyString(\r\n surface: string,\r\n index: number,\r\n field: string,\r\n value: unknown,\r\n): string {\r\n if (typeof value !== \"string\" || value.length === 0) {\r\n throw new ConnectorConfigError(`${surface}[${index}].${field} must be a non-empty string`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Detect a duplicate surface name within one array, throwing on collision. */\r\nfunction assertNoDuplicate(\r\n surface: string,\r\n seen: Set<string>,\r\n name: string,\r\n index: number,\r\n field = \"name\",\r\n): void {\r\n if (seen.has(name)) {\r\n throw new ConnectorConfigError(`${surface}[${index}] duplicate ${field} \"${name}\"`);\r\n }\r\n seen.add(name);\r\n}\r\n\r\nfunction normalizeCommands(input: CommandDef[] | undefined): CommandDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"commands must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((cmd, i) => {\r\n if (!cmd || typeof cmd !== \"object\") {\r\n throw new ConnectorConfigError(`commands[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"commands\", cmd.name, i);\r\n assertNoDuplicate(\"commands\", seen, name, i);\r\n assertNonEmptyString(\"commands\", i, \"prompt\", cmd.prompt);\r\n // Pass through verbatim (content); arrays are content, not handlers.\r\n return { ...cmd, name };\r\n });\r\n}\r\n\r\nfunction normalizeSkills(input: SkillDef[] | undefined): SkillDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"skills must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((skill, i) => {\r\n if (!skill || typeof skill !== \"object\") {\r\n throw new ConnectorConfigError(`skills[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"skills\", skill.name, i);\r\n assertNoDuplicate(\"skills\", seen, name, i);\r\n const description = assertNonEmptyString(\"skills\", i, \"description\", skill.description);\r\n if (description.length > SKILL_DESCRIPTION_MAX) {\r\n throw new ConnectorConfigError(\r\n `skills[${i}].description exceeds ${SKILL_DESCRIPTION_MAX} chars (got ${description.length})`,\r\n );\r\n }\r\n assertNonEmptyString(\"skills\", i, \"body\", skill.body);\r\n assertSafeResourceKeys(\"skills\", i, skill.resources);\r\n return { ...skill, name };\r\n });\r\n}\r\n\r\n/**\r\n * Validate every `skill.resources` key as a SAFE relative path that stays inside\r\n * the skill dir. Each resource is later written/removed via join(skillDir, rel)\r\n * by every adapter, so an unvalidated key like \"../../settings.json\" would\r\n * escape the skill dir → arbitrary file write/delete. Reject (throw) when a key\r\n * is empty/\".\", absolute, or normalizes to a path that begins with \"..\" or\r\n * contains a \"/..\" (or platform-sep) traversal segment.\r\n */\r\nfunction assertSafeResourceKeys(\r\n surface: string,\r\n index: number,\r\n resources: Record<string, string> | undefined,\r\n): void {\r\n if (resources == null) return;\r\n if (typeof resources !== \"object\" || Array.isArray(resources)) {\r\n throw new ConnectorConfigError(`${surface}[${index}].resources must be an object`);\r\n }\r\n for (const rel of Object.keys(resources)) {\r\n if (rel === \"\" || rel === \".\" || rel.trim() === \"\") {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must be a non-empty relative path (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n if (isAbsolute(rel)) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must be a relative path inside the skill dir, not absolute (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n // Normalize with BOTH posix and native separators flattened so a Windows\r\n // \"..\\\\x\" or a posix \"../x\" is caught regardless of the host OS.\r\n const norm = normalize(rel.replace(/\\\\/g, \"/\"));\r\n const segs = norm.split(/[/\\\\]/);\r\n if (norm === \"..\" || norm.startsWith(\"../\") || norm.startsWith(\"..\\\\\") || segs.includes(\"..\")) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must not escape the skill dir via \"..\" (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/** Default name for a single-entry memory declaration. */\r\nconst MEMORY_DEFAULT_NAME = \"memory\";\r\n\r\n/**\r\n * Validate + normalize `memory` entries (the managed-block content surface).\r\n * - `name` defaults to \"memory\", then must be kebab-case and unique — it is\r\n * half of the block marker id (`<connectorId>/<name>`) and must stay stable;\r\n * - `content` must be a non-empty string, ≤ 16 KiB (hard cap — memory files\r\n * are injected into every prompt of every session on the host), and must\r\n * NOT contain the literal marker tokens `agent-connector:begin` /\r\n * `agent-connector:end` (they would corrupt marker scanning in the shared\r\n * file — rephrase the guidance instead). The 4 KiB SOFT budget is reported\r\n * at install time as a `warn` ChangeRecord, not a config error\r\n * (defineConnector has no warning channel).\r\n */\r\nfunction normalizeMemory(input: MemoryDef[] | undefined): MemoryDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"memory must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((entry, i) => {\r\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\r\n throw new ConnectorConfigError(`memory[${i}] must be an object`);\r\n }\r\n const name =\r\n entry.name === undefined\r\n ? MEMORY_DEFAULT_NAME\r\n : assertSurfaceName(\"memory\", entry.name, i);\r\n assertNoDuplicate(\"memory\", seen, name, i);\r\n const content = assertNonEmptyString(\"memory\", i, \"content\", entry.content);\r\n const bytes = Buffer.byteLength(content, \"utf8\");\r\n if (bytes > MEMORY_CONTENT_HARD_CAP_BYTES) {\r\n throw new ConnectorConfigError(\r\n `memory[${i}].content exceeds the ${MEMORY_CONTENT_HARD_CAP_BYTES}-byte hard cap ` +\r\n `(got ${bytes} bytes); memory is inlined into every prompt of every targeted host — keep it terse`,\r\n );\r\n }\r\n for (const token of [MANAGED_BLOCK_BEGIN_TOKEN, MANAGED_BLOCK_END_TOKEN]) {\r\n if (content.includes(token)) {\r\n throw new ConnectorConfigError(\r\n `memory[${i}].content must not contain the literal marker token \"${token}\" ` +\r\n `(it would corrupt managed-block scanning in the shared memory file); rephrase the guidance`,\r\n );\r\n }\r\n }\r\n if (entry.description !== undefined && typeof entry.description !== \"string\") {\r\n throw new ConnectorConfigError(`memory[${i}].description must be a string`);\r\n }\r\n return { ...entry, name };\r\n });\r\n}\r\n\r\n/** Default name for the (singular) statusline declaration. */\r\nconst STATUSLINE_DEFAULT_NAME = \"statusline\";\r\n\r\n/**\r\n * Validate + normalize the SINGULAR `statusline` (a HUD handler surface):\r\n * - `render` MUST be a function (it is the renderer, re-imported at runtime\r\n * like a hook handler);\r\n * - `name` defaults to \"statusline\", then must be kebab-case (the shared\r\n * surface-name validator);\r\n * - `description`, when present, must be a string.\r\n * Returns undefined when no statusline is declared (it is optional and singular,\r\n * unlike the memory[] array).\r\n */\r\nfunction normalizeStatusline(\r\n input: StatuslineDef | undefined,\r\n): StatuslineDef | undefined {\r\n if (input == null) return undefined;\r\n if (typeof input !== \"object\" || Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"statusline must be an object\");\r\n }\r\n if (typeof input.render !== \"function\") {\r\n throw new ConnectorConfigError(\"statusline.render must be a function\");\r\n }\r\n const name =\r\n input.name === undefined\r\n ? STATUSLINE_DEFAULT_NAME\r\n : assertSurfaceName(\"statusline\", input.name, 0);\r\n if (input.description !== undefined && typeof input.description !== \"string\") {\r\n throw new ConnectorConfigError(\"statusline.description must be a string\");\r\n }\r\n // Per-host render override map: registered platform ids only, each render a\r\n // function (author-time hard error, mirroring the hook hosts-map validation).\r\n validateHostsMap(input.hosts, \"statusline.hosts\", \"render\");\r\n return { ...input, name };\r\n}\r\n\r\n/**\r\n * Validate + normalize `actions` (the user-invokable action handler surface):\r\n * - the value must be an array;\r\n * - each entry's `id` must be kebab-case (the shared surface-name validator)\r\n * and UNIQUE within the connector (ConnectorConfigError on dup — the id is\r\n * the verb's positional arg, so a duplicate would be ambiguous);\r\n * - `run` MUST be a function (it is the handler, re-imported at runtime like a\r\n * hook handler / statusline render);\r\n * - `description`, when present, must be a string;\r\n * - the per-host `hosts:` override map is validated via the shared\r\n * validateHostsMap (registered platform ids only, each `run` a function).\r\n * Returns [] when no actions are declared (defaults applied, like the other\r\n * array surfaces).\r\n */\r\nfunction normalizeActions(input: ActionDef[] | undefined): ActionDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"actions must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((action, i) => {\r\n if (!action || typeof action !== \"object\" || Array.isArray(action)) {\r\n throw new ConnectorConfigError(`actions[${i}] must be an object`);\r\n }\r\n const id = assertSurfaceName(\"actions\", action.id, i, \"id\");\r\n assertNoDuplicate(\"actions\", seen, id, i, \"id\");\r\n if (typeof action.run !== \"function\") {\r\n throw new ConnectorConfigError(`actions[${i}].run must be a function`);\r\n }\r\n if (action.description !== undefined && typeof action.description !== \"string\") {\r\n throw new ConnectorConfigError(`actions[${i}].description must be a string`);\r\n }\r\n // Per-host run override map: registered platform ids only, each run a\r\n // function (author-time hard error, mirroring the statusline/hook hosts-map).\r\n validateHostsMap(action.hosts, `actions.${id}.hosts`, \"run\");\r\n return { ...action, id };\r\n });\r\n}\r\n\r\n/**\r\n * Typed identity helper for authoring a status line in its own module:\r\n * export const myStatusline = defineStatusline({ render: (ctx) => \"…\" });\r\n * Mirrors the (informal) defineX helpers; gives the developer full type\r\n * inference on {@link StatuslineContext} without importing the type by hand.\r\n */\r\nexport const defineStatusline = (def: StatuslineDef): StatuslineDef => def;\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Typed identity helpers (the `define*` authoring family)\r\n//\r\n// Each is a one-line identity function: it returns its argument UNCHANGED and\r\n// does NOT validate or mutate (validation still happens centrally in\r\n// defineConnector). Their only job is ergonomics — authoring a surface in its\r\n// own module with full type inference + autocomplete on the *Def shape, and a\r\n// single import site — mirroring the existing {@link defineStatusline}.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Typed identity helper for authoring ONE normalized lifecycle hook in its own\r\n * module, EVENT-PARAMETERIZED so the handler's payload narrows to that event:\r\n *\r\n * export const onPre = defineHook(\"PreToolUse\", {\r\n * handler(evt) { evt.toolName // ← typed as a PreToolUseEvent, not the union\r\n * return { decision: \"deny\", reason: \"no\" };\r\n * },\r\n * });\r\n *\r\n * The leading `event` argument exists ONLY to infer `E`; the def is returned\r\n * unchanged (identity — validation still happens in defineConnector). Passing\r\n * `HookDefinition` without an event would widen the handler param to the full\r\n * {@link HookEventName} union and lose per-event narrowing, so the event tag is\r\n * required.\r\n */\r\nexport const defineHook = <E extends HookEventName>(\r\n event: E,\r\n def: HookDefinition<E>,\r\n): HookDefinition<E> => {\r\n void event; // tag-only: used solely to infer E (the def carries no event field)\r\n return def;\r\n};\r\n\r\n/**\r\n * Typed identity helper for authoring a slash {@link CommandDef} in its own\r\n * module. Returns the def unchanged (kebab-case name + prompt are validated by\r\n * defineConnector when the connector is assembled).\r\n */\r\nexport const defineCommand = (def: CommandDef): CommandDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring an Agent {@link SkillDef} in its own\r\n * module. Returns the def unchanged (name/description/body + safe resource keys\r\n * are validated by defineConnector).\r\n */\r\nexport const defineSkill = (def: SkillDef): SkillDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link SubagentDef} in its own module.\r\n * Returns the def unchanged (name/description/prompt validated by defineConnector).\r\n */\r\nexport const defineSubagent = (def: SubagentDef): SubagentDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link MemoryDef} (standing-guidance\r\n * managed block) in its own module. Returns the def unchanged (name/content +\r\n * byte budget + marker-token guard validated by defineConnector).\r\n */\r\nexport const defineMemory = (def: MemoryDef): MemoryDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a user-invokable {@link ActionDef} in its\r\n * own module. Returns the def unchanged (kebab-case unique id + run-is-function\r\n * + the per-host hosts map validated by defineConnector when the connector is\r\n * assembled).\r\n */\r\nexport const defineAction = (def: ActionDef): ActionDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a declarative {@link ConfigPatchDef}\r\n * (set-if-absent host-config key patch) in its own module. Returns the def\r\n * unchanged (leaf-path grammar + namespace guard + required reason validated by\r\n * defineConnector when it appears under `platforms[<id>].configPatch`).\r\n */\r\nexport const defineConfigPatch = (def: ConfigPatchDef): ConfigPatchDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link NativeHookDef} (host-native\r\n * passthrough hook) in its own module. Returns the def unchanged (event-name\r\n * collision + handler-is-function validated by defineConnector when it appears\r\n * under `platforms[<id>].nativeHooks`).\r\n */\r\nexport const defineNativeHook = (def: NativeHookDef): NativeHookDef => def;\r\n\r\nfunction normalizeSubagents(input: SubagentDef[] | undefined): SubagentDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"subagents must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((agent, i) => {\r\n if (!agent || typeof agent !== \"object\") {\r\n throw new ConnectorConfigError(`subagents[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"subagents\", agent.name, i);\r\n assertNoDuplicate(\"subagents\", seen, name, i);\r\n assertNonEmptyString(\"subagents\", i, \"description\", agent.description);\r\n assertNonEmptyString(\"subagents\", i, \"prompt\", agent.prompt);\r\n return { ...agent, name };\r\n });\r\n}\r\n\r\nfunction normalizeServer(server: ConnectorConfig[\"server\"]): ResolvedConnector[\"server\"] {\r\n if (!server) return undefined;\r\n const wrapDefault = server.transport === \"stdio\";\r\n return {\r\n ...server,\r\n enabled: server.enabled ?? true,\r\n tools: server.tools ?? { include: [\"*\"] },\r\n wrapForTelemetry: server.wrapForTelemetry ?? wrapDefault,\r\n };\r\n}\r\n","/**\r\n * core/mcp-standard — pinned literals + guards for the official MCP standards\r\n * agent-connector EMITS (registry server.json, MCPB bundle) or SPEAKS (the\r\n * connection-lifecycle wire used by `doctor --probe`).\r\n *\r\n * Each pinned constant is the CURRENT released value verified 2026-06-05 against\r\n * the upstream spec/schema. They are deliberately centralized + annotated\r\n * MUST-VERIFY-AT-IMPLEMENTATION: a newer spec revision can supersede any of them\r\n * without breaking us, so the bump is a one-line change here, never scattered.\r\n *\r\n * Sources:\r\n * • server.schema.json 2025-12-11 — https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\r\n * • MCPB manifest 0.3 — github.com/anthropics/mcpb (MANIFEST.md)\r\n * • MCP protocol 2025-11-25 — modelcontextprotocol.io/specification/2025-11-25\r\n * (latest RELEASED revision. 2026-07-28 is a release-candidate only — do NOT\r\n * advance to it until it publishes as a stable dated revision. The probe\r\n * offers this version but ACCEPTS whatever a server negotiates, so the\r\n * offered literal being stale never breaks interop — only this constant.)\r\n */\r\n\r\nimport type { Transport } from \"./types.js\";\r\n\r\n/** Registry server.json JSON Schema URL (released 2025-12-11). MUST-VERIFY on bump. */\r\nexport const MCP_SERVER_SCHEMA_URL =\r\n \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\";\r\n\r\n/** Current MCPB bundle manifest_version (anthropics/mcpb). MUST-VERIFY on bump. */\r\nexport const MCPB_MANIFEST_VERSION = \"0.3\";\r\n\r\n/**\r\n * Latest RELEASED MCP protocol revision `doctor --probe` offers in `initialize`.\r\n * Current = 2025-11-25. MUST-VERIFY on bump; stay on the latest *released*\r\n * revision (2026-07-28 is RC-only as of 2026-06). Negotiation accepts whatever\r\n * the server returns, so this is the offered value, not a hard requirement.\r\n */\r\nexport const MCP_PROTOCOL_VERSION = \"2025-11-25\";\r\n\r\n/** Default npm registry base URL stamped into server.json npm packages. */\r\nexport const NPM_REGISTRY_BASE_URL = \"https://registry.npmjs.org\";\r\n\r\n/**\r\n * server.json transport.type enum — the EXACT values the 2025-12-11 schema\r\n * accepts (packages[].transport.type and remotes[].type). Our `http` Transport\r\n * maps to the spec slug \"streamable-http\"; \"ws\" is non-spec (see below).\r\n */\r\nexport type RegistryTransportType = \"stdio\" | \"streamable-http\" | \"sse\";\r\n\r\n/**\r\n * Map our {@link Transport} union to the registry/server.json transport slug.\r\n * Returns null for \"ws\" — WebSocket is NOT a spec transport (it can only exist\r\n * as a vendor custom transport, e.g. Claude Code's non-spec type:\"ws\"), so a\r\n * conformant artifact must REJECT it rather than emit an invalid type. The spec\r\n * defines exactly stdio + streamable-http, with sse the deprecated HTTP+SSE.\r\n */\r\nexport function registryTransportType(transport: Transport): RegistryTransportType | null {\r\n switch (transport) {\r\n case \"stdio\":\r\n return \"stdio\";\r\n case \"http\":\r\n return \"streamable-http\";\r\n case \"sse\":\r\n return \"sse\";\r\n case \"ws\":\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Is `v` a CONCRETE version the MCP Registry accepts? The registry rejects\r\n * ranges (\"^1.2.3\", \"~1.2.3\", \">=1.2.3\", \"1.x\", \"1.*\"); only a pinned SemVer\r\n * (optionally with a -prerelease / +build suffix) is valid. \"0.0.0\" is concrete\r\n * (so it passes this guard) but is the unset placeholder — callers warn on it\r\n * separately via {@link isPlaceholderVersion}.\r\n */\r\nexport function isConcreteSemver(v: string): boolean {\r\n return /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(v);\r\n}\r\n\r\n/** The unset default version a connector ships with until the dev sets a real one. */\r\nexport function isPlaceholderVersion(v: string): boolean {\r\n return v === \"0.0.0\";\r\n}\r\n\r\n/**\r\n * Reverse-DNS registry namespace pattern (the part BEFORE the \"/\" in a\r\n * server.json `name`). The full name regex is\r\n * `^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$`; the namespace side allows letters, digits,\r\n * dots and hyphens (NO underscore) — e.g. \"io.github.acme\" or \"com.acme\".\r\n */\r\nexport const REGISTRY_NAMESPACE_RE = /^[a-zA-Z0-9.-]+$/;\r\n\r\n/** The full server.json `name` regex (namespace \"/\" server-name), per the schema. */\r\nexport const REGISTRY_NAME_RE = /^[a-zA-Z0-9.-]+\\/[a-zA-Z0-9._-]+$/;\r\n"],"mappings":"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","names":[]}
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  normalizeSessionSource
4
- } from "./chunk-H53QZQJI.js";
4
+ } from "./chunk-PSGTHJQU.js";
5
5
  import {
6
6
  resolveEnvRefsDeep
7
- } from "./chunk-BEFVJ2OE.js";
7
+ } from "./chunk-XXLCMSD3.js";
8
8
  import {
9
9
  BaseAdapter,
10
10
  renderSkillMd
11
- } from "./chunk-MGTDQLJJ.js";
11
+ } from "./chunk-3FINQ2ZF.js";
12
12
  import {
13
13
  buildHomeBinHookCommand,
14
14
  buildUsageEventCommand,
@@ -16,7 +16,7 @@ import {
16
16
  isHomeBinHookCommand,
17
17
  isHostNativeUsageEnabled,
18
18
  isUsageEventCommand
19
- } from "./chunk-4NHXLXSD.js";
19
+ } from "./chunk-Y3K6KJMS.js";
20
20
 
21
21
  // src/adapters/antigravity/index.ts
22
22
  import { existsSync } from "fs";
@@ -687,4 +687,4 @@ export {
687
687
  adapter,
688
688
  antigravity_default
689
689
  };
690
- //# sourceMappingURL=chunk-XC5SJ35F.js.map
690
+ //# sourceMappingURL=chunk-C63AAXK7.js.map