@ken-jo/agent-connector 0.4.98 → 0.4.99

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 (387) hide show
  1. package/LICENSE +202 -202
  2. package/NOTICE +6 -6
  3. package/README.md +604 -596
  4. package/dist/{action-5JM23CFJ.js → action-5OEM3QC4.js} +17 -16
  5. package/dist/action-5OEM3QC4.js.map +1 -0
  6. package/dist/{amazon-q-LFZNGN27.js → amazon-q-7DPVJXJN.js} +6 -6
  7. package/dist/amazon-q-7DPVJXJN.js.map +1 -0
  8. package/dist/{amp-CEWOSWQO.js → amp-BQZOL5GR.js} +4 -4
  9. package/dist/amp-BQZOL5GR.js.map +1 -0
  10. package/dist/{amp-S22XTPEQ.js → amp-VYXZWHXW.js} +7 -7
  11. package/dist/amp-VYXZWHXW.js.map +1 -0
  12. package/dist/{antigravity-LHFEFNMC.js → antigravity-EA4L225L.js} +5 -5
  13. package/dist/antigravity-EA4L225L.js.map +1 -0
  14. package/dist/antigravity-VXHL6ZPM.js +18 -0
  15. package/dist/{antigravity-cli-MOKFSWOU.js → antigravity-cli-B2HXZFYQ.js} +5 -5
  16. package/dist/antigravity-cli-B2HXZFYQ.js.map +1 -0
  17. package/dist/{antigravity-cli-PN474FXM.js → antigravity-cli-JHQ7JGNX.js} +10 -9
  18. package/dist/antigravity-cli-JHQ7JGNX.js.map +1 -0
  19. package/dist/{audit-2H7E3Z4N.js → audit-BO7JQYIH.js} +8 -8
  20. package/dist/{chunk-7C2IPIIB.js → chunk-2Y2MZRLP.js} +3 -3
  21. package/dist/chunk-2Y2MZRLP.js.map +1 -0
  22. package/dist/{chunk-B6PKHS5I.js → chunk-4KIXXJ7B.js} +2 -2
  23. package/dist/chunk-4KIXXJ7B.js.map +1 -0
  24. package/dist/chunk-4NFDNY3C.js +34 -0
  25. package/dist/chunk-4NFDNY3C.js.map +1 -0
  26. package/dist/{chunk-RPWD5H6Y.js → chunk-4QXCNZMD.js} +5 -5
  27. package/dist/chunk-4QXCNZMD.js.map +1 -0
  28. package/dist/{chunk-Q7PR2WGT.js → chunk-6TF7MHG5.js} +2 -2
  29. package/dist/chunk-6TF7MHG5.js.map +1 -0
  30. package/dist/{chunk-KWC5DQ5Z.js → chunk-6WN37NVN.js} +113 -10
  31. package/dist/chunk-6WN37NVN.js.map +1 -0
  32. package/dist/{chunk-DWZ5IWF4.js → chunk-6XMV2OOA.js} +6 -6
  33. package/dist/chunk-6XMV2OOA.js.map +1 -0
  34. package/dist/{chunk-XXLCMSD3.js → chunk-BEFVJ2OE.js} +1 -1
  35. package/dist/chunk-BEFVJ2OE.js.map +1 -0
  36. package/dist/{chunk-HATCOSQT.js → chunk-BV5WK6VQ.js} +19 -19
  37. package/dist/chunk-BV5WK6VQ.js.map +1 -0
  38. package/dist/{chunk-KTBAB556.js → chunk-BXPSDNIB.js} +2 -2
  39. package/dist/chunk-BXPSDNIB.js.map +1 -0
  40. package/dist/{chunk-Q4ISQHUQ.js → chunk-FBJQGRET.js} +1 -1
  41. package/dist/chunk-FBJQGRET.js.map +1 -0
  42. package/dist/{chunk-THI4PI4H.js → chunk-FJCUKXGX.js} +2 -2
  43. package/dist/chunk-FJCUKXGX.js.map +1 -0
  44. package/dist/{chunk-6XWORQM6.js → chunk-FKW5A6HE.js} +23 -7
  45. package/dist/chunk-FKW5A6HE.js.map +1 -0
  46. package/dist/{chunk-TOSNS2BY.js → chunk-G5HAIYRM.js} +43 -43
  47. package/dist/chunk-G5HAIYRM.js.map +1 -0
  48. package/dist/{chunk-RNVIK5YJ.js → chunk-GDIAHWNY.js} +2 -2
  49. package/dist/chunk-GDIAHWNY.js.map +1 -0
  50. package/dist/{chunk-QYOUQCC6.js → chunk-GZGLCCEE.js} +1 -1
  51. package/dist/chunk-GZGLCCEE.js.map +1 -0
  52. package/dist/{chunk-PSGTHJQU.js → chunk-H53QZQJI.js} +1 -1
  53. package/dist/chunk-H53QZQJI.js.map +1 -0
  54. package/dist/{chunk-7HHW23AC.js → chunk-IRUYJD23.js} +29 -29
  55. package/dist/chunk-IRUYJD23.js.map +1 -0
  56. package/dist/{chunk-IOJDZJ72.js → chunk-IVAWP6HH.js} +2 -2
  57. package/dist/chunk-IVAWP6HH.js.map +1 -0
  58. package/dist/{chunk-UNU2KPYJ.js → chunk-JTN3AKZO.js} +23 -15
  59. package/dist/chunk-JTN3AKZO.js.map +1 -0
  60. package/dist/{chunk-4GH2KA7V.js → chunk-KHO5WNTP.js} +1 -1
  61. package/dist/chunk-KHO5WNTP.js.map +1 -0
  62. package/dist/{chunk-S25MVWBP.js → chunk-KLZBRNFP.js} +12 -12
  63. package/dist/chunk-KLZBRNFP.js.map +1 -0
  64. package/dist/{chunk-DOPFBUCX.js → chunk-M6OS4OLU.js} +3 -3
  65. package/dist/chunk-M6OS4OLU.js.map +1 -0
  66. package/dist/{chunk-UZZTWWGG.js → chunk-MQPNU2CY.js} +1 -1
  67. package/dist/chunk-MQPNU2CY.js.map +1 -0
  68. package/dist/{chunk-LZL2YITN.js → chunk-N4STCQGP.js} +7 -7
  69. package/dist/chunk-N4STCQGP.js.map +1 -0
  70. package/dist/{chunk-KFPSJRHR.js → chunk-NBYKLUF6.js} +2 -2
  71. package/dist/chunk-NBYKLUF6.js.map +1 -0
  72. package/dist/{chunk-KM2YXO6V.js → chunk-O7SDRBVB.js} +1 -1
  73. package/dist/chunk-O7SDRBVB.js.map +1 -0
  74. package/dist/{chunk-LFWYYWLV.js → chunk-OP4KBXUO.js} +1 -1
  75. package/dist/chunk-OP4KBXUO.js.map +1 -0
  76. package/dist/{chunk-XN7S44U4.js → chunk-OPXAP3AC.js} +1 -1
  77. package/dist/chunk-OPXAP3AC.js.map +1 -0
  78. package/dist/{chunk-LD5HAN6O.js → chunk-PWCBWAM4.js} +6 -4
  79. package/dist/chunk-PWCBWAM4.js.map +1 -0
  80. package/dist/{chunk-W7AGWAMH.js → chunk-QSY74NAP.js} +2 -2
  81. package/dist/chunk-QSY74NAP.js.map +1 -0
  82. package/dist/{chunk-ZSOS2KOR.js → chunk-RK6VBLXP.js} +1 -1
  83. package/dist/chunk-RK6VBLXP.js.map +1 -0
  84. package/dist/{chunk-7VSZXOXJ.js → chunk-SFY6YLVK.js} +19 -12
  85. package/dist/chunk-SFY6YLVK.js.map +1 -0
  86. package/dist/{chunk-C747DYNT.js → chunk-UM5S7DKK.js} +1 -1
  87. package/dist/chunk-UM5S7DKK.js.map +1 -0
  88. package/dist/{chunk-ILWHLGIC.js → chunk-UMQ6NBQR.js} +2 -2
  89. package/dist/chunk-UMQ6NBQR.js.map +1 -0
  90. package/dist/{chunk-7PSNXUFK.js → chunk-XD7MY6HB.js} +1 -1
  91. package/dist/chunk-XD7MY6HB.js.map +1 -0
  92. package/dist/{chunk-FJ6F5U3W.js → chunk-XY3N2U6L.js} +5 -5
  93. package/dist/chunk-XY3N2U6L.js.map +1 -0
  94. package/dist/{chunk-XZWMJLIT.js → chunk-YT43MUSJ.js} +1 -1
  95. package/dist/chunk-YT43MUSJ.js.map +1 -0
  96. package/dist/{claude-code-TA53454O.js → claude-code-LJ6DVXWQ.js} +22 -12
  97. package/dist/claude-code-LJ6DVXWQ.js.map +1 -0
  98. package/dist/{claude-code-FS42PXZO.js → claude-code-NMRKTAP7.js} +4 -4
  99. package/dist/claude-code-NMRKTAP7.js.map +1 -0
  100. package/dist/cli/sdk.js +7 -7
  101. package/dist/cli/sdk.js.map +1 -1
  102. package/dist/cli.js +1 -1
  103. package/dist/cli.js.map +1 -1
  104. package/dist/{cline-GZFN32BM.js → cline-JAPJNOZQ.js} +6 -6
  105. package/dist/cline-JAPJNOZQ.js.map +1 -0
  106. package/dist/{codebuddy-IYS3TQZ3.js → codebuddy-GC7VAE2Y.js} +7 -7
  107. package/dist/codebuddy-GC7VAE2Y.js.map +1 -0
  108. package/dist/{codebuff-D3MIKJHC.js → codebuff-3VODFPD4.js} +6 -6
  109. package/dist/codebuff-3VODFPD4.js.map +1 -0
  110. package/dist/{codebuff-6KWBW6CT.js → codebuff-ETYT5UBL.js} +4 -4
  111. package/dist/codebuff-ETYT5UBL.js.map +1 -0
  112. package/dist/{codex-ZKLP5IXZ.js → codex-RXIS5BHM.js} +9 -9
  113. package/dist/codex-RXIS5BHM.js.map +1 -0
  114. package/dist/{codex-DKBAAUCO.js → codex-YAORPCOD.js} +4 -4
  115. package/dist/codex-YAORPCOD.js.map +1 -0
  116. package/dist/{continue-I34FNSTJ.js → continue-MECVDV4Z.js} +8 -8
  117. package/dist/continue-MECVDV4Z.js.map +1 -0
  118. package/dist/{copilot-cli-CLBJACQ5.js → copilot-cli-MZTAWMPW.js} +4 -4
  119. package/dist/copilot-cli-MZTAWMPW.js.map +1 -0
  120. package/dist/{copilot-cli-NWPM5GE6.js → copilot-cli-WVWAWNSM.js} +7 -7
  121. package/dist/copilot-cli-WVWAWNSM.js.map +1 -0
  122. package/dist/{crush-A5C5USRL.js → crush-QBXLNN7T.js} +4 -4
  123. package/dist/crush-QBXLNN7T.js.map +1 -0
  124. package/dist/{crush-MDGPZSZU.js → crush-YB3SK6NK.js} +7 -7
  125. package/dist/crush-YB3SK6NK.js.map +1 -0
  126. package/dist/{cursor-D5SWDVSW.js → cursor-DIW43TRZ.js} +3 -3
  127. package/dist/cursor-DIW43TRZ.js.map +1 -0
  128. package/dist/cursor-RSLHA2CY.js +22 -0
  129. package/dist/{define-connector-B7tLHVnx.d.ts → define-connector-odRHEC4H.d.ts} +1 -1
  130. package/dist/{detect-FKJC36P4.js → detect-ALP4G7WG.js} +4 -4
  131. package/dist/detect-ALP4G7WG.js.map +1 -0
  132. package/dist/{devin-TZMRC57O.js → devin-WPDN3MXE.js} +7 -7
  133. package/dist/devin-WPDN3MXE.js.map +1 -0
  134. package/dist/{doctor-PGVYUQYG.js → doctor-YEQWCWZJ.js} +27 -26
  135. package/dist/doctor-YEQWCWZJ.js.map +1 -0
  136. package/dist/{droid-SCFWDJR4.js → droid-HS6MX3IL.js} +10 -8
  137. package/dist/droid-HS6MX3IL.js.map +1 -0
  138. package/dist/{droid-PFQ2PZSF.js → droid-U3ZBLQFO.js} +4 -4
  139. package/dist/droid-U3ZBLQFO.js.map +1 -0
  140. package/dist/{gemini-cli-Y6RJMU24.js → gemini-cli-NMVVBO3K.js} +4 -4
  141. package/dist/gemini-cli-NMVVBO3K.js.map +1 -0
  142. package/dist/{gemini-cli-MLDGOR2L.js → gemini-cli-VJ6X5DNF.js} +8 -8
  143. package/dist/gemini-cli-VJ6X5DNF.js.map +1 -0
  144. package/dist/{goose-5DBHDSJW.js → goose-3X7ID7YW.js} +9 -9
  145. package/dist/goose-3X7ID7YW.js.map +1 -0
  146. package/dist/{goose-K2HKUTBK.js → goose-64V46Y2W.js} +4 -4
  147. package/dist/goose-64V46Y2W.js.map +1 -0
  148. package/dist/{grok-cli-LX6Q6RUY.js → grok-cli-4VFVF2CQ.js} +7 -7
  149. package/dist/grok-cli-4VFVF2CQ.js.map +1 -0
  150. package/dist/{hermes-LJB3SJKB.js → hermes-AIVUE7LX.js} +10 -8
  151. package/dist/hermes-AIVUE7LX.js.map +1 -0
  152. package/dist/{hermes-MF3NX4ZY.js → hermes-F3EGTK6N.js} +4 -4
  153. package/dist/hermes-F3EGTK6N.js.map +1 -0
  154. package/dist/{hook-PVGBQUQI.js → hook-F63I3SD5.js} +17 -16
  155. package/dist/hook-F63I3SD5.js.map +1 -0
  156. package/dist/index.d.ts +3 -3
  157. package/dist/index.js +5 -5
  158. package/dist/{install-HPDIK7F6.js → install-23WRRFBY.js} +21 -21
  159. package/dist/install-23WRRFBY.js.map +1 -0
  160. package/dist/{introspect-DWCu0Krk.d.ts → introspect-gTx6GzpW.d.ts} +1 -1
  161. package/dist/{jetbrains-copilot-2DSVAJMJ.js → jetbrains-copilot-XBO2JZRO.js} +6 -6
  162. package/dist/jetbrains-copilot-XBO2JZRO.js.map +1 -0
  163. package/dist/{junie-GUBDRADP.js → junie-UCOS6Q37.js} +6 -6
  164. package/dist/junie-UCOS6Q37.js.map +1 -0
  165. package/dist/{kilo-SMHPOHJ5.js → kilo-SW7BH6EG.js} +4 -4
  166. package/dist/kilo-SW7BH6EG.js.map +1 -0
  167. package/dist/{kilo-HRLWMENX.js → kilo-T4OXNUYY.js} +8 -8
  168. package/dist/kilo-T4OXNUYY.js.map +1 -0
  169. package/dist/{kilo-cli-IQMFMYZF.js → kilo-cli-I2S3W245.js} +8 -8
  170. package/dist/kilo-cli-I2S3W245.js.map +1 -0
  171. package/dist/{kilo-cli-T2SRRRJS.js → kilo-cli-ZF272ZHN.js} +5 -5
  172. package/dist/kilo-cli-ZF272ZHN.js.map +1 -0
  173. package/dist/{kimi-MSIDEMCI.js → kimi-5FHEXGZD.js} +4 -4
  174. package/dist/kimi-5FHEXGZD.js.map +1 -0
  175. package/dist/{kimi-EPD46UJK.js → kimi-VLSUFLYV.js} +7 -7
  176. package/dist/kimi-VLSUFLYV.js.map +1 -0
  177. package/dist/{kiro-A7DL52FX.js → kiro-AQFXGOJX.js} +10 -8
  178. package/dist/kiro-AQFXGOJX.js.map +1 -0
  179. package/dist/{kiro-NYRRBIKW.js → kiro-WGOI5CGT.js} +4 -4
  180. package/dist/kiro-WGOI5CGT.js.map +1 -0
  181. package/dist/{leaderboard-KCT7XPCI.js → leaderboard-YBD3IKC2.js} +7 -7
  182. package/dist/leaderboard-YBD3IKC2.js.map +1 -0
  183. package/dist/{mimo-code-NDGLBXNC.js → mimo-code-KETL7W7D.js} +7 -7
  184. package/dist/mimo-code-KETL7W7D.js.map +1 -0
  185. package/dist/{mistral-vibe-LLWASF5X.js → mistral-vibe-3AU7N2CA.js} +6 -6
  186. package/dist/mistral-vibe-3AU7N2CA.js.map +1 -0
  187. package/dist/{mux-ON4QK3OC.js → mux-BO2L5CTW.js} +6 -6
  188. package/dist/mux-BO2L5CTW.js.map +1 -0
  189. package/dist/{mux-7PIJ7HUQ.js → mux-XM6AP35L.js} +4 -4
  190. package/dist/mux-XM6AP35L.js.map +1 -0
  191. package/dist/{nemoclaw-45R5MFBF.js → nemoclaw-WA7RSKF2.js} +7 -7
  192. package/dist/nemoclaw-WA7RSKF2.js.map +1 -0
  193. package/dist/{omp-ROCTFV3A.js → omp-UDYJ2PYY.js} +9 -7
  194. package/dist/omp-UDYJ2PYY.js.map +1 -0
  195. package/dist/{open-interpreter-V6CN542J.js → open-interpreter-WMBNM4MQ.js} +6 -6
  196. package/dist/open-interpreter-WMBNM4MQ.js.map +1 -0
  197. package/dist/openclaw-3DHVHX5P.js +17 -0
  198. package/dist/{openclaw-KAFTNLR2.js → openclaw-5EQFGOWL.js} +4 -4
  199. package/dist/openclaw-5EQFGOWL.js.map +1 -0
  200. package/dist/{opencode-YYWQ45LF.js → opencode-IKMI3RI7.js} +7 -7
  201. package/dist/opencode-IKMI3RI7.js.map +1 -0
  202. package/dist/{opencode-Z65JYILL.js → opencode-QGP4ALQY.js} +4 -4
  203. package/dist/opencode-QGP4ALQY.js.map +1 -0
  204. package/dist/{openhands-OFFMWCQW.js → openhands-QGXMQR6I.js} +7 -7
  205. package/dist/openhands-QGXMQR6I.js.map +1 -0
  206. package/dist/{package-TALOSRQ4.js → package-TAUTPP7Z.js} +15 -15
  207. package/dist/package-TAUTPP7Z.js.map +1 -0
  208. package/dist/{pi-4W74ETTI.js → pi-A2HCGRJG.js} +9 -7
  209. package/dist/pi-A2HCGRJG.js.map +1 -0
  210. package/dist/{pi-DLKCPOJE.js → pi-GGDQREVG.js} +4 -4
  211. package/dist/pi-GGDQREVG.js.map +1 -0
  212. package/dist/{qwen-code-JOBFNEVT.js → qwen-code-DNQTGJOF.js} +28 -10
  213. package/dist/qwen-code-DNQTGJOF.js.map +1 -0
  214. package/dist/{qwen-code-26CSFDX6.js → qwen-code-GQILBJ5B.js} +4 -4
  215. package/dist/qwen-code-GQILBJ5B.js.map +1 -0
  216. package/dist/{roo-code-HSAE2CJU.js → roo-code-SUWI4BBN.js} +4 -4
  217. package/dist/roo-code-SUWI4BBN.js.map +1 -0
  218. package/dist/{roo-code-RHIGJZNY.js → roo-code-VI2ZKTZC.js} +6 -6
  219. package/dist/roo-code-VI2ZKTZC.js.map +1 -0
  220. package/dist/runtime/index.d.ts +1 -1
  221. package/dist/runtime/index.js +15 -14
  222. package/dist/sdk/index.d.ts +4 -4
  223. package/dist/sdk/index.js +6 -6
  224. package/dist/sdk/index.js.map +1 -1
  225. package/dist/sdk/test.d.ts +2 -2
  226. package/dist/sdk/test.js +12 -11
  227. package/dist/{serve-4TEHK726.js → serve-6MDLRQS2.js} +17 -16
  228. package/dist/serve-6MDLRQS2.js.map +1 -0
  229. package/dist/{status-DVD4EHMX.js → status-IUP75XHP.js} +11 -11
  230. package/dist/status-IUP75XHP.js.map +1 -0
  231. package/dist/{statusline-ZVNH7XBK.js → statusline-PRODZV2J.js} +16 -15
  232. package/dist/statusline-PRODZV2J.js.map +1 -0
  233. package/dist/{synthetic-LUT6V6SD.js → synthetic-6FRA7P5Q.js} +4 -4
  234. package/dist/synthetic-6FRA7P5Q.js.map +1 -0
  235. package/dist/{telemetry-NWUJPIK3.js → telemetry-X4PLZEDB.js} +10 -10
  236. package/dist/telemetry-X4PLZEDB.js.map +1 -0
  237. package/dist/{trae-SIQI3C66.js → trae-CPPYASR2.js} +4 -4
  238. package/dist/trae-CPPYASR2.js.map +1 -0
  239. package/dist/{trae-TLAFSQRQ.js → trae-VOJXUYRN.js} +6 -6
  240. package/dist/trae-VOJXUYRN.js.map +1 -0
  241. package/dist/{types-C6j18a6R.d.ts → types-DWXnnx-N.d.ts} +83 -8
  242. package/dist/{uninstall-DZVFV7KE.js → uninstall-BSIJ4QXN.js} +21 -21
  243. package/dist/uninstall-BSIJ4QXN.js.map +1 -0
  244. package/dist/{upgrade-OUE4ED52.js → upgrade-ZSICU3NE.js} +21 -21
  245. package/dist/upgrade-ZSICU3NE.js.map +1 -0
  246. package/dist/{usage-NT3ZXALZ.js → usage-EQUNVSCT.js} +4 -4
  247. package/dist/usage-EQUNVSCT.js.map +1 -0
  248. package/dist/{usage-event-IELZE6WO.js → usage-event-J5CQ6LNT.js} +16 -15
  249. package/dist/usage-event-J5CQ6LNT.js.map +1 -0
  250. package/dist/{vscode-copilot-VZ5XYSTK.js → vscode-copilot-ZBXRPKGG.js} +7 -7
  251. package/dist/vscode-copilot-ZBXRPKGG.js.map +1 -0
  252. package/dist/{warp-5YBSP7FP.js → warp-NRBBJQR2.js} +4 -4
  253. package/dist/warp-NRBBJQR2.js.map +1 -0
  254. package/dist/{warp-P2HWXIKT.js → warp-S444B2S3.js} +9 -7
  255. package/dist/warp-S444B2S3.js.map +1 -0
  256. package/dist/{windsurf-3JC73GZK.js → windsurf-R6D2JUTN.js} +6 -6
  257. package/dist/windsurf-R6D2JUTN.js.map +1 -0
  258. package/dist/{zed-6CMUKXLI.js → zed-DQV3ZUCU.js} +10 -8
  259. package/dist/zed-DQV3ZUCU.js.map +1 -0
  260. package/dist/{zed-XXCNYOIN.js → zed-XJFOOKCO.js} +4 -4
  261. package/dist/zed-XJFOOKCO.js.map +1 -0
  262. package/package.json +88 -88
  263. package/dist/action-5JM23CFJ.js.map +0 -1
  264. package/dist/amazon-q-LFZNGN27.js.map +0 -1
  265. package/dist/amp-CEWOSWQO.js.map +0 -1
  266. package/dist/amp-S22XTPEQ.js.map +0 -1
  267. package/dist/antigravity-LHFEFNMC.js.map +0 -1
  268. package/dist/antigravity-PZXYAO3X.js +0 -18
  269. package/dist/antigravity-cli-MOKFSWOU.js.map +0 -1
  270. package/dist/antigravity-cli-PN474FXM.js.map +0 -1
  271. package/dist/chunk-4GH2KA7V.js.map +0 -1
  272. package/dist/chunk-6XWORQM6.js.map +0 -1
  273. package/dist/chunk-7C2IPIIB.js.map +0 -1
  274. package/dist/chunk-7HHW23AC.js.map +0 -1
  275. package/dist/chunk-7PSNXUFK.js.map +0 -1
  276. package/dist/chunk-7VSZXOXJ.js.map +0 -1
  277. package/dist/chunk-B6PKHS5I.js.map +0 -1
  278. package/dist/chunk-C747DYNT.js.map +0 -1
  279. package/dist/chunk-DOPFBUCX.js.map +0 -1
  280. package/dist/chunk-DWZ5IWF4.js.map +0 -1
  281. package/dist/chunk-FJ6F5U3W.js.map +0 -1
  282. package/dist/chunk-HATCOSQT.js.map +0 -1
  283. package/dist/chunk-ILWHLGIC.js.map +0 -1
  284. package/dist/chunk-IOJDZJ72.js.map +0 -1
  285. package/dist/chunk-KFPSJRHR.js.map +0 -1
  286. package/dist/chunk-KM2YXO6V.js.map +0 -1
  287. package/dist/chunk-KTBAB556.js.map +0 -1
  288. package/dist/chunk-KWC5DQ5Z.js.map +0 -1
  289. package/dist/chunk-LD5HAN6O.js.map +0 -1
  290. package/dist/chunk-LFWYYWLV.js.map +0 -1
  291. package/dist/chunk-LZL2YITN.js.map +0 -1
  292. package/dist/chunk-PSGTHJQU.js.map +0 -1
  293. package/dist/chunk-Q4ISQHUQ.js.map +0 -1
  294. package/dist/chunk-Q7PR2WGT.js.map +0 -1
  295. package/dist/chunk-QYOUQCC6.js.map +0 -1
  296. package/dist/chunk-RNVIK5YJ.js.map +0 -1
  297. package/dist/chunk-RPWD5H6Y.js.map +0 -1
  298. package/dist/chunk-S25MVWBP.js.map +0 -1
  299. package/dist/chunk-THI4PI4H.js.map +0 -1
  300. package/dist/chunk-TOSNS2BY.js.map +0 -1
  301. package/dist/chunk-UNU2KPYJ.js.map +0 -1
  302. package/dist/chunk-UZZTWWGG.js.map +0 -1
  303. package/dist/chunk-W7AGWAMH.js.map +0 -1
  304. package/dist/chunk-XN7S44U4.js.map +0 -1
  305. package/dist/chunk-XXLCMSD3.js.map +0 -1
  306. package/dist/chunk-XZWMJLIT.js.map +0 -1
  307. package/dist/chunk-ZSOS2KOR.js.map +0 -1
  308. package/dist/claude-code-FS42PXZO.js.map +0 -1
  309. package/dist/claude-code-TA53454O.js.map +0 -1
  310. package/dist/cline-GZFN32BM.js.map +0 -1
  311. package/dist/codebuddy-IYS3TQZ3.js.map +0 -1
  312. package/dist/codebuff-6KWBW6CT.js.map +0 -1
  313. package/dist/codebuff-D3MIKJHC.js.map +0 -1
  314. package/dist/codex-DKBAAUCO.js.map +0 -1
  315. package/dist/codex-ZKLP5IXZ.js.map +0 -1
  316. package/dist/continue-I34FNSTJ.js.map +0 -1
  317. package/dist/copilot-cli-CLBJACQ5.js.map +0 -1
  318. package/dist/copilot-cli-NWPM5GE6.js.map +0 -1
  319. package/dist/crush-A5C5USRL.js.map +0 -1
  320. package/dist/crush-MDGPZSZU.js.map +0 -1
  321. package/dist/cursor-D5SWDVSW.js.map +0 -1
  322. package/dist/cursor-JRVK56QA.js +0 -22
  323. package/dist/detect-FKJC36P4.js.map +0 -1
  324. package/dist/devin-TZMRC57O.js.map +0 -1
  325. package/dist/doctor-PGVYUQYG.js.map +0 -1
  326. package/dist/droid-PFQ2PZSF.js.map +0 -1
  327. package/dist/droid-SCFWDJR4.js.map +0 -1
  328. package/dist/gemini-cli-MLDGOR2L.js.map +0 -1
  329. package/dist/gemini-cli-Y6RJMU24.js.map +0 -1
  330. package/dist/goose-5DBHDSJW.js.map +0 -1
  331. package/dist/goose-K2HKUTBK.js.map +0 -1
  332. package/dist/grok-cli-LX6Q6RUY.js.map +0 -1
  333. package/dist/hermes-LJB3SJKB.js.map +0 -1
  334. package/dist/hermes-MF3NX4ZY.js.map +0 -1
  335. package/dist/hook-PVGBQUQI.js.map +0 -1
  336. package/dist/install-HPDIK7F6.js.map +0 -1
  337. package/dist/jetbrains-copilot-2DSVAJMJ.js.map +0 -1
  338. package/dist/junie-GUBDRADP.js.map +0 -1
  339. package/dist/kilo-HRLWMENX.js.map +0 -1
  340. package/dist/kilo-SMHPOHJ5.js.map +0 -1
  341. package/dist/kilo-cli-IQMFMYZF.js.map +0 -1
  342. package/dist/kilo-cli-T2SRRRJS.js.map +0 -1
  343. package/dist/kimi-EPD46UJK.js.map +0 -1
  344. package/dist/kimi-MSIDEMCI.js.map +0 -1
  345. package/dist/kiro-A7DL52FX.js.map +0 -1
  346. package/dist/kiro-NYRRBIKW.js.map +0 -1
  347. package/dist/leaderboard-KCT7XPCI.js.map +0 -1
  348. package/dist/mimo-code-NDGLBXNC.js.map +0 -1
  349. package/dist/mistral-vibe-LLWASF5X.js.map +0 -1
  350. package/dist/mux-7PIJ7HUQ.js.map +0 -1
  351. package/dist/mux-ON4QK3OC.js.map +0 -1
  352. package/dist/nemoclaw-45R5MFBF.js.map +0 -1
  353. package/dist/omp-ROCTFV3A.js.map +0 -1
  354. package/dist/open-interpreter-V6CN542J.js.map +0 -1
  355. package/dist/openclaw-AOKFJGRQ.js +0 -17
  356. package/dist/openclaw-KAFTNLR2.js.map +0 -1
  357. package/dist/opencode-YYWQ45LF.js.map +0 -1
  358. package/dist/opencode-Z65JYILL.js.map +0 -1
  359. package/dist/openhands-OFFMWCQW.js.map +0 -1
  360. package/dist/package-TALOSRQ4.js.map +0 -1
  361. package/dist/pi-4W74ETTI.js.map +0 -1
  362. package/dist/pi-DLKCPOJE.js.map +0 -1
  363. package/dist/qwen-code-26CSFDX6.js.map +0 -1
  364. package/dist/qwen-code-JOBFNEVT.js.map +0 -1
  365. package/dist/roo-code-HSAE2CJU.js.map +0 -1
  366. package/dist/roo-code-RHIGJZNY.js.map +0 -1
  367. package/dist/serve-4TEHK726.js.map +0 -1
  368. package/dist/status-DVD4EHMX.js.map +0 -1
  369. package/dist/statusline-ZVNH7XBK.js.map +0 -1
  370. package/dist/synthetic-LUT6V6SD.js.map +0 -1
  371. package/dist/telemetry-NWUJPIK3.js.map +0 -1
  372. package/dist/trae-SIQI3C66.js.map +0 -1
  373. package/dist/trae-TLAFSQRQ.js.map +0 -1
  374. package/dist/uninstall-DZVFV7KE.js.map +0 -1
  375. package/dist/upgrade-OUE4ED52.js.map +0 -1
  376. package/dist/usage-NT3ZXALZ.js.map +0 -1
  377. package/dist/usage-event-IELZE6WO.js.map +0 -1
  378. package/dist/vscode-copilot-VZ5XYSTK.js.map +0 -1
  379. package/dist/warp-5YBSP7FP.js.map +0 -1
  380. package/dist/warp-P2HWXIKT.js.map +0 -1
  381. package/dist/windsurf-3JC73GZK.js.map +0 -1
  382. package/dist/zed-6CMUKXLI.js.map +0 -1
  383. package/dist/zed-XXCNYOIN.js.map +0 -1
  384. /package/dist/{antigravity-PZXYAO3X.js.map → antigravity-VXHL6ZPM.js.map} +0 -0
  385. /package/dist/{audit-2H7E3Z4N.js.map → audit-BO7JQYIH.js.map} +0 -0
  386. /package/dist/{cursor-JRVK56QA.js.map → cursor-RSLHA2CY.js.map} +0 -0
  387. /package/dist/{openclaw-AOKFJGRQ.js.map → openclaw-3DHVHX5P.js.map} +0 -0
@@ -1,20 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  roamingAppData
4
- } from "./chunk-C747DYNT.js";
4
+ } from "./chunk-UM5S7DKK.js";
5
5
  import {
6
6
  resolveEnvRefsDeep
7
- } from "./chunk-XXLCMSD3.js";
7
+ } from "./chunk-BEFVJ2OE.js";
8
8
  import {
9
9
  BaseAdapter,
10
10
  renderSkillMd
11
- } from "./chunk-UNU2KPYJ.js";
11
+ } from "./chunk-JTN3AKZO.js";
12
12
  import {
13
13
  buildWrappedStdio,
14
14
  isHomeBinActionCommand
15
- } from "./chunk-W7AGWAMH.js";
16
- import "./chunk-ILWHLGIC.js";
17
- import "./chunk-QYOUQCC6.js";
15
+ } from "./chunk-QSY74NAP.js";
16
+ import "./chunk-UMQ6NBQR.js";
17
+ import "./chunk-GZGLCCEE.js";
18
18
 
19
19
  // src/adapters/zed/index.ts
20
20
  import { existsSync } from "fs";
@@ -54,7 +54,9 @@ var ZedAdapter = class _ZedAdapter extends BaseAdapter {
54
54
  // (zed.dev/docs/tasks). Each AC action becomes one owned task whose `command`
55
55
  // execs the home-bin action verb — a headless exec (zed runs it in a shell).
56
56
  // user → ~/.config/zed/tasks.json; project → <projectDir>/.zed/tasks.json.
57
- supportsActions: true
57
+ supportsActions: true,
58
+ actionInvocationMode: "task",
59
+ actionAffordanceKind: "task"
58
60
  };
59
61
  // ── Detection ────────────────────────────────────────────────────────────
60
62
  detectInstalled(projectDir) {
@@ -425,4 +427,4 @@ export {
425
427
  adapter,
426
428
  zed_default as default
427
429
  };
428
- //# sourceMappingURL=zed-6CMUKXLI.js.map
430
+ //# sourceMappingURL=zed-DQV3ZUCU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/zed/index.ts"],"sourcesContent":["/**\n * adapters/zed — Zed editor platform adapter for agent-connector.\n *\n * Zed is an **mcp-only** host: it is an IDE, not a CLI with a hook pipeline, so\n * there is NO lifecycle hook system. MCP (\"context servers\") is the only\n * integration path, so this adapter installs only the MCP server and reports\n * hooks as unavailable — like Warp, it exercises the `mcp-only` paradigm.\n *\n * MCP config (one JSON-with-comments settings file, NOT a dedicated MCP file):\n * - user scope → settings.json under Zed's OS-native config dir (Rust\n * `dirs::config_dir()`):\n * • Windows: %APPDATA%\\Zed\\settings.json (Roaming, NOT %LOCALAPPDATA%)\n * • macOS / Linux: ~/.config/zed/settings.json\n * - project scope → <projectDir>/.zed/settings.json\n * Root key is \"context_servers\" (NOT \"mcpServers\"). The same file holds the\n * (non-existent) hook config — there is no separate hook file here.\n *\n * MERGE CONTRACT: Zed's settings.json is a large user-owned IDE config. We read\n * the whole file, set ONLY context_servers[<id>], and write it back — every\n * other top-level key and sibling context server is preserved. (Zed accepts\n * JSONC; we WRITE plain JSON, mirroring the other JSON-config adapters.)\n *\n * ENTRY SHAPE QUIRK (verified against context-mode's proven Zed adapter +\n * zed-industries/zed crates/settings_content/src/project.rs): Zed's\n * context_servers Stdio variant flattens ContextServerCommand and renames its\n * `path` field to the JSON key `command`. The accepted shape is therefore a\n * FLAT entry: { \"command\": \"<exe>\", \"args\": [...], \"env\": {...} }. The nested\n * { command: { path, args } } form fails to deserialize under Zed's\n * #[serde(untagged)] enum and is silently dropped (the server never loads).\n *\n * Zed documents no native ${env:VAR} interpolation token for context_servers,\n * so env refs are resolved to literals at install time (the no-native-token\n * path, same as Warp).\n *\n * Skills surface: Zed reads SKILL.md files from:\n * project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n * user scope → ~/.agents/skills/<name>/SKILL.md\n *\n * Actions surface: Zed reads `tasks.json` — a JSON ARRAY of tasks\n * `{ label, command, args?, … }` spawned in its integrated terminal and surfaced\n * in the command palette (`task: spawn`) / bindable (zed.dev/docs/tasks):\n * user scope → ~/.config/zed/tasks.json (%APPDATA%\\Zed on Windows — the\n * SAME OS-native config dir as settings.json)\n * project scope → <projectDir>/.zed/tasks.json\n * For each AC action we add ONE owned task whose `command` execs the home-bin\n * action verb. Zed runs `command` in a shell (\"tasks act just like your shell\"),\n * so the full `<homeBin> action zed <id> --connector <id>` line is a HEADLESS\n * exec (unlike Warp's paste-into-input semantics). tasks.json is a user-owned\n * ARRAY, so we array-merge: set-if-absent, keyed on OUR action command (the\n * isHomeBinActionCommand ownership predicate), idempotent, and uninstall removes\n * ONLY our entries — every foreign task survives.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter, type ActionTrigger } from \"../base.js\";\nimport type { Adapter, InstallContext, MemoryTarget } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookParadigm,\n PlatformCapabilities,\n PlatformId,\n ServerDef,\n SkillDef,\n Transport,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { roamingAppData } from \"../../core/host-paths.js\";\nimport {\n buildWrappedStdio,\n isHomeBinActionCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\n\nconst HOST: PlatformId = \"zed\";\nconst MCP_ROOT_KEY = \"context_servers\";\n\n/**\n * Zed's context_servers Stdio entry. FLAT shape — `command` is a string, NOT a\n * nested { path, args } object (see file header). Remote transports are\n * represented as a URL-bearing entry.\n */\ninterface ZedStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n}\ninterface ZedHttpServer {\n url: string;\n headers?: Record<string, string>;\n}\n\n/**\n * One Zed task entry in tasks.json (zed.dev/docs/tasks). Zed accepts many\n * optional keys (env, cwd, reveal, …); we write only the minimal owned trio\n * { label, command } and preserve every key on FOREIGN entries untouched.\n */\ninterface ZedTask {\n label: string;\n command: string;\n [key: string]: unknown;\n}\n\nexport class ZedAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Zed\";\n readonly paradigm: HookParadigm = \"mcp-only\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block. Zed's project rules file\n // is FIRST-MATCH across nine candidates — memoryTargets below probes that\n // order and writes into the file Zed will actually read; user scope is the\n // personal ~/.config/zed/AGENTS.md (%APPDATA%\\Zed on Windows, base map).\n supportsMemory: true,\n // Zed has no lifecycle hook system — every hook capability is false.\n preToolUse: false,\n postToolUse: false,\n preCompact: false,\n sessionStart: false,\n sessionEnd: false,\n userPromptSubmit: false,\n stop: false,\n notification: false,\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: false,\n // Zed registers stdio context servers; remote URLs are also accepted.\n transports: [\"stdio\", \"sse\", \"http\"],\n // Skills: Zed reads SKILL.md from .agents/skills/<name>/SKILL.md (project)\n // and ~/.agents/skills/<name>/SKILL.md (user).\n supportsSkills: true,\n // Actions: Zed reads tasks.json (a JSON ARRAY of { label, command, args? })\n // spawned in its integrated terminal + surfaced in the command palette\n // (zed.dev/docs/tasks). Each AC action becomes one owned task whose `command`\n // execs the home-bin action verb — a headless exec (zed runs it in a shell).\n // user → ~/.config/zed/tasks.json; project → <projectDir>/.zed/tasks.json.\n supportsActions: true,\n actionInvocationMode: \"task\",\n actionAffordanceKind: \"task\",\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = this.userConfigDir();\n const userSettings = this.userSettingsPath();\n const projDir = join(projectDir, \".zed\");\n const projSettings = join(projDir, \"settings.json\");\n\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\n const projInstalled = existsSync(projDir) || existsSync(projSettings);\n const installed = userInstalled || projInstalled;\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projSettings : userSettings;\n\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? `found Zed config (${scope}) at ${configPath}`\n : `no Zed config at ${userSettings} or ${projSettings}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".zed\")\n : this.userConfigDir();\n }\n\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n /**\n * Zed has no hook file — hooks are not a thing here. The hook \"config path\"\n * is the same settings.json so the generic doctor/backup behave sensibly.\n */\n getHookConfigPath(ctx: InstallContext): string {\n return this.getServerConfigPath(ctx);\n }\n\n /**\n * Zed's user config dir is OS-native (Rust `dirs::config_dir()`), NOT a\n * uniform ~/.config:\n * - Windows: %APPDATA%\\Zed (Roaming, NOT Local/%LOCALAPPDATA%)\n * - macOS / Linux: ~/.config/zed\n */\n private userConfigDir(): string {\n if (process.platform === \"win32\") {\n return join(roamingAppData(), \"Zed\");\n }\n return join(homedir(), \".config\", \"zed\");\n }\n\n private userSettingsPath(): string {\n return join(this.userConfigDir(), \"settings.json\");\n }\n\n // ── Memory surface: first-match project rules probe ─────────────────────\n /**\n * Zed reads exactly ONE project rules file — the FIRST existing of these\n * worktree-root candidates (zed docs/src/ai/instructions.md order). A block\n * in AGENTS.md is silently ignored when e.g. `.cursorrules` exists, so the\n * probe targets the file Zed will actually pick; AGENTS.md is created only\n * when nothing shadows it.\n */\n private static readonly PROJECT_RULES_PROBE_ORDER = [\n \".rules\",\n \".cursorrules\",\n \".windsurfrules\",\n \".clinerules\",\n join(\".github\", \"copilot-instructions.md\"),\n \"AGENT.md\",\n \"AGENTS.md\",\n \"CLAUDE.md\",\n \"GEMINI.md\",\n ];\n\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"project\") {\n return super.memoryTargets(ctx); // user scope: personal AGENTS.md (base map)\n }\n for (const rel of ZedAdapter.PROJECT_RULES_PROBE_ORDER) {\n const candidate = join(ctx.projectDir, rel);\n if (existsSync(candidate)) {\n return [\n {\n path: candidate,\n reason: `zed first-match project rules file (${rel} shadows later candidates)`,\n },\n ];\n }\n }\n return [\n {\n path: join(ctx.projectDir, \"AGENTS.md\"),\n reason: \"AGENTS.md (created; no zed first-match rules file present)\",\n },\n ];\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for zed\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n // upsertServerInJson reads the WHOLE settings file, sets only\n // context_servers[<id>], and writes it back — preserving every other\n // top-level key and sibling context server (the merge contract).\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /** Render a normalized ServerDef into Zed's native context_servers entry. */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): ZedStdioServer | ZedHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n // Zed has no documented native interpolation token, so resolve every\n // ${env:VAR} to a literal at install time.\n // FLAT shape: `command` is a string, never a nested { path, args }.\n const entry: ZedStdioServer = { command: resolveEnvRefsDeep(command) };\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n return entry;\n }\n\n // sse / http (and any other remote transport) — Zed registers a URL.\n const entry: ZedHttpServer = { url: resolveEnvRefsDeep(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Zed documents no native interpolation token, so\n * resolve `${env:VAR}` references to literals at install time.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Skills surface ───────────────────────────────────────────────────────\n // Zed reads SKILL.md files from:\n // project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n // user scope → ~/.agents/skills/<name>/SKILL.md\n\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"skills\")\n : join(homedir(), \".agents\", \"skills\");\n }\n\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for zed\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\n );\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue;\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n private renderSkill(skill: SkillDef): string {\n return renderSkillMd(skill);\n }\n\n // ── Action surface (owned entries array-merged into tasks.json) ───────────\n // Zed reads tasks.json (zed.dev/docs/tasks): a JSON ARRAY of tasks\n // `{ label, command, args? }` spawned in the integrated terminal + invocable\n // from the command palette (`task: spawn`). Per AC action we add ONE task\n // whose `command` execs the home-bin action verb. Zed runs `command` in a\n // shell, so this is a HEADLESS exec (not Warp's paste-into-input).\n //\n // OWNERSHIP: tasks.json is a USER-OWNED array, so we never clobber it. We\n // read the whole array, upsert only OUR tasks (identity = isHomeBinActionCommand\n // on `command`, anchored to this connector id so a sibling connector's tasks\n // are foreign), and write back. Idempotent (byte-identical entry → skip).\n // Uninstall filters out ONLY our entries, leaving every foreign task intact.\n\n /** tasks.json path: <configDir>/tasks.json (~/.config/zed | <projectDir>/.zed). */\n private tasksPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"tasks.json\");\n }\n\n /** Render the owned task entry: minimal { label, command }. */\n private renderTask(trigger: ActionTrigger): ZedTask {\n return { label: trigger.label, command: trigger.command };\n }\n\n override installActions(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n if (connector.platforms[HOST]?.actions === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"actions disabled for zed\" }];\n }\n const triggers = this.actionTriggers(ctx);\n if (triggers.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no actions\" }];\n }\n\n const path = this.tasksPath(ctx);\n const symlink = this.symlinkPathWarning(path);\n if (symlink) return [symlink];\n\n // Overwrite guard: a present-but-unparseable tasks.json must never be blanked\n // (symmetric with the settings.json merge contract — see review-fixes tests).\n if (this.isPresentButUnparseable(path)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path,\n detail: `${path} is present but not parseable as JSON; left untouched (fix it, then re-run)`,\n },\n ];\n }\n\n // tasks.json IS a top-level array. A null parse means \"absent\" (create\n // fresh); a present non-array value was hand-edited to the wrong shape, so\n // warn-skip rather than clobber it (mirrors continue's mcpServers guard).\n const raw = this.readJson<unknown>(path);\n if (raw !== null && !Array.isArray(raw)) {\n return [\n {\n platform: this.id,\n action: \"warn\",\n path,\n detail: `${path} is not a JSON array of tasks; left untouched (fix it, then re-run)`,\n },\n ];\n }\n const list = (raw ?? []) as ZedTask[];\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n for (const trigger of triggers) {\n const entry = this.renderTask(trigger);\n // Identity is OUR action command (anchored to this connector id), NOT the\n // label — a user could relabel. Match the SPECIFIC action by its command,\n // which is unique per action id (one slot per action).\n const slot = list.findIndex(\n (t) => this.isOurTask(t, ctx) && t.command === entry.command,\n );\n if (slot < 0) {\n list.push(entry);\n mutated = true;\n changes.push({ platform: this.id, action: \"create\", path, detail: `tasks.json [${trigger.id}]` });\n } else if (JSON.stringify(list[slot]) === JSON.stringify(entry)) {\n changes.push({ platform: this.id, action: \"skip\", path, detail: `tasks.json [${trigger.id}]` });\n } else {\n list[slot] = entry;\n mutated = true;\n changes.push({ platform: this.id, action: \"update\", path, detail: `tasks.json [${trigger.id}]` });\n }\n }\n\n if (mutated && !dryRun) this.writeJson(path, list);\n return changes;\n }\n\n override uninstallActions(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n if (connector.actions.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no actions\" }];\n }\n\n const path = this.tasksPath(ctx);\n const raw = this.readJson<unknown>(path);\n if (raw === null || !Array.isArray(raw)) {\n return [{ platform: this.id, action: \"skip\", detail: \"tasks.json absent or not an array\" }];\n }\n\n const list = raw as ZedTask[];\n const kept = list.filter((t) => !this.isOurTask(t, ctx));\n if (kept.length === list.length) {\n return [{ platform: this.id, action: \"skip\", detail: \"no owned tasks in tasks.json\" }];\n }\n if (!dryRun) this.writeJson(path, kept);\n return [\n {\n platform: this.id,\n action: \"remove\",\n path,\n detail: `tasks.json (${list.length - kept.length} owned task(s) removed)`,\n },\n ];\n }\n\n /**\n * True when a task entry is OURS — its `command` is the home-bin action verb\n * for exactly this connector id (anchored so a shared-prefix id can't collide,\n * and the ` action ` verb so a future hook/serve task is never misread).\n */\n private isOurTask(task: ZedTask | undefined, ctx: InstallContext): boolean {\n return isHomeBinActionCommand(task?.command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Hooks (unavailable — Zed is mcp-only) ────────────────────────────────\n\n installHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Zed is mcp-only)\",\n },\n ];\n }\n\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: \"hooks unavailable (Zed is mcp-only)\",\n },\n ];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n return [\n {\n name: `${this.name}: settings.json present`,\n check: () =>\n existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\n },\n {\n name: `${this.name}: context server entry registered`,\n check: () => {\n // Only assert what the connector declares: a server-less connector —\n // e.g. a catalog-only bundle of agents/skills/commands — never writes\n // a context_servers entry, so its absence is healthy.\n if (!ctx.connector.server) {\n return { status: \"OK\", detail: \"no MCP server declared\" };\n }\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(settingsPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n if (!cfg || !bucket) {\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${settingsPath}` };\n }\n return connectorId in bucket\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\n : {\n status: \"FAIL\",\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${settingsPath}`,\n };\n },\n },\n ];\n }\n}\n\nexport const adapter = new ZedAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  openSqlite
4
- } from "./chunk-XZWMJLIT.js";
4
+ } from "./chunk-YT43MUSJ.js";
5
5
  import {
6
6
  firstExistingRoot
7
- } from "./chunk-KM2YXO6V.js";
7
+ } from "./chunk-O7SDRBVB.js";
8
8
  import {
9
9
  emptyTokens,
10
10
  normalizeWorkspaceKey,
11
11
  workspaceLabelFromKey
12
- } from "./chunk-7PSNXUFK.js";
12
+ } from "./chunk-XD7MY6HB.js";
13
13
 
14
14
  // src/usage/readers/zed.ts
15
15
  import { decompress } from "fzstd";
@@ -269,4 +269,4 @@ var zed_default = zedReader;
269
269
  export {
270
270
  zed_default as default
271
271
  };
272
- //# sourceMappingURL=zed-XXCNYOIN.js.map
272
+ //# sourceMappingURL=zed-XJFOOKCO.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/readers/zed.ts"],"sourcesContent":["/**\n * usage/readers/zed — Zed Agent hosted-thread usage reader (SQLite + zstd JSON).\n *\n * Faithful port of tokscale sessions/zed.rs. Zed persists one row per agent\n * thread in a `threads` table inside a single SQLite database:\n * • Linux/FreeBSD: $XDG_DATA_HOME/zed/threads/threads.db (~/.local/share/zed/…)\n * • macOS: ~/Library/Application Support/Zed/threads/threads.db\n * • Windows: %LOCALAPPDATA%\\Zed\\threads\\threads.db\n * (host roots, incl. the AGENT_CONNECTOR_ZED_DIR override, are resolved by\n * paths.ts hostRoots(\"zed\").)\n *\n * Only Zed-HOSTED model rows (provider == \"zed.dev\", case-insensitive) are\n * counted. External ACP agents are billed/logged by their own providers/CLIs, so\n * counting their Zed UI rows would double-count those sources.\n *\n * The thread payload is stored in a `data` BLOB whose `data_type` is either:\n * • \"json\" — the raw UTF-8 JSON bytes; or\n * • \"zstd\" — ZSTD-compressed JSON, decompressed here via fzstd's decompress().\n * Any other data_type, a failed zstd decode, or invalid JSON → the row is skipped\n * (fail-open). A decoded payload exceeding 32 MiB is rejected.\n *\n * One SELECT pulls every thread; the schema is backward-compatible — created_at,\n * folder_paths, folder_paths_order are OPTIONAL columns (older Zed builds omit\n * them). We probe `PRAGMA table_info(threads)` and substitute NULL for any column\n * that is absent so the SELECT never errors on an old schema:\n * SELECT id, updated_at, {created_at|NULL}, {folder_paths|NULL},\n * {folder_paths_order|NULL}, data_type, data FROM threads\n *\n * Token extraction (nested JSON in the decoded payload; reasoning always 0 — Zed's\n * TokenUsage has no reasoning field). Each TokenUsage object maps:\n * input = input_tokens\n * output = output_tokens\n * cacheRead = cache_read_input_tokens\n * cacheWrite = cache_creation_input_tokens\n * Primary source is `request_token_usage` (an object map keyed by request id, OR\n * an array): each entry with a positive total is summed and counted. When the\n * request usage total is > 0 we use it (messageCount = count, min 1). Otherwise we\n * fall back to a single `cumulative_token_usage` object (messageCount = 1). A\n * thread with no positive token total is dropped.\n *\n * Model: model.model (trimmed, required non-empty). Provider hard-coded \"zed.dev\"\n * (per zed.rs — the row is only kept when model.provider == \"zed.dev\"). Threads\n * with imported == true are skipped. Timestamp (port of timestamp_ms): the\n * created_at column, else the updated_at column, else the payload's updated_at —\n * each parsed via parse_timestamp_str (RFC3339 or numeric s/ms). Session id = the\n * `id` column (thread id), which also seeds the dedup key \"zed:<thread_id>\".\n * Project: folder_paths (newline-separated) selected by folder_paths_order\n * (comma-separated indices; lowest order wins) or the first path, normalized via\n * normalizeWorkspaceKey. Confidence is \"host-reported\".\n *\n * Fail-open: db missing/locked/unreadable/non-sqlite → openSqlite returns null →\n * []; a bad/zstd-undecodable/non-hosted row is skipped, never thrown.\n */\n\nimport { decompress } from \"fzstd\";\n\nimport type { TokenBreakdown, UsageReader, UsageRecord } from \"../types.js\";\nimport { emptyTokens } from \"../aggregate.js\";\nimport { normalizeWorkspaceKey, workspaceLabelFromKey } from \"../normalize.js\";\nimport { firstExistingRoot } from \"../paths.js\";\nimport { openSqlite } from \"../sqlite.js\";\n\nconst PLATFORM_ID = \"zed\" as const;\n/** Only Zed-hosted threads (provider == this) are counted (per zed.rs). */\nconst ZED_HOSTED_PROVIDER = \"zed.dev\";\n/** Reject a decoded thread payload larger than this (mirrors the Rust guard). */\nconst MAX_ZED_THREAD_JSON_BYTES = 32 * 1024 * 1024;\n\n/** The thread columns we read off each SQLite row (everything unknown). */\ninterface ZedThreadRow {\n id?: unknown;\n updated_at?: unknown;\n created_at?: unknown;\n folder_paths?: unknown;\n folder_paths_order?: unknown;\n data_type?: unknown;\n data?: unknown;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Schema probe + query build (backward-compat optional columns)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The set of column names on the `threads` table (empty on any probe error). */\nfunction threadColumns(db: { all(sql: string): Array<Record<string, unknown>> }): Set<string> {\n const cols = new Set<string>();\n for (const row of db.all(\"PRAGMA table_info(threads)\")) {\n // table_info's column-name field is `name`.\n const name = row.name;\n if (typeof name === \"string\") cols.add(name);\n }\n return cols;\n}\n\n/** `column` when present on the table, else the literal `NULL` (port of optional_column). */\nfunction optionalColumn(columns: Set<string>, column: string): string {\n return columns.has(column) ? column : \"NULL\";\n}\n\n/** Build the threads SELECT, substituting NULL for any absent optional column. */\nfunction buildThreadsQuery(columns: Set<string>): string {\n const createdAt = optionalColumn(columns, \"created_at\");\n const folderPaths = optionalColumn(columns, \"folder_paths\");\n const folderPathsOrder = optionalColumn(columns, \"folder_paths_order\");\n return (\n `SELECT id, updated_at, ${createdAt}, ${folderPaths}, ${folderPathsOrder}, ` +\n `data_type, data FROM threads`\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// BLOB decode (json / zstd → JSON value)\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Coerce a sql.js BLOB cell to a Uint8Array (sql.js returns BLOBs as Uint8Array;\n * be tolerant of Buffer / number[] just in case), or null when it is not bytes.\n */\nfunction toBytes(v: unknown): Uint8Array | null {\n if (v instanceof Uint8Array) return v;\n if (Array.isArray(v)) return Uint8Array.from(v as number[]);\n if (v instanceof ArrayBuffer) return new Uint8Array(v);\n return null;\n}\n\n/**\n * Decode the `data` BLOB to JSON bytes (port of decode_thread_json): \"json\"\n * passes the bytes through; \"zstd\" decompresses via fzstd. Returns null on an\n * unsupported data_type, a failed zstd decode, or an over-size payload (the row\n * is then skipped — fail-open).\n */\nfunction decodeThreadJson(dataType: string, data: Uint8Array): Uint8Array | null {\n switch (dataType.trim().toLowerCase()) {\n case \"json\": {\n if (data.length > MAX_ZED_THREAD_JSON_BYTES) return null;\n return data;\n }\n case \"zstd\": {\n let decoded: Uint8Array;\n try {\n decoded = decompress(data);\n } catch {\n return null; // undecodable zstd → skip the row (fail-open)\n }\n if (decoded.length > MAX_ZED_THREAD_JSON_BYTES) return null;\n return decoded;\n }\n default:\n return null; // unsupported data_type → skip\n }\n}\n\n/** Decode a UTF-8 byte payload to a parsed JSON value, or null on failure. */\nfunction parseJsonBytes(bytes: Uint8Array): unknown {\n let text: string;\n try {\n text = new TextDecoder(\"utf-8\", { fatal: false }).decode(bytes);\n } catch {\n return null;\n }\n try {\n return JSON.parse(text);\n } catch {\n return null;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Token usage extraction (port of thread_usage / token_usage_from_value)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Sum the five token dimensions of a breakdown. */\nfunction totalTokens(t: TokenBreakdown): number {\n return t.input + t.output + t.cacheRead + t.cacheWrite + t.reasoning;\n}\n\n/**\n * Coerce a TokenUsage field to a non-negative integer (port of usage_field):\n * accept a number or a numeric string; clamp ≥ 0; 0 on absence/garbage.\n */\nfunction usageField(obj: Record<string, unknown>, field: string): number {\n const v = obj[field];\n let n: number;\n if (typeof v === \"number\") n = v;\n else if (typeof v === \"string\") n = Number(v);\n else return 0;\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.trunc(n));\n}\n\n/**\n * Build a TokenBreakdown from a single TokenUsage value (port of\n * token_usage_from_value); reasoning stays 0 (not present in Zed's schema).\n * Returns null when the value is not an object.\n */\nfunction tokenUsageFromValue(value: unknown): TokenBreakdown | null {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) return null;\n const obj = value as Record<string, unknown>;\n const tokens = emptyTokens();\n tokens.input = usageField(obj, \"input_tokens\");\n tokens.output = usageField(obj, \"output_tokens\");\n tokens.cacheRead = usageField(obj, \"cache_read_input_tokens\");\n tokens.cacheWrite = usageField(obj, \"cache_creation_input_tokens\");\n // reasoning stays 0.\n return tokens;\n}\n\n/**\n * Sum every positive TokenUsage in `request_token_usage` (port of\n * sum_request_token_usage). The value may be an object map (keyed by request id)\n * or an array; non-object members and zero-total entries are skipped. Returns the\n * summed breakdown and the count of positive entries.\n */\nfunction sumRequestTokenUsage(value: unknown): { tokens: TokenBreakdown; count: number } {\n const total = emptyTokens();\n let count = 0;\n\n let usages: unknown[];\n if (Array.isArray(value)) {\n usages = value;\n } else if (typeof value === \"object\" && value !== null) {\n usages = Object.values(value as Record<string, unknown>);\n } else {\n return { tokens: total, count };\n }\n\n for (const usageValue of usages) {\n const usage = tokenUsageFromValue(usageValue);\n if (usage === null) continue;\n if (totalTokens(usage) <= 0) continue;\n total.input += usage.input;\n total.output += usage.output;\n total.cacheRead += usage.cacheRead;\n total.cacheWrite += usage.cacheWrite;\n total.reasoning += usage.reasoning;\n count += 1;\n }\n\n return { tokens: total, count };\n}\n\n/**\n * Resolve a thread's usage (port of thread_usage): prefer the summed\n * request_token_usage when its total is > 0 (messageCount = count, min 1),\n * otherwise fall back to a single cumulative_token_usage (messageCount = 1).\n * Returns null when neither source yields a positive total.\n */\nfunction threadUsage(thread: Record<string, unknown>): { tokens: TokenBreakdown; messageCount: number } | null {\n const { tokens: requestTokens, count } = sumRequestTokenUsage(thread.request_token_usage);\n if (totalTokens(requestTokens) > 0) {\n return { tokens: requestTokens, messageCount: Math.max(1, count) };\n }\n\n const cumulative = tokenUsageFromValue(thread.cumulative_token_usage);\n if (cumulative !== null && totalTokens(cumulative) > 0) {\n return { tokens: cumulative, messageCount: 1 };\n }\n return null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Timestamp (port of timestamp_ms + parse_timestamp_str)\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Parse a timestamp string to epoch ms (port of parse_timestamp_str): RFC3339\n * first, else a positive integer disambiguated s↔ms (≥ 1e12 → ms, else × 1000).\n * Returns null on a non-positive / unparseable value.\n */\nfunction parseTimestampStr(value: string): number | null {\n const iso = Date.parse(value);\n if (!Number.isNaN(iso)) return iso;\n\n // Strict integer parse (the Rust path uses i64::from_str_radix-style parsing).\n if (/^[+-]?\\d+$/.test(value.trim())) {\n const numeric = Number(value.trim());\n if (!Number.isFinite(numeric) || numeric <= 0) return null;\n return numeric >= 1_000_000_000_000 ? Math.trunc(numeric) : Math.trunc(numeric * 1000);\n }\n return null;\n}\n\n/** A cell that should be a string, else undefined. */\nfunction asString(v: unknown): string | undefined {\n return typeof v === \"string\" ? v : undefined;\n}\n\n/**\n * Resolve the thread timestamp (port of timestamp_ms): created_at column, else\n * updated_at column, else the payload's updated_at — first that parses. Returns\n * null when none yields a valid timestamp.\n */\nfunction timestampMs(row: ZedThreadRow, thread: Record<string, unknown>): number | null {\n const createdAt = asString(row.created_at);\n if (createdAt !== undefined) {\n const ms = parseTimestampStr(createdAt);\n if (ms !== null) return ms;\n }\n const updatedAt = asString(row.updated_at);\n if (updatedAt !== undefined) {\n const ms = parseTimestampStr(updatedAt);\n if (ms !== null) return ms;\n }\n const payloadUpdatedAt = asString(thread.updated_at);\n if (payloadUpdatedAt !== undefined) {\n const ms = parseTimestampStr(payloadUpdatedAt);\n if (ms !== null) return ms;\n }\n return null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Project / workspace (port of workspace_key_from_folders)\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Pick the index of the lowest-order path (port of first_ordered_path_index):\n * `order` is a comma-separated list of indices aligned positionally with the\n * paths; we take the position whose parsed order value is smallest, ignoring\n * positions beyond the path count. Returns undefined when nothing parses.\n */\nfunction firstOrderedPathIndex(order: string, pathCount: number): number | undefined {\n let bestIndex: number | undefined;\n let bestOrder = Number.POSITIVE_INFINITY;\n const parts = order.split(\",\");\n for (let index = 0; index < parts.length; index++) {\n if (index >= pathCount) continue;\n const raw = (parts[index] as string).trim();\n if (!/^\\d+$/.test(raw)) continue;\n const value = Number(raw);\n if (!Number.isFinite(value)) continue;\n if (value < bestOrder) {\n bestOrder = value;\n bestIndex = index;\n }\n }\n return bestIndex;\n}\n\n/**\n * Derive a normalized workspace key from the folder columns (port of\n * workspace_key_from_folders): split `paths` on newlines (trimmed, non-empty),\n * select by `order` (lowest-order index) or the first path, then normalize.\n */\nfunction workspaceKeyFromFolders(paths: unknown, order: unknown): string | undefined {\n if (typeof paths !== \"string\") return undefined;\n const list = paths\n .split(/\\r?\\n/)\n .map((p) => p.trim())\n .filter((p) => p !== \"\");\n if (list.length === 0) return undefined;\n\n let selected: string | undefined;\n if (typeof order === \"string\") {\n const idx = firstOrderedPathIndex(order, list.length);\n if (idx !== undefined) selected = list[idx];\n }\n if (selected === undefined) selected = list[0];\n\n return normalizeWorkspaceKey(selected as string);\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Row → record (port of parse_thread_row)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Parse one threads row into a UsageRecord, or null when it should be skipped. */\nfunction parseThreadRow(row: ZedThreadRow): UsageRecord | null {\n const id = asString(row.id);\n if (id === undefined || id === \"\") return null;\n\n const dataType = asString(row.data_type);\n if (dataType === undefined) return null;\n const dataBytes = toBytes(row.data);\n if (dataBytes === null) return null;\n\n const jsonBytes = decodeThreadJson(dataType, dataBytes);\n if (jsonBytes === null) return null; // unsupported / undecodable / oversize → skip\n\n const parsed = parseJsonBytes(jsonBytes);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) return null;\n const thread = parsed as Record<string, unknown>;\n\n // Skip imported threads.\n if (thread.imported === true) return null;\n\n // Require a hosted (zed.dev) model with a non-empty model id.\n const model = thread.model;\n if (typeof model !== \"object\" || model === null || Array.isArray(model)) return null;\n const modelObj = model as Record<string, unknown>;\n const provider = asString(modelObj.provider);\n if (provider === undefined) return null;\n if (provider.trim().toLowerCase() !== ZED_HOSTED_PROVIDER) return null;\n\n const modelRaw = asString(modelObj.model);\n if (modelRaw === undefined) return null;\n const modelId = modelRaw.trim();\n if (modelId === \"\") return null;\n\n const usage = threadUsage(thread);\n if (usage === null) return null; // no positive token total → drop\n\n const ts = timestampMs(row, thread);\n if (ts === null) return null;\n\n const record: UsageRecord = {\n platformId: PLATFORM_ID,\n modelId,\n providerId: ZED_HOSTED_PROVIDER,\n sessionId: id,\n tokens: usage.tokens,\n ts,\n messageCount: usage.messageCount,\n dedupKey: `zed:${id}`,\n confidence: \"host-reported\",\n };\n\n const projectKey = workspaceKeyFromFolders(row.folder_paths, row.folder_paths_order);\n if (projectKey !== undefined) {\n record.projectKey = projectKey;\n const label = workspaceLabelFromKey(projectKey);\n if (label !== undefined) record.projectLabel = label;\n }\n\n return record;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Reader\n// ─────────────────────────────────────────────────────────────────────────\n\n/** The Zed Agent hosted-thread usage reader singleton. */\nconst zedReader: UsageReader = {\n platformId: PLATFORM_ID,\n kind: \"local\",\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\n const dbPath = firstExistingRoot(PLATFORM_ID);\n if (dbPath === undefined) return []; // no threads.db → fail-open\n\n const db = await openSqlite(dbPath);\n if (db === null) return []; // missing / locked / unreadable / non-sqlite → fail-open\n\n try {\n const columns = threadColumns(db);\n const query = buildThreadsQuery(columns);\n const rows = db.all(query); // bad SQL / schema mismatch → [] (fail-open)\n const records: UsageRecord[] = [];\n\n for (const raw of rows) {\n let record: UsageRecord | null;\n try {\n record = parseThreadRow(raw as ZedThreadRow);\n } catch {\n continue; // any per-row decode failure → skip (fail-open)\n }\n if (record === null) continue;\n if (sinceMs !== undefined && record.ts < sinceMs) continue;\n records.push(record);\n }\n\n return records;\n } finally {\n db.close();\n }\n },\n};\n\nexport default zedReader;\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,69 +1,69 @@
1
- {
2
- "name": "@ken-jo/agent-connector",
3
- "version": "0.4.98",
4
- "type": "module",
5
- "description": "SDK/runtime for branded MCP packages: declare your server + hooks once, install across the current AI-agent coverage matrix, and collect local-first token telemetry.",
6
- "keywords": [
7
- "mcp",
8
- "model-context-protocol",
9
- "hooks",
10
- "claude-code",
11
- "codex",
12
- "cursor",
13
- "opencode",
14
- "copilot",
15
- "gemini-cli",
16
- "telemetry",
17
- "tokens",
18
- "multi-platform"
19
- ],
20
- "license": "Apache-2.0",
21
- "author": "KenJo",
22
- "repository": {
23
- "type": "git",
24
- "url": "git+https://github.com/ken-jo/agent-connector.git"
25
- },
26
- "homepage": "https://agent-connector.ai",
27
- "bugs": {
28
- "url": "https://github.com/ken-jo/agent-connector/issues"
29
- },
30
- "bin": {
31
- "agent-connector": "dist/cli.js"
32
- },
33
- "exports": {
34
- ".": {
35
- "types": "./dist/index.d.ts",
36
- "import": "./dist/index.js"
37
- },
38
- "./runtime": {
39
- "types": "./dist/runtime/index.d.ts",
40
- "import": "./dist/runtime/index.js"
41
- },
42
- "./sdk": {
43
- "types": "./dist/sdk/index.d.ts",
44
- "import": "./dist/sdk/index.js"
45
- },
46
- "./sdk/test": {
47
- "types": "./dist/sdk/test.d.ts",
48
- "import": "./dist/sdk/test.js"
49
- },
50
- "./cli": {
51
- "types": "./dist/cli/sdk.d.ts",
52
- "import": "./dist/cli/sdk.js"
53
- },
54
- "./package.json": "./package.json"
55
- },
56
- "files": [
57
- "dist",
58
- "NOTICE"
59
- ],
60
- "engines": {
61
- "node": ">=18.17"
62
- },
63
- "workspaces": [
64
- "examples/*"
65
- ],
66
- "scripts": {
1
+ {
2
+ "name": "@ken-jo/agent-connector",
3
+ "version": "0.4.99",
4
+ "type": "module",
5
+ "description": "SDK/runtime for branded MCP packages: declare your server + hooks once, install across the current AI-agent coverage matrix, and collect local-first token telemetry.",
6
+ "keywords": [
7
+ "mcp",
8
+ "model-context-protocol",
9
+ "hooks",
10
+ "claude-code",
11
+ "codex",
12
+ "cursor",
13
+ "opencode",
14
+ "copilot",
15
+ "gemini-cli",
16
+ "telemetry",
17
+ "tokens",
18
+ "multi-platform"
19
+ ],
20
+ "license": "Apache-2.0",
21
+ "author": "KenJo",
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/ken-jo/agent-connector.git"
25
+ },
26
+ "homepage": "https://agent-connector.ai",
27
+ "bugs": {
28
+ "url": "https://github.com/ken-jo/agent-connector/issues"
29
+ },
30
+ "bin": {
31
+ "agent-connector": "dist/cli.js"
32
+ },
33
+ "exports": {
34
+ ".": {
35
+ "types": "./dist/index.d.ts",
36
+ "import": "./dist/index.js"
37
+ },
38
+ "./runtime": {
39
+ "types": "./dist/runtime/index.d.ts",
40
+ "import": "./dist/runtime/index.js"
41
+ },
42
+ "./sdk": {
43
+ "types": "./dist/sdk/index.d.ts",
44
+ "import": "./dist/sdk/index.js"
45
+ },
46
+ "./sdk/test": {
47
+ "types": "./dist/sdk/test.d.ts",
48
+ "import": "./dist/sdk/test.js"
49
+ },
50
+ "./cli": {
51
+ "types": "./dist/cli/sdk.d.ts",
52
+ "import": "./dist/cli/sdk.js"
53
+ },
54
+ "./package.json": "./package.json"
55
+ },
56
+ "files": [
57
+ "dist",
58
+ "NOTICE"
59
+ ],
60
+ "engines": {
61
+ "node": ">=18.17"
62
+ },
63
+ "workspaces": [
64
+ "examples/*"
65
+ ],
66
+ "scripts": {
67
67
  "build": "tsup",
68
68
  "dev": "tsx src/cli/index.ts",
69
69
  "typecheck": "tsc --noEmit",
@@ -74,25 +74,25 @@
74
74
  "generate:site-verification": "node scripts/generate-site-verification-results.mjs",
75
75
  "generate:site-release": "node scripts/generate-site-release-status.mjs",
76
76
  "verify:host": "node scripts/verify-host.mjs",
77
- "prepublishOnly": "npm run typecheck && npm run build"
78
- },
79
- "dependencies": {
80
- "@iarna/toml": "^2.2.5",
81
- "fzstd": "^0.1.1",
82
- "gpt-tokenizer": "^2.9.0",
83
- "sql.js": "^1.14.1",
84
- "yaml": "^2.9.0"
85
- },
86
- "devDependencies": {
87
- "@types/node": "^22.10.0",
88
- "tsup": "^8.3.5",
89
- "tsx": "^4.19.2",
90
- "typescript": "^5.7.2",
91
- "vite": "6.4.3",
92
- "vitest": "^3.2.6"
93
- },
94
- "overrides": {
95
- "esbuild": "0.28.1",
96
- "vite": "6.4.3"
97
- }
98
- }
77
+ "prepublishOnly": "npm run typecheck && npm run build"
78
+ },
79
+ "dependencies": {
80
+ "@iarna/toml": "^2.2.5",
81
+ "fzstd": "^0.1.1",
82
+ "gpt-tokenizer": "^2.9.0",
83
+ "sql.js": "^1.14.1",
84
+ "yaml": "^2.9.0"
85
+ },
86
+ "devDependencies": {
87
+ "@types/node": "^22.10.0",
88
+ "tsup": "^8.3.5",
89
+ "tsx": "^4.19.2",
90
+ "typescript": "^5.7.2",
91
+ "vite": "6.4.3",
92
+ "vitest": "^3.2.6"
93
+ },
94
+ "overrides": {
95
+ "esbuild": "0.28.1",
96
+ "vite": "6.4.3"
97
+ }
98
+ }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/cli/commands/action.ts"],"sourcesContent":["/**\r\n * cli/commands/action — the universal user-invokable action entrypoint.\r\n *\r\n * agent-connector action <platform> <actionId> --connector <id>\r\n *\r\n * A host-native affordance or a manual command points at the single stable home\n * binary (via core/spawn.buildHomeBinActionCommand). This command parses the\n * positionals + --connector, dispatches through runAction, writes any\n * stdout/stderr the action produced, and exits with its code. It reads NO stdin\n * (an action takes no host payload, unlike a hook or status line).\n *\r\n * USER-TRIGGERED is the runtime's contract: unlike the fail-open hook command,\r\n * an unknown action id or a throwing run surfaces as exit 1 + a stderr message —\r\n * the user invoked it deliberately, so the failure is shown, never swallowed.\r\n */\r\n\r\nimport { parseArgs } from \"node:util\";\r\n\r\nimport { runAction } from \"../../runtime/index.js\";\r\nimport { fail } from \"../app.js\";\r\n\r\nexport async function run(argv: string[]): Promise<number> {\r\n const { values, positionals } = parseArgs({\r\n args: argv,\r\n options: {\r\n connector: { type: \"string\" },\r\n },\r\n allowPositionals: true,\r\n });\r\n\r\n const platformId = positionals[0];\r\n const actionId = positionals[1];\r\n if (!platformId || !actionId) {\r\n return fail(\"usage: agent-connector action <platform> <actionId> --connector <id>\");\r\n }\r\n const connectorId = values.connector;\r\n if (!connectorId || connectorId.trim() === \"\") {\r\n return fail(\"action requires --connector <id>\");\r\n }\r\n\r\n const reply = await runAction({ platformId, actionId, connectorId });\r\n if (reply.stdout !== undefined && reply.stdout !== \"\") {\r\n process.stdout.write(reply.stdout.endsWith(\"\\n\") ? reply.stdout : `${reply.stdout}\\n`);\r\n }\r\n if (reply.stderr !== undefined && reply.stderr !== \"\") {\r\n process.stderr.write(reply.stderr.endsWith(\"\\n\") ? reply.stderr : `${reply.stderr}\\n`);\r\n }\r\n process.exit(reply.exitCode);\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAgBA,SAAS,iBAAiB;AAK1B,eAAsB,IAAI,MAAiC;AACzD,QAAM,EAAE,QAAQ,YAAY,IAAI,UAAU;AAAA,IACxC,MAAM;AAAA,IACN,SAAS;AAAA,MACP,WAAW,EAAE,MAAM,SAAS;AAAA,IAC9B;AAAA,IACA,kBAAkB;AAAA,EACpB,CAAC;AAED,QAAM,aAAa,YAAY,CAAC;AAChC,QAAM,WAAW,YAAY,CAAC;AAC9B,MAAI,CAAC,cAAc,CAAC,UAAU;AAC5B,WAAO,KAAK,sEAAsE;AAAA,EACpF;AACA,QAAM,cAAc,OAAO;AAC3B,MAAI,CAAC,eAAe,YAAY,KAAK,MAAM,IAAI;AAC7C,WAAO,KAAK,kCAAkC;AAAA,EAChD;AAEA,QAAM,QAAQ,MAAM,UAAU,EAAE,YAAY,UAAU,YAAY,CAAC;AACnE,MAAI,MAAM,WAAW,UAAa,MAAM,WAAW,IAAI;AACrD,YAAQ,OAAO,MAAM,MAAM,OAAO,SAAS,IAAI,IAAI,MAAM,SAAS,GAAG,MAAM,MAAM;AAAA,CAAI;AAAA,EACvF;AACA,MAAI,MAAM,WAAW,UAAa,MAAM,WAAW,IAAI;AACrD,YAAQ,OAAO,MAAM,MAAM,OAAO,SAAS,IAAI,IAAI,MAAM,SAAS,GAAG,MAAM,MAAM;AAAA,CAAI;AAAA,EACvF;AACA,UAAQ,KAAK,MAAM,QAAQ;AAC7B;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/adapters/amazon-q/index.ts"],"sourcesContent":["/**\r\n * adapters/amazon-q — Amazon Q Developer CLI platform adapter.\r\n *\r\n * Amazon Q Developer CLI (`q` / `qchat`) is a **json-stdio** host. It exposes a\r\n * real hooks layer (agentSpawn / userPromptSubmit / preToolUse / postToolUse /\r\n * stop, JSON-over-STDIN, exit-code 0/2 contract — primary-verified via\r\n * aws.github.io/amazon-q-developer-cli agent-format → Hooks Field). The hook\r\n * STDIN+exit contract is IDENTICAL to the sibling AWS host kiro; only the WRITE\r\n * shape differs (see below).\r\n *\r\n * Hooks live ONLY in per-agent config JSON files — there is NO global hooks.json:\r\n * user → ~/.aws/amazonq/cli-agents/<name>.json\r\n * project → <projectDir>/.amazonq/cli-agents/<name>.json\r\n * Because hooks have no global file, AC must target a SPECIFIC agent file. We\r\n * mirror kiro's per-agent selection rule and write the built-in default agent\r\n * file — `cli-agents/q_cli_default.json`. Amazon Q auto-loads the built-in\r\n * `q_cli_default` agent for a new chat session (the built-in default is otherwise\r\n * in-memory); a file literally named `default.json` would be an INACTIVE custom\r\n * agent named `default` the user must explicitly select (`q chat --agent default`),\r\n * so hooks there would never fire — exactly the trap kiro avoids with\r\n * `kiro_default.json`. Primary-verified via the agent-format default\r\n * knowledge-base dir `~/.aws/amazonq/knowledge_bases/q_cli_default/`.\r\n * A PROJECT install writes a project-scoped `q_cli_default` agent file\r\n * (<projectDir>/.amazonq/cli-agents/q_cli_default.json) that SHADOWS the\r\n * user-global one — a local `q_cli_default` takes precedence and auto-loads.\r\n *\r\n * The `hooks` field is an OBJECT keyed by trigger name (NOT kiro's matcher-grouped\r\n * array). Each entry is `{ command, matcher? }` — NO `type` field; `matcher` is\r\n * only meaningful for preToolUse/postToolUse:\r\n * \"hooks\": {\r\n * \"agentSpawn\": [{ \"command\": \"<cmd>\" }],\r\n * \"userPromptSubmit\": [{ \"command\": \"<cmd>\" }],\r\n * \"preToolUse\": [{ \"command\": \"<cmd>\", \"matcher\": \"<toolNamePattern?>\" }],\r\n * \"postToolUse\": [{ \"command\": \"<cmd>\", \"matcher\": \"<optional>\" }],\r\n * \"stop\": [{ \"command\": \"<cmd>\" }]\r\n * }\r\n * AC MERGES into this object: it preserves ALL other agent fields (name /\r\n * description / mcpServers / tools / resources / user hooks) and only upserts its\r\n * own home-bin command into each mapped trigger array, identified by the command\r\n * string for idempotent re-install and clean uninstall (an emptied trigger key is\r\n * dropped). The shared object-map hook-array merge engine (base.ts\r\n * upsertHookEntries / removeHookEntries) handles this FLAT object-of-arrays shape\r\n * directly — the descriptor renders a flat `{ command, matcher? }` entry.\r\n *\r\n * Canonical AC event → Amazon Q trigger:\r\n * SessionStart → agentSpawn\r\n * UserPromptSubmit → userPromptSubmit\r\n * PreToolUse → preToolUse\r\n * PostToolUse → postToolUse\r\n * Stop → stop\r\n * Events with no Amazon Q trigger (PreCompact / SessionEnd / Notification and the\r\n * E1 extension events) warn-skip at install time.\r\n *\r\n * Hook protocol is EXIT-CODE based (identical to kiro): exit 0 = allow, exit 2 =\r\n * block (preToolUse only; STDERR is returned to the LLM). Amazon Q cannot rewrite\r\n * tool args or output, so canModifyArgs / canModifyOutput are false.\r\n * Context injection → exit 0 with the guidance written as PLAIN STDOUT (NOT a\r\n * JSON envelope). Amazon Q adds a hook's STDOUT to the agent's context ONLY for\r\n * agentSpawn and userPromptSubmit (\"STDOUT is added to agent's context\"); for\r\n * preToolUse / postToolUse / stop the docs say STDOUT is \"captured but not shown\r\n * to user\" — no context channel — so a `context` decision on those degrades to a\r\n * plain exit-0 pass-through. Primary-verified via aws/amazon-q-developer-cli\r\n * docs/hooks.md (Hook Output + per-event Exit Code Behavior); there is NO\r\n * hookSpecificOutput / hookEventName / additionalContext envelope anywhere in\r\n * Amazon Q's schema.\r\n *\r\n * MCP config (legacy files, primary-verified via AWS docs) — UNCHANGED by the\r\n * hooks wiring; the MCP server surface still targets the global/workspace mcp.json:\r\n * - user scope → ~/.aws/amazonq/mcp.json (global; applies to all workspaces)\r\n * - project scope → <projectDir>/.amazonq/mcp.json (local workspace)\r\n * Both are JSON, root key \"mcpServers\". Amazon Q reads BOTH when both exist\r\n * and merges them (union); workspace wins on same-name conflict with a warning.\r\n *\r\n * Server entry shape (primary-verified):\r\n * - stdio: { command: string; args?: string[]; env?: { [k: string]: string };\r\n * timeout?: number } (timeout in MILLISECONDS, e.g. 60000;\r\n * transport inferred from presence of `command` — no `type` key)\r\n * - http: { type: \"http\"; url: string }\r\n * (the remote/HTTP shape is written with an explicit `type: \"http\"`\r\n * discriminator + `url`, per command-line-mcp-config-CLI.html. No\r\n * `headers` field — Amazon Q remote auth is OAuth, not static\r\n * headers — and no `disabled` flag.)\r\n *\r\n * Path resolution — NOTE the nested user scope:\r\n * - user: join(homedir(), \".aws\", \"amazonq\") (two path segments)\r\n * - project: join(projectDir, \".amazonq\") (single dotDir, no .aws)\r\n * homedir() handles USERPROFILE on Windows automatically; no manual branch.\r\n *\r\n * Env interpolation: Amazon Q has no documented native ${env:VAR} token;\r\n * resolve all references to literals at install time (the safe path, same as\r\n * droid/crush).\r\n *\r\n * Memory / rules (primary-verified — docs.aws.amazon.com context-project-rules):\r\n * Project rules are plain Markdown files in <projectDir>/.amazonq/rules; Amazon\r\n * Q \"will automatically use them as context whenever a developer chats with\r\n * Amazon Q within your project\". NO frontmatter required. We write a DEDICATED\r\n * agent-connector-owned file there (`.amazonq/rules/agent-connector.md`),\r\n * mirroring the cline `.clinerules/agent-connector.md` approach: memoryTargets()\r\n * points at the dedicated file and the base managed-block engine performs the\r\n * surgical, hash-stamped, uninstall-reversible write. PROJECT SCOPE ONLY — the\r\n * AWS docs do not cleanly document a user/global rules directory for the CLI\r\n * (a `~/.aws/amazonq/.../rules` path is unverified), so user scope returns [] →\r\n * the base installMemory skip-warns rather than writing into an unread path.\r\n *\r\n * Hook config path targets the built-in default agent file\r\n * (cli-agents/q_cli_default.json), which is a DIFFERENT file from the MCP mcp.json\r\n * (getHookConfigPath ≠ getServerConfigPath), mirroring kiro's split surfaces.\r\n */\r\n\r\nimport { existsSync, statSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostToolUseEvent,\r\n PreToolUseEvent,\r\n ServerDef,\r\n SessionStartEvent,\r\n StopEvent,\r\n SubagentDef,\r\n Transport,\r\n UserPromptSubmitEvent,\r\n} from \"../../core/types.js\";\r\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\r\nimport {\r\n buildWrappedStdio,\r\n isHomeBinHookCommand,\r\n} from \"../../core/spawn.js\";\r\n\r\nconst HOST: PlatformId = \"amazon-q\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * The built-in default agent file AC registers hooks on. Amazon Q auto-loads the\r\n * built-in `q_cli_default` agent for a new chat session (the built-in default is\r\n * otherwise in-memory). A file literally named `default.json` would be an INACTIVE\r\n * custom agent named `default` that the user must explicitly select\r\n * (`q chat --agent default`), so hooks merged there would never fire — we register\r\n * on `q_cli_default.json` instead (mirrors kiro's `kiro_default.json` selection;\r\n * primary-verified via the agent-format default knowledge-base dir\r\n * `knowledge_bases/q_cli_default/`).\r\n */\r\nconst DEFAULT_AGENT_FILE = \"q_cli_default.json\";\r\n\r\n/**\r\n * The agent NAME (filename stem) AC reserves for the hooks / built-in default\r\n * agent (`cli-agents/q_cli_default.json`). A connector subagent declared with\r\n * this exact name would resolve to the SAME file and clobber the hooks agent, so\r\n * installSubagents REFUSES it (skip-warn) and uninstallSubagents never touches it.\r\n */\r\nconst RESERVED_AGENT_NAME = \"q_cli_default\";\r\n\r\n/**\r\n * Amazon Q native hook trigger names (the keys under an agent file's `hooks`\r\n * object). Only the triggers Amazon Q fires for the json-stdio command paradigm.\r\n */\r\nconst Q_TRIGGER = {\r\n preToolUse: \"preToolUse\",\r\n postToolUse: \"postToolUse\",\r\n agentSpawn: \"agentSpawn\",\r\n userPromptSubmit: \"userPromptSubmit\",\r\n stop: \"stop\",\r\n} as const;\r\n\r\n/**\r\n * Map canonical event names → Amazon Q's native trigger names. Only mapped\r\n * events are present; PreCompact / SessionEnd / Notification and the E1\r\n * extension events have no Amazon Q equivalent → warn-skip at install time.\r\n */\r\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\r\n SessionStart: Q_TRIGGER.agentSpawn,\r\n UserPromptSubmit: Q_TRIGGER.userPromptSubmit,\r\n PreToolUse: Q_TRIGGER.preToolUse,\r\n PostToolUse: Q_TRIGGER.postToolUse,\r\n Stop: Q_TRIGGER.stop,\r\n};\r\n\r\n/** Triggers whose `matcher` is meaningful (tool-name pattern). Others omit it. */\r\nconst MATCHER_TRIGGERS: ReadonlySet<string> = new Set([\r\n Q_TRIGGER.preToolUse,\r\n Q_TRIGGER.postToolUse,\r\n]);\r\n\r\n/**\r\n * Amazon Q triggers whose hook STDOUT is added to the agent's context: agentSpawn\r\n * (≈ SessionStart) and userPromptSubmit (docs/hooks.md — both say \"STDOUT is added\r\n * to agent's context\"). For preToolUse / postToolUse / stop the docs say STDOUT is\r\n * \"captured but not shown to user\" — no context channel — so a `context` decision\r\n * on those degrades to a plain exit-0 pass-through.\r\n * Ref: aws/amazon-q-developer-cli docs/hooks.md (per-event Exit Code Behavior).\r\n */\r\nconst CONTEXT_TRIGGERS: ReadonlySet<string> = new Set([\r\n Q_TRIGGER.agentSpawn,\r\n Q_TRIGGER.userPromptSubmit,\r\n]);\r\n\r\n/**\r\n * A single Amazon Q native hook entry: FLAT `{ command, matcher? }` (NO `type`\r\n * field — unlike kiro's matcher-grouped nested shape).\r\n */\r\ninterface AmazonQHookEntry {\r\n command: string;\r\n matcher?: string;\r\n}\r\n\r\n/** The shape of an Amazon Q agent file (only the parts we touch). */\r\ninterface AmazonQAgentFile {\r\n hooks?: Record<string, AmazonQHookEntry[]>;\r\n [key: string]: unknown;\r\n}\r\n\r\n/**\r\n * Raw Amazon Q CLI hook stdin payload (snake_case wire fields).\r\n *\r\n * PRIMARY-VERIFIED against aws/amazon-q-developer-cli\r\n * crates/chat-cli/src/cli/chat/cli/hooks.rs:300-321 (run_hook builds `hook_input`)\r\n * and docs/hooks.md:14-107 (per-event input examples). The host serializes ONLY:\r\n * - hook_event_name + cwd (always)\r\n * - prompt (userPromptSubmit only)\r\n * - tool_name + tool_input + tool_response (pre/postToolUse only; response optional)\r\n * `connector` is injected by AC's own hook-command argv, not the host.\r\n *\r\n * Host GAPS (fields the host NEVER serializes — do NOT add reads for these):\r\n * - session_id : no session id on stdin → sessionId stays \"\".\r\n * - source : agentSpawn carries no start-reason discriminator; the Rust\r\n * hook::Source enum is config-grouping, never serialized.\r\n * - stop_hook_active: stop payload is exactly {hook_event_name, cwd}.\r\n */\r\ninterface AmazonQWireInput {\r\n connector?: unknown;\r\n hook_event_name?: string;\r\n cwd?: string;\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n tool_response?: unknown;\r\n prompt?: string;\r\n}\r\n\r\n/**\r\n * Native MCP server entry shapes Amazon Q accepts under `mcpServers`.\r\n * - stdio: BARE shape — NO `type` discriminator and NO `disabled` flag; the\r\n * transport is inferred from the presence of `command`. timeout is in\r\n * MILLISECONDS (pass timeoutMs through unchanged, do NOT divide).\r\n * - http: REMOTE shape — explicit `type: \"http\"` + `url`\r\n * (command-line-mcp-config-CLI.html). NO `headers` (remote auth is OAuth,\r\n * not static headers) and NO `disabled` flag.\r\n */\r\ninterface AmazonQStdioServer {\r\n command: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n timeout?: number;\r\n}\r\ninterface AmazonQHttpServer {\r\n type: \"http\";\r\n url: string;\r\n}\r\n\r\nexport class AmazonQAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Amazon Q Developer CLI\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: WIRED. Amazon Q reads `.amazonq/rules` (NOT AGENTS.md), so\r\n // the AGENTS.md-first BaseAdapter default does not apply — memoryTargets()\r\n // below overrides it to write a DEDICATED agent-connector-owned file\r\n // (<projectDir>/.amazonq/rules/agent-connector.md, plain Markdown, no\r\n // frontmatter — auto-applied as context per the AWS docs). Project scope\r\n // only; user scope skip-warns (no verified user/global rules dir).\r\n supportsMemory: true,\r\n //\r\n // Hooks: Amazon Q fires agentSpawn / userPromptSubmit / preToolUse /\r\n // postToolUse / stop (mapped from SessionStart / UserPromptSubmit /\r\n // PreToolUse / PostToolUse / Stop). It has no PreCompact / SessionEnd /\r\n // Notification equivalent, nor the E1 extension events (PermissionRequest /\r\n // PostToolUseFailure / SubagentStart / SubagentStop) — those warn-skip.\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: false,\r\n sessionStart: true,\r\n sessionEnd: false,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: false,\r\n // Exit-code protocol only — a hook can allow (0) or block (2), but it CANNOT\r\n // rewrite tool args or output.\r\n canModifyArgs: false,\r\n canModifyOutput: false,\r\n // agentSpawn / userPromptSubmit add a hook's plain STDOUT to the agent's\r\n // context (no JSON envelope) — primary-verified via docs/hooks.md.\r\n canInjectSessionContext: true,\r\n // Amazon Q registers stdio + Streamable HTTP MCP servers (primary-verified).\r\n transports: [\"stdio\", \"http\"],\r\n // Content surfaces:\r\n // subagents: WIRED. Amazon Q's \"agents\" are per-agent JSON files where the\r\n // FILENAME (minus .json) IS the agent name (primary-verified via the CLI\r\n // repo docs/agent-file-locations.md + docs/agent-format.md). AC maps each\r\n // connector SubagentDef → cli-agents/<name>.json = { name, description,\r\n // prompt } (+ model when non-\"inherit\"; + tools/allowedTools when the\r\n // SubagentDef carries a tool policy — see renderSubagent). Both scopes:\r\n // user → ~/.aws/amazonq/cli-agents/<name>.json\r\n // project → <projectDir>/.amazonq/cli-agents/<name>.json\r\n // A subagent named `q_cli_default` would resolve to the hooks/default-agent\r\n // file — the SDK already rejects it (non-kebab name), and installSubagents\r\n // refuses it as defense-in-depth so a subagent write can never clobber it.\r\n supportsSubagents: true,\r\n // commands (prompt library): DEFERRED — format unverified. The only primary\r\n // doc for the ~/.aws/amazonq/prompts/*.md prompt library is the IDE prompt-\r\n // library page (q-in-IDE-chat → ide-chat-context: prompts saved in\r\n // ~/.aws/amazonq/prompts, invoked via @<name> inside the IDE chat). The Q\r\n // CLI repo (aws/amazon-q-developer-cli/docs) ships NO prompts/saved-prompts\r\n // doc, so whether the `q`/`qchat` CLI reads that folder — and whether a\r\n // project-scoped prompts dir exists — is NOT primary-verified for the CLI\r\n // host this adapter targets. supportsCommands stays UNSET (base skip-warns)\r\n // rather than render an unverified surface (the continue per-server-YAML /\r\n // other deferred-unverified precedent).\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".aws\", \"amazonq\");\r\n const userMcp = join(userDir, \"mcp.json\");\r\n const projDir = join(projectDir, \".amazonq\");\r\n const projMcp = join(projDir, \"mcp.json\");\r\n\r\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\r\n const projInstalled = existsSync(projDir) || existsSync(projMcp);\r\n const installed = userInstalled || projInstalled;\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projMcp : userMcp;\r\n\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? `found Amazon Q config (${scope}) at ${configPath}`\r\n : `no Amazon Q mcp.json at ${userDir} or ${projDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n /**\r\n * Config directory per scope. Amazon Q uses DIFFERENT basenames:\r\n * user: ~/.aws/amazonq (two segments — NOT a single dotDir)\r\n * project: <projectDir>/.amazonq\r\n * This is the ONE deviation from droid/cursor's single-basename getConfigDir.\r\n */\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".amazonq\")\r\n : join(homedir(), \".aws\", \"amazonq\");\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"mcp.json\");\r\n }\r\n\r\n /**\r\n * Hooks live in a per-agent file, NOT the mcp.json. Amazon Q hooks have no\r\n * global file, so AC targets the built-in `q_cli_default` agent file at the\r\n * install scope (mirroring kiro's default-agent selection):\r\n * user → ~/.aws/amazonq/cli-agents/q_cli_default.json\r\n * project → <projectDir>/.amazonq/cli-agents/q_cli_default.json\r\n * A project install writes a project-scoped `q_cli_default` that SHADOWS the\r\n * user-global one (a local `q_cli_default` takes precedence and auto-loads).\r\n */\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"cli-agents\", DEFAULT_AGENT_FILE);\r\n }\r\n\r\n // ── Memory surface: the `.amazonq/rules` content tree ─────────────────────\r\n // Amazon Q uses `.amazonq/rules` (NOT AGENTS.md) for its OWN project rules, so\r\n // this override replaces the AGENTS.md base default entirely:\r\n // project → <projectDir>/.amazonq/rules/agent-connector.md (DEDICATED file\r\n // AC owns; plain Markdown, auto-applied — no frontmatter needed)\r\n // user → [] (no verified user/global rules dir → base installMemory\r\n // skip-warns rather than guessing a path the CLI may not read)\r\n // When `.amazonq/rules` exists as a single FILE (not a directory) we must NOT\r\n // create `.amazonq/rules/agent-connector.md` underneath it (that would throw\r\n // ENOTDIR), so memoryTargets() returns [] and installMemory() emits a precise\r\n // skip-warn rather than crashing (the cline `.clinerules`-is-a-file precedent).\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n // An explicit platforms[amazon-q].memory.path override wins (escape hatch).\r\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\r\n if (ctx.scope === \"project\") {\r\n if (this.rulesDirIsFile(ctx.projectDir)) return [];\r\n return [\r\n {\r\n path: join(ctx.projectDir, \".amazonq\", \"rules\", \"agent-connector.md\"),\r\n reason: \"amazon-q project rules dir (.amazonq/rules; agent-connector-owned file)\",\r\n },\r\n ];\r\n }\r\n // user scope: no primary-verified user/global rules dir → [] → skip-warn.\r\n return [];\r\n }\r\n\r\n /**\r\n * Override installMemory ONLY to surface a precise warn when `.amazonq/rules`\r\n * exists as a single FILE at project scope (so memoryTargets() returned []):\r\n * we never write under it. All other behavior delegates to the base\r\n * implementation (the cline `.clinerules`-is-a-file precedent).\r\n */\r\n override installMemory(ctx: InstallContext): ChangeRecord[] {\r\n if (\r\n ctx.scope === \"project\" &&\r\n !this.memoryOverride(ctx)?.path &&\r\n (ctx.connector.memory ?? []).length > 0 &&\r\n ctx.connector.platforms[this.id]?.memory !== false &&\r\n this.rulesDirIsFile(ctx.projectDir)\r\n ) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n path: join(ctx.projectDir, \".amazonq\", \"rules\"),\r\n detail:\r\n \"existing .amazonq/rules is a file, not a directory; left untouched — \" +\r\n \"convert it to a .amazonq/rules/ directory to receive agent-connector memory\",\r\n },\r\n ];\r\n }\r\n return super.installMemory(ctx);\r\n }\r\n\r\n /** True when `<dir>/.amazonq/rules` exists and is a regular FILE (not a dir). */\r\n private rulesDirIsFile(dir: string): boolean {\r\n const p = join(dir, \".amazonq\", \"rules\");\r\n if (!existsSync(p)) return false;\r\n try {\r\n return statSync(p).isFile();\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for amazon-q\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n // Shallow-merge any per-platform server override into the base ServerDef.\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /** Render a normalized ServerDef into Amazon Q's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): AmazonQStdioServer | AmazonQHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n // Amazon Q has no documented native interpolation token — resolve every\r\n // ${env:VAR} to a literal at install time (safe path, matches droid/crush).\r\n const entry: AmazonQStdioServer = {\r\n command: resolveEnvRefsDeep(command),\r\n };\r\n if (args.length > 0) entry.args = resolveEnvRefsDeep(args);\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n // timeout: Amazon Q uses MILLISECONDS — pass timeoutMs through unchanged.\r\n // Only emit when the connector explicitly sets one (do NOT invent a default).\r\n if (server.timeoutMs !== undefined) entry.timeout = server.timeoutMs;\r\n return entry;\r\n }\r\n\r\n // http (and any other remote transport) — Amazon Q registers a remote URL.\r\n // REMOTE shape: { type: \"http\", url } — explicit `type` discriminator, NO\r\n // `headers` (OAuth auth, not static headers), NO `disabled`.\r\n return {\r\n type: \"http\",\r\n url: resolveEnvRefsDeep(server.url ?? \"\"),\r\n };\r\n }\r\n\r\n /**\r\n * Render stdio env values. Amazon Q has no documented native interpolation\r\n * token, so resolve `${env:VAR}` references to literals at install time.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n return resolveEnvRefsDeep({ ...env });\r\n }\r\n\r\n // ── Hook install / uninstall (merge into the default agent file) ──────────\r\n\r\n installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.hooks === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"hooks disabled for amazon-q\" }];\r\n }\r\n if (connector.hookEvents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no hooks\" }];\r\n }\r\n\r\n const pending = connector.hookEvents.map((event) => ({\r\n event,\r\n matcher: connector.hooks[event]?.matcher ?? \"\",\r\n }));\r\n return this.upsertHookEntries(\r\n ctx,\r\n this.getHookConfigPath(ctx),\r\n pending,\r\n this.hookDescriptor(),\r\n );\r\n }\r\n\r\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor());\r\n }\r\n\r\n /**\r\n * Amazon Q's hook-merge descriptor (FLAT object-of-arrays shape — each entry is\r\n * `{ command, matcher? }`, NO `type` field, unlike kiro's nested\r\n * `{ matcher, hooks:[...] }`).\r\n * - mapEvent = EVENT_MAP (canonical → Amazon Q trigger); unmapped events\r\n * (PreCompact / SessionEnd / Notification + the E1 set) warn-skip.\r\n * - renderEntry emits `{ command }`, adding `matcher` ONLY for the\r\n * matcher-meaningful triggers (preToolUse/postToolUse) when one is declared;\r\n * an empty matcher = all tools, so it is OMITTED (no `matcher: \"\"` noise).\r\n * - entryOwnsCommand / ownsEntryForRemove match the home-bin command string\r\n * (idempotency on re-install; whole-entry removal on uninstall). FLAT host →\r\n * no stripInner; an emptied trigger key is dropped by the engine.\r\n */\r\n private hookDescriptor(): HookMergeDescriptor<AmazonQHookEntry> {\r\n return {\r\n mapEvent: (e) => EVENT_MAP[e as HookEventName],\r\n unmappedWarnDetail: (e) => `${e} has no Amazon Q hook equivalent — skipped`,\r\n renderEntry: (trigger, matcher, command) => {\r\n const entry: AmazonQHookEntry = { command };\r\n if (matcher && MATCHER_TRIGGERS.has(trigger)) entry.matcher = matcher;\r\n return entry;\r\n },\r\n entryOwnsCommand: (entry, command) => entry.command === command,\r\n ownsEntryForRemove: (c) => (entry) => this.isOurCommand(entry.command, c),\r\n skipDetail: (trigger) => `hooks.${trigger} already registered`,\r\n removeDetail: (trigger, removed) => `hooks.${trigger} (${removed})`,\r\n absentDetail: \"no hooks section present\",\r\n noMatchDetail: \"no matching hook entries\",\r\n };\r\n }\r\n\r\n /** True when a hook command references our home binary AND this connector id\r\n * (anchored so a shared-prefix id can't collide — see isHomeBinHookCommand). */\r\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\r\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\r\n }\r\n\r\n // ── Content surface: subagents → cli-agents/<name>.json ───────────────────\r\n // CONTENT-ONLY: a pure native-file writer — no runtime dispatch, no home-bin\r\n // pointer, no telemetry wrap. Amazon Q \"agents\" are per-agent JSON files where\r\n // the FILENAME (minus .json) IS the agent name (agent-file-locations.md). Each\r\n // file is a STANDALONE agent definition: we write only { name, description,\r\n // prompt } (+ model / tools / allowedTools when the SubagentDef carries them)\r\n // and NEVER inject hooks (those live in q_cli_default.json) or mcpServers (those\r\n // live in mcp.json). The whole file is AC-owned, so idempotency + reversibility\r\n // come from writeContentFile/removeContentFile (byte-identical → skip; uninstall\r\n // removes the file → NO_RESIDUE).\r\n // user → ~/.aws/amazonq/cli-agents/<name>.json\r\n // project → <projectDir>/.amazonq/cli-agents/<name>.json\r\n\r\n /** Native subagent file path: <configDir>/cli-agents/<name>.json. */\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.getConfigDir(ctx), \"cli-agents\", `${name}.json`);\r\n }\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for amazon-q\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) => {\r\n // COLLISION GUARD: a subagent named `q_cli_default` resolves to the SAME\r\n // file as the hooks/built-in default agent — refuse it so a subagent write\r\n // can never clobber the hooks agent.\r\n if (agent.name === RESERVED_AGENT_NAME) {\r\n return {\r\n platform: this.id,\r\n action: \"warn\",\r\n detail:\r\n `subagent \"${agent.name}\" collides with the built-in default agent file ` +\r\n `(cli-agents/${DEFAULT_AGENT_FILE}); skipped — rename the subagent`,\r\n };\r\n }\r\n return this.writeContentFile(\r\n this.subagentPath(ctx, agent.name),\r\n this.renderSubagent(agent),\r\n ctx.dryRun,\r\n );\r\n });\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) => {\r\n // Never remove the hooks/default-agent file under the collision name.\r\n if (agent.name === RESERVED_AGENT_NAME) {\r\n return {\r\n platform: this.id,\r\n action: \"warn\",\r\n detail:\r\n `subagent \"${agent.name}\" was never installed (collides with ` +\r\n `cli-agents/${DEFAULT_AGENT_FILE}); left untouched`,\r\n };\r\n }\r\n return this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun);\r\n });\r\n }\r\n\r\n /**\r\n * Render a connector subagent into an Amazon Q agent JSON file\r\n * (agent-format.md):\r\n * { name, description, prompt } — prompt is the INLINE system-prompt string\r\n * (Amazon Q's `prompt` field is \"high-level context … similar to a system\r\n * prompt\"; we use the inline-text form, NOT a file:// ref).\r\n * Plus, when the SubagentDef carries them:\r\n * - model: only when set and not the platform-agnostic \"inherit\"\r\n * sentinel (Amazon Q has no \"inherit\" — omitting it applies the default).\r\n * - tools: SurfaceToolPolicy.allow → the `tools` array (the tools the\r\n * agent can use). Amazon Q's `tools` accepts plain tool-name strings and\r\n * `*`, the same vocabulary the portable allow-list carries.\r\n * - allowedTools: SurfaceToolPolicy.allow → the `allowedTools` array (tools\r\n * usable WITHOUT a permission prompt) — BUT only when the allow-list holds\r\n * no `*` (Amazon Q's allowedTools does NOT accept the `\"*\"` wildcard;\r\n * agent-format.md \"AllowedTools Field\"). When allow is exactly [\"*\"] we set\r\n * `tools` but omit `allowedTools` (every tool available, none auto-allowed).\r\n * `deny` has no clean Amazon Q analog (there is no disallowedTools field —\r\n * access is an allow-list), so a deny-only policy maps to no tool keys.\r\n * `readonly` is likewise dropped — Amazon Q has no read-only-agent field; the\r\n * permission model IS the allowedTools allow-list (no separate analog).\r\n * `extra` is shallow-merged last (per-platform escape hatch).\r\n */\r\n private renderSubagent(agent: SubagentDef): string {\r\n const obj: Record<string, unknown> = {\r\n name: agent.name,\r\n description: agent.description,\r\n prompt: agent.prompt,\r\n };\r\n if (agent.model !== undefined && agent.model !== \"inherit\") obj.model = agent.model;\r\n\r\n const allow = agent.tools?.allow;\r\n if (allow && allow.length > 0) {\r\n obj.tools = [...allow];\r\n // allowedTools rejects the \"*\" wildcard — only emit it for concrete patterns.\r\n const allowed = allow.filter((t) => t !== \"*\");\r\n if (allowed.length > 0) obj.allowedTools = allowed;\r\n }\r\n if (agent.extra) Object.assign(obj, agent.extra);\r\n\r\n // Match writeJson's serialization (2-space indent + trailing newline) so the\r\n // bytes are stable for writeContentFile's idempotent skip.\r\n return `${JSON.stringify(obj, null, 2)}\\n`;\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const mcpPath = this.getServerConfigPath(ctx);\r\n const agentPath = this.getHookConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const homeBin = ctx.homeBinPath;\r\n const hookEvents = ctx.connector.hookEvents;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: mcp.json present`,\r\n check: () =>\r\n existsSync(mcpPath)\r\n ? { status: \"OK\", detail: mcpPath }\r\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\r\n },\r\n {\r\n name: `${this.name}: server entry registered`,\r\n check: () => {\r\n if (!ctx.connector.server) {\r\n return { status: \"OK\", detail: \"no MCP server declared\" };\r\n }\r\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\r\n const bucket = cfg?.[MCP_ROOT_KEY];\r\n if (!cfg || !bucket) {\r\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\r\n }\r\n return connectorId in bucket\r\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\r\n : {\r\n status: \"FAIL\",\r\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\r\n };\r\n },\r\n },\r\n {\r\n name: `${this.name}: hook command registered`,\r\n check: () => {\r\n if (hookEvents.length === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n const agent = this.readJson<AmazonQAgentFile>(agentPath);\r\n if (!agent) return { status: \"FAIL\", detail: `cannot read ${agentPath}` };\r\n const hooks = agent.hooks ?? {};\r\n const registered = Object.values(hooks).some((entries) =>\r\n (entries ?? []).some((e) => isHomeBinHookCommand(e.command, homeBin, connectorId)),\r\n );\r\n return registered\r\n ? { status: \"OK\", detail: \"hook command present\" }\r\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${agentPath}` };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: assert each declared subagent's JSON file exists.\r\n // Skip the reserved collision name (never written by installSubagents).\r\n for (const agent of ctx.connector.subagents) {\r\n if (agent.name === RESERVED_AGENT_NAME) continue;\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse Amazon Q stdin JSON → normalized event ─────────────────\r\n // Amazon Q's stdin payload shape and exit-code contract are IDENTICAL to kiro's\r\n // (both AWS hosts in the same hook family); this parse + the formatReply context\r\n // channel below follow Amazon Q's own primary-verified schema (docs/hooks.md):\r\n // exit-code reply + PLAIN STDOUT context, gated to agentSpawn / userPromptSubmit.\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as AmazonQWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n // Host gap: Amazon Q never serializes a session id onto hook stdin — the only\r\n // always-present fields are hook_event_name + cwd (hooks.rs:300-304). sessionId\r\n // stays \"\" rather than reading a non-existent input.session_id.\r\n // Ref: aws/amazon-q-developer-cli crates/chat-cli/src/cli/chat/cli/hooks.rs:300-321\r\n const sessionId = \"\";\r\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\r\n\r\n const base = {\r\n hostPlatform: HOST,\r\n connectorId,\r\n sessionId,\r\n raw,\r\n ...(projectDir !== undefined ? { projectDir } : {}),\r\n } as const;\r\n\r\n switch (event) {\r\n case \"PreToolUse\": {\r\n const ev: PreToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUse\": {\r\n const ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolResponseToString(input.tool_response) !== undefined\r\n ? { toolOutput: toolResponseToString(input.tool_response) }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n // Host gap: agentSpawn stdin is exactly {hook_event_name, cwd} — Amazon Q\r\n // serializes no start-reason discriminator (the Rust hook::Source enum is\r\n // config-grouping, never written to the payload), so resume/compact/clear\r\n // are indistinguishable. Default to \"startup\" rather than reading a\r\n // non-existent input.source.\r\n // Ref: aws/amazon-q-developer-cli crates/chat-cli/src/cli/chat/cli/hooks.rs:300-304\r\n // + docs/hooks.md:14-17 (agentSpawn input example)\r\n const ev: SessionStartEvent = {\r\n ...base,\r\n source: \"startup\",\r\n };\r\n return ev;\r\n }\r\n case \"UserPromptSubmit\": {\r\n const ev: UserPromptSubmitEvent = {\r\n ...base,\r\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"Stop\": {\r\n // Host gap: stop stdin is exactly {hook_event_name, cwd} — Amazon Q never\r\n // serializes a stop_hook_active boolean, so the field is omitted (never set\r\n // from a non-existent input.stop_hook_active).\r\n // Ref: aws/amazon-q-developer-cli crates/chat-cli/src/cli/chat/cli/hooks.rs:300-321\r\n // + docs/hooks.md:106-107 (stop input example)\r\n const ev: StopEvent = {\r\n ...base,\r\n };\r\n return ev;\r\n }\r\n default: {\r\n // Amazon Q never delivers PreCompact / SessionEnd / Notification nor the\r\n // E1 extension events (no native triggers). If the runtime dispatches one\r\n // anyway, surface it loudly rather than silently mis-parse.\r\n throw new Error(`unsupported amazon-q hook event: ${String(event)}`);\r\n }\r\n }\r\n }\r\n\r\n // ── Runtime: normalized response → Amazon Q native (exit-code) hook reply ──\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const decision = response.decision ?? \"allow\";\r\n\r\n // deny → block the action: exit 2 with the reason on stderr.\r\n if (decision === \"deny\") {\r\n return { exitCode: 2, stderr: response.reason ?? \"Blocked by hook\" };\r\n }\r\n\r\n // ask → Amazon Q has no native \"ask\"; degrade to deny (exit 2) to stay fail-safe.\r\n if (decision === \"ask\") {\r\n return {\r\n exitCode: 2,\r\n stderr: response.reason ?? \"Action requires user confirmation (security policy)\",\r\n };\r\n }\r\n\r\n // Stop → exit-code only (deny already handled above). No context channel on a\r\n // Stop hook, so anything non-deny passes through with exit 0.\r\n if (event === \"Stop\") {\r\n return { exitCode: 0 };\r\n }\r\n\r\n // context → inject soft guidance. Amazon Q adds a hook's PLAIN STDOUT to the\r\n // agent's context (NO JSON envelope), but ONLY for agentSpawn and\r\n // userPromptSubmit; preToolUse / postToolUse / stop have no context channel\r\n // (their STDOUT is \"captured but not shown\"). So emit the raw text on stdout\r\n // only when the FIRING event maps to a context-supporting Amazon Q trigger;\r\n // otherwise the context decision degrades to a plain exit-0 pass-through rather\r\n // than a mislabeled/ineffective payload. exit 0 = allow.\r\n // Ref: aws/amazon-q-developer-cli docs/hooks.md\r\n const trigger = EVENT_MAP[event as HookEventName];\r\n if (\r\n decision === \"context\" &&\r\n response.additionalContext &&\r\n trigger !== undefined &&\r\n CONTEXT_TRIGGERS.has(trigger)\r\n ) {\r\n return { exitCode: 0, stdout: response.additionalContext };\r\n }\r\n\r\n // modify is unsupported (exit-code protocol — cannot rewrite args/output);\r\n // allow / void → pass through with exit 0.\r\n return { exitCode: 0 };\r\n }\r\n}\r\n\r\n/** Coerce an Amazon Q PostToolUse `tool_response` into a string for the normalized event. */\r\nfunction toolResponseToString(value: unknown): string | undefined {\r\n if (value == null) return undefined;\r\n if (typeof value === \"string\") return value;\r\n try {\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n\r\nexport const adapter = new AmazonQAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/usage/readers/amp.ts"],"sourcesContent":["/**\r\n * usage/readers/amp — Amp (Sourcegraph) native session-log reader.\r\n *\r\n * Faithful port of tokscale sessions/amp.rs. Reads one JSON file per thread from\r\n * ~/.local/share/amp/threads/*.json. Each thread carries token usage in TWO\r\n * overlapping places that describe the SAME calls and must be MERGED, not summed:\r\n *\r\n * 1. `usageLedger.events[]` — billing ledger rows:\r\n * tokens.input → input\r\n * tokens.output → output\r\n * tokens.cacheReadInputTokens → cacheRead\r\n * tokens.cacheCreationInputTokens → cacheWrite\r\n * model, credits (cost), timestamp (RFC3339), toMessageId.\r\n * 2. `messages[].usage` (assistant role only) — per-message usage:\r\n * inputTokens / outputTokens / cacheReadInputTokens /\r\n * cacheCreationInputTokens, model, credits.\r\n *\r\n * Reconciliation (port of parse_amp_file + merge_amp_records): when a ledger\r\n * exists, each assistant message-record is matched to at most one ledger record —\r\n * first by `toMessageId == messageId`, else by an exact (model, tokens) heuristic\r\n * — using a rotating search cursor so earlier matches are not re-consumed. A match\r\n * MERGES into the ledger record (the ledger keeps its explicit timestamp/cost,\r\n * but borrows the message timestamp/cost where it lacks them); an unmatched\r\n * message-record is appended as its own row. Ledger rows that match nothing stay.\r\n * When there is NO ledger, message-records pass through directly. This in-file\r\n * merge is the dedup: a call logged in both places yields ONE row, never two.\r\n *\r\n * Timestamps (port of parse_amp_timestamp / fallback_amp_timestamp): a ledger\r\n * event prefers its RFC3339 string, else thread.created, else file mtime. A\r\n * message-record derives `thread.created (or mtime) + messageId*1000` so messages\r\n * order by id. reasoning is always 0 (Amp does not report it).\r\n *\r\n * Attribution: session = thread.id (or the filename stem). Project is not captured\r\n * by Amp, so projectKey/projectLabel are omitted. model/provider come from the\r\n * row's model (provider inferred, default \"anthropic\"). Confidence is\r\n * \"host-reported\" (real host token counts). A stable cross-source `dedupKey`\r\n * (`amp:<thread>:<ts>:<model>:<tokens>`) guards against the same file being read\r\n * twice; the in-file merge already prevents ledger/message double counting.\r\n *\r\n * Fail-open: no root → []; unreadable/malformed file → skipped (no throw).\r\n * Read-only.\r\n */\r\n\r\nimport { basename } from \"node:path\";\r\n\r\nimport type { UsageReader, UsageRecord, TokenBreakdown } from \"../types.js\";\r\nimport { emptyTokens } from \"../aggregate.js\";\r\nimport { fileMtimeMs, readJsonFile } from \"../jsonl.js\";\r\nimport { inferProvider } from \"../normalize.js\";\r\nimport { firstExistingRoot, walkFiles } from \"../paths.js\";\r\n\r\nconst PLATFORM_ID = \"amp\" as const;\r\nconst DEFAULT_PROVIDER = \"anthropic\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Raw shapes (everything optional / unknown — narrowed at read time)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface AmpTokensRaw {\r\n input?: unknown;\r\n output?: unknown;\r\n cacheReadInputTokens?: unknown;\r\n cacheCreationInputTokens?: unknown;\r\n}\r\n\r\ninterface AmpUsageEventRaw {\r\n timestamp?: unknown;\r\n model?: unknown;\r\n credits?: unknown;\r\n tokens?: AmpTokensRaw;\r\n toMessageId?: unknown;\r\n}\r\n\r\ninterface AmpMessageUsageRaw {\r\n model?: unknown;\r\n inputTokens?: unknown;\r\n outputTokens?: unknown;\r\n cacheReadInputTokens?: unknown;\r\n cacheCreationInputTokens?: unknown;\r\n credits?: unknown;\r\n}\r\n\r\ninterface AmpMessageRaw {\r\n role?: unknown;\r\n messageId?: unknown;\r\n usage?: AmpMessageUsageRaw;\r\n}\r\n\r\ninterface AmpThreadRaw {\r\n id?: unknown;\r\n created?: unknown;\r\n messages?: unknown;\r\n usageLedger?: { events?: unknown };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Coercion helpers\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Coerce an unknown to a non-negative integer (0 on absence/garbage). Mirrors `.unwrap_or(0).max(0)`. */\r\nfunction toNonNegInt(v: unknown): number {\r\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\r\n if (!Number.isFinite(n)) return 0;\r\n return Math.max(0, Math.trunc(n));\r\n}\r\n\r\n/** Coerce an unknown to a non-negative float (0 on absence/garbage). Mirrors credits `.unwrap_or(0.0).max(0.0)`. */\r\nfunction toNonNegFloat(v: unknown): number {\r\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\r\n if (!Number.isFinite(n)) return 0;\r\n return Math.max(0, n);\r\n}\r\n\r\n/** Coerce an unknown to an integer, or null when absent/garbage (for ids). */\r\nfunction toIntOrNull(v: unknown): number | null {\r\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\r\n if (!Number.isFinite(n)) return null;\r\n return Math.trunc(n);\r\n}\r\n\r\n/**\r\n * Parse an RFC3339 timestamp string to epoch ms, filtering 0 out. Port of\r\n * parse_amp_timestamp: returns null when absent, unparseable, or exactly 0.\r\n */\r\nfunction parseAmpTimestamp(v: unknown): number | null {\r\n if (typeof v !== \"string\" || v === \"\") return null;\r\n const ms = Date.parse(v);\r\n if (Number.isNaN(ms) || ms === 0) return null;\r\n return ms;\r\n}\r\n\r\n/**\r\n * Pick a ledger timestamp with fallback (port of fallback_amp_timestamp):\r\n * explicit (when non-zero) → thread.created (when non-zero) → file mtime.\r\n */\r\nfunction fallbackAmpTimestamp(\r\n explicit: number | null,\r\n threadCreatedMs: number,\r\n fileMtime: number,\r\n): number {\r\n if (explicit !== null && explicit !== 0) return explicit;\r\n if (threadCreatedMs !== 0) return threadCreatedMs;\r\n return fileMtime;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Intermediate record (port of AmpUsageRecord)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface AmpUsageRecord {\r\n model: string;\r\n timestamp: number;\r\n hasExplicitTimestamp: boolean;\r\n /** assistant messageId (>0) when this row came from / merged a message. */\r\n messageId: number | null;\r\n /** ledger event's toMessageId (>0) used for id-based matching. */\r\n ledgerToMessageId: number | null;\r\n tokens: TokenBreakdown;\r\n cost: number;\r\n}\r\n\r\n/** Element-wise token equality (port of `self.tokens == other.tokens`). */\r\nfunction tokensEqual(a: TokenBreakdown, b: TokenBreakdown): boolean {\r\n return (\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/** Heuristic match: same model AND identical tokens (port of matches_message_usage). */\r\nfunction matchesMessageUsage(a: AmpUsageRecord, b: AmpUsageRecord): boolean {\r\n return a.model === b.model && tokensEqual(a.tokens, b.tokens);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Ledger / message parsing\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Port of parse_amp_ledger_records. */\r\nfunction parseLedgerRecords(\r\n eventsRaw: unknown,\r\n threadCreatedMs: number,\r\n fileMtime: number,\r\n): AmpUsageRecord[] {\r\n if (!Array.isArray(eventsRaw)) return [];\r\n\r\n const out: AmpUsageRecord[] = [];\r\n for (const raw of eventsRaw) {\r\n if (typeof raw !== \"object\" || raw === null) continue;\r\n const event = raw as AmpUsageEventRaw;\r\n\r\n if (typeof event.model !== \"string\" || event.model === \"\") continue; // model? early-return\r\n const model = event.model;\r\n\r\n const explicit = parseAmpTimestamp(event.timestamp);\r\n const timestamp = fallbackAmpTimestamp(explicit, threadCreatedMs, fileMtime);\r\n\r\n const tokensRaw = event.tokens ?? {};\r\n const tokens = emptyTokens();\r\n tokens.input = toNonNegInt(tokensRaw.input);\r\n tokens.output = toNonNegInt(tokensRaw.output);\r\n tokens.cacheRead = toNonNegInt(tokensRaw.cacheReadInputTokens);\r\n tokens.cacheWrite = toNonNegInt(tokensRaw.cacheCreationInputTokens);\r\n // reasoning stays 0.\r\n\r\n const toMsgId = toIntOrNull(event.toMessageId);\r\n\r\n out.push({\r\n model,\r\n timestamp,\r\n hasExplicitTimestamp: explicit !== null,\r\n messageId: null,\r\n ledgerToMessageId: toMsgId !== null && toMsgId > 0 ? toMsgId : null,\r\n tokens,\r\n cost: toNonNegFloat(event.credits),\r\n });\r\n }\r\n return out;\r\n}\r\n\r\n/** Port of parse_amp_message_records (assistant rows only). */\r\nfunction parseMessageRecords(\r\n messagesRaw: unknown,\r\n threadCreatedMs: number,\r\n fileMtime: number,\r\n): AmpUsageRecord[] {\r\n if (!Array.isArray(messagesRaw)) return [];\r\n\r\n const baseTimestamp = threadCreatedMs !== 0 ? threadCreatedMs : fileMtime;\r\n\r\n const out: AmpUsageRecord[] = [];\r\n for (const raw of messagesRaw) {\r\n if (typeof raw !== \"object\" || raw === null) continue;\r\n const msg = raw as AmpMessageRaw;\r\n\r\n if (msg.role !== \"assistant\") continue;\r\n const usage = msg.usage;\r\n if (usage === undefined || usage === null) continue; // usage? early-return\r\n if (typeof usage.model !== \"string\" || usage.model === \"\") continue; // model? early-return\r\n const model = usage.model;\r\n\r\n const messageId = Math.max(0, toIntOrNull(msg.messageId) ?? 0);\r\n // base + messageId*1000 (saturating in Rust; JS numbers don't overflow here).\r\n const timestamp = baseTimestamp + messageId * 1000;\r\n\r\n const tokens = emptyTokens();\r\n tokens.input = toNonNegInt(usage.inputTokens);\r\n tokens.output = toNonNegInt(usage.outputTokens);\r\n tokens.cacheRead = toNonNegInt(usage.cacheReadInputTokens);\r\n tokens.cacheWrite = toNonNegInt(usage.cacheCreationInputTokens);\r\n // reasoning stays 0.\r\n\r\n out.push({\r\n model,\r\n timestamp,\r\n hasExplicitTimestamp: false,\r\n messageId: messageId > 0 ? messageId : null,\r\n ledgerToMessageId: null,\r\n tokens,\r\n cost: toNonNegFloat(usage.credits),\r\n });\r\n }\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Reconciliation (port of find_matching_ledger_record + merge_amp_records)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Find an unconsumed ledger record matching `messageRecord`, scanning from\r\n * `searchStart` forward then wrapping to the front (port of the rotating\r\n * find_match). Prefers a `toMessageId == messageId` match, then the\r\n * (model, tokens) heuristic. Returns the index, or null when none matches.\r\n */\r\nfunction findMatchingLedgerRecord(\r\n ledger: AmpUsageRecord[],\r\n consumed: boolean[],\r\n searchStart: number,\r\n messageRecord: AmpUsageRecord,\r\n): number | null {\r\n const findMatch = (predicate: (i: number) => boolean): number | null => {\r\n for (let i = searchStart; i < ledger.length; i++) {\r\n if (predicate(i)) return i;\r\n }\r\n for (let i = 0; i < searchStart; i++) {\r\n if (predicate(i)) return i;\r\n }\r\n return null;\r\n };\r\n\r\n if (messageRecord.messageId !== null) {\r\n const byId = findMatch(\r\n (i) => !consumed[i] && ledger[i]!.ledgerToMessageId === messageRecord.messageId,\r\n );\r\n if (byId !== null) return byId;\r\n }\r\n\r\n return findMatch((i) => !consumed[i] && matchesMessageUsage(ledger[i]!, messageRecord));\r\n}\r\n\r\n/**\r\n * Merge a matched message-record into its ledger record (port of merge_amp_records).\r\n * If the ledger row has an explicit timestamp, it wins (only borrowing the\r\n * message cost/messageId when the ledger had no cost); otherwise the merged row\r\n * adopts the message timestamp, keeping ledger tokens and the better cost.\r\n */\r\nfunction mergeAmpRecords(ledger: AmpUsageRecord, message: AmpUsageRecord): AmpUsageRecord {\r\n if (ledger.hasExplicitTimestamp) {\r\n if (ledger.cost > 0 || message.cost <= 0) {\r\n return ledger;\r\n }\r\n return { ...ledger, cost: message.cost, messageId: message.messageId };\r\n }\r\n return {\r\n model: ledger.model,\r\n timestamp: message.timestamp,\r\n hasExplicitTimestamp: false,\r\n messageId: message.messageId,\r\n ledgerToMessageId: ledger.ledgerToMessageId,\r\n tokens: ledger.tokens,\r\n cost: ledger.cost > 0 ? ledger.cost : message.cost,\r\n };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// File parse (port of parse_amp_file)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nfunction stripExt(name: string): string {\r\n const dot = name.lastIndexOf(\".\");\r\n return dot > 0 ? name.slice(0, dot) : name;\r\n}\r\n\r\n/** Stable cross-source dedup key for one reconciled row. */\r\nfunction dedupKey(threadId: string, rec: AmpUsageRecord): string {\r\n const t = rec.tokens;\r\n return `amp:${threadId}:${rec.timestamp}:${rec.model}:${t.input}-${t.output}-${t.cacheRead}-${t.cacheWrite}-${t.reasoning}`;\r\n}\r\n\r\nfunction parseAmpFile(path: string): UsageRecord[] {\r\n const parsed = readJsonFile(path);\r\n if (typeof parsed !== \"object\" || parsed === null) return []; // missing/malformed → []\r\n const thread = parsed as AmpThreadRaw;\r\n\r\n const fileMtime = fileMtimeMs(path);\r\n\r\n const threadId =\r\n typeof thread.id === \"string\" && thread.id !== \"\"\r\n ? thread.id\r\n : stripExt(basename(path)) || \"unknown\";\r\n\r\n const threadCreatedMs = toIntOrNull(thread.created) ?? 0;\r\n\r\n const ledgerRecords = parseLedgerRecords(\r\n thread.usageLedger?.events,\r\n threadCreatedMs,\r\n fileMtime,\r\n );\r\n const messageRecords = parseMessageRecords(thread.messages, threadCreatedMs, fileMtime);\r\n\r\n let reconciled: AmpUsageRecord[];\r\n\r\n if (ledgerRecords.length === 0) {\r\n // No ledger → message-records pass through, sorted by timestamp.\r\n reconciled = messageRecords.slice().sort((a, b) => a.timestamp - b.timestamp);\r\n } else {\r\n const consumed = new Array<boolean>(ledgerRecords.length).fill(false);\r\n let searchStart = 0;\r\n const unmatched: AmpUsageRecord[] = [];\r\n\r\n for (const messageRecord of messageRecords) {\r\n const index = findMatchingLedgerRecord(\r\n ledgerRecords,\r\n consumed,\r\n searchStart,\r\n messageRecord,\r\n );\r\n if (index !== null) {\r\n consumed[index] = true;\r\n searchStart = index + 1;\r\n ledgerRecords[index] = mergeAmpRecords(ledgerRecords[index]!, messageRecord);\r\n } else {\r\n unmatched.push(messageRecord);\r\n }\r\n }\r\n\r\n reconciled = ledgerRecords.concat(unmatched).sort((a, b) => a.timestamp - b.timestamp);\r\n }\r\n\r\n return reconciled.map((rec) => {\r\n const modelId = rec.model;\r\n const providerId = inferProvider(modelId) ?? DEFAULT_PROVIDER;\r\n\r\n const tokens = emptyTokens();\r\n tokens.input = rec.tokens.input;\r\n tokens.output = rec.tokens.output;\r\n tokens.cacheRead = rec.tokens.cacheRead;\r\n tokens.cacheWrite = rec.tokens.cacheWrite;\r\n tokens.reasoning = rec.tokens.reasoning;\r\n\r\n const record: UsageRecord = {\r\n platformId: PLATFORM_ID,\r\n modelId,\r\n providerId,\r\n sessionId: threadId,\r\n tokens,\r\n ts: rec.timestamp,\r\n messageCount: 1,\r\n confidence: \"host-reported\",\r\n dedupKey: dedupKey(threadId, rec),\r\n };\r\n if (rec.cost > 0) record.cost = rec.cost;\r\n // Amp does not capture a project → projectKey/projectLabel omitted.\r\n return record;\r\n });\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Reader\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The Amp (Sourcegraph) usage reader singleton. */\r\nconst ampReader: UsageReader = {\r\n platformId: PLATFORM_ID,\r\n kind: \"local\",\r\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\r\n const root = firstExistingRoot(PLATFORM_ID);\r\n if (root === undefined) return []; // no ~/.local/share/amp/threads → fail-open\r\n\r\n // ~/.local/share/amp/threads/*.json\r\n const files = walkFiles(root, (name) => name.endsWith(\".json\"));\r\n\r\n const records: UsageRecord[] = [];\r\n for (const file of files) {\r\n const rows = parseAmpFile(file);\r\n for (const row of rows) {\r\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\r\n records.push(row);\r\n }\r\n }\r\n return records;\r\n },\r\n};\r\n\r\nexport default ampReader;\r\n"],"mappings":"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","names":[]}