@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.
- package/LICENSE +202 -202
- package/NOTICE +6 -6
- package/README.md +604 -596
- package/dist/{action-5JM23CFJ.js → action-5OEM3QC4.js} +17 -16
- package/dist/action-5OEM3QC4.js.map +1 -0
- package/dist/{amazon-q-LFZNGN27.js → amazon-q-7DPVJXJN.js} +6 -6
- package/dist/amazon-q-7DPVJXJN.js.map +1 -0
- package/dist/{amp-CEWOSWQO.js → amp-BQZOL5GR.js} +4 -4
- package/dist/amp-BQZOL5GR.js.map +1 -0
- package/dist/{amp-S22XTPEQ.js → amp-VYXZWHXW.js} +7 -7
- package/dist/amp-VYXZWHXW.js.map +1 -0
- package/dist/{antigravity-LHFEFNMC.js → antigravity-EA4L225L.js} +5 -5
- package/dist/antigravity-EA4L225L.js.map +1 -0
- package/dist/antigravity-VXHL6ZPM.js +18 -0
- package/dist/{antigravity-cli-MOKFSWOU.js → antigravity-cli-B2HXZFYQ.js} +5 -5
- package/dist/antigravity-cli-B2HXZFYQ.js.map +1 -0
- package/dist/{antigravity-cli-PN474FXM.js → antigravity-cli-JHQ7JGNX.js} +10 -9
- package/dist/antigravity-cli-JHQ7JGNX.js.map +1 -0
- package/dist/{audit-2H7E3Z4N.js → audit-BO7JQYIH.js} +8 -8
- package/dist/{chunk-7C2IPIIB.js → chunk-2Y2MZRLP.js} +3 -3
- package/dist/chunk-2Y2MZRLP.js.map +1 -0
- package/dist/{chunk-B6PKHS5I.js → chunk-4KIXXJ7B.js} +2 -2
- package/dist/chunk-4KIXXJ7B.js.map +1 -0
- package/dist/chunk-4NFDNY3C.js +34 -0
- package/dist/chunk-4NFDNY3C.js.map +1 -0
- package/dist/{chunk-RPWD5H6Y.js → chunk-4QXCNZMD.js} +5 -5
- package/dist/chunk-4QXCNZMD.js.map +1 -0
- package/dist/{chunk-Q7PR2WGT.js → chunk-6TF7MHG5.js} +2 -2
- package/dist/chunk-6TF7MHG5.js.map +1 -0
- package/dist/{chunk-KWC5DQ5Z.js → chunk-6WN37NVN.js} +113 -10
- package/dist/chunk-6WN37NVN.js.map +1 -0
- package/dist/{chunk-DWZ5IWF4.js → chunk-6XMV2OOA.js} +6 -6
- package/dist/chunk-6XMV2OOA.js.map +1 -0
- package/dist/{chunk-XXLCMSD3.js → chunk-BEFVJ2OE.js} +1 -1
- package/dist/chunk-BEFVJ2OE.js.map +1 -0
- package/dist/{chunk-HATCOSQT.js → chunk-BV5WK6VQ.js} +19 -19
- package/dist/chunk-BV5WK6VQ.js.map +1 -0
- package/dist/{chunk-KTBAB556.js → chunk-BXPSDNIB.js} +2 -2
- package/dist/chunk-BXPSDNIB.js.map +1 -0
- package/dist/{chunk-Q4ISQHUQ.js → chunk-FBJQGRET.js} +1 -1
- package/dist/chunk-FBJQGRET.js.map +1 -0
- package/dist/{chunk-THI4PI4H.js → chunk-FJCUKXGX.js} +2 -2
- package/dist/chunk-FJCUKXGX.js.map +1 -0
- package/dist/{chunk-6XWORQM6.js → chunk-FKW5A6HE.js} +23 -7
- package/dist/chunk-FKW5A6HE.js.map +1 -0
- package/dist/{chunk-TOSNS2BY.js → chunk-G5HAIYRM.js} +43 -43
- package/dist/chunk-G5HAIYRM.js.map +1 -0
- package/dist/{chunk-RNVIK5YJ.js → chunk-GDIAHWNY.js} +2 -2
- package/dist/chunk-GDIAHWNY.js.map +1 -0
- package/dist/{chunk-QYOUQCC6.js → chunk-GZGLCCEE.js} +1 -1
- package/dist/chunk-GZGLCCEE.js.map +1 -0
- package/dist/{chunk-PSGTHJQU.js → chunk-H53QZQJI.js} +1 -1
- package/dist/chunk-H53QZQJI.js.map +1 -0
- package/dist/{chunk-7HHW23AC.js → chunk-IRUYJD23.js} +29 -29
- package/dist/chunk-IRUYJD23.js.map +1 -0
- package/dist/{chunk-IOJDZJ72.js → chunk-IVAWP6HH.js} +2 -2
- package/dist/chunk-IVAWP6HH.js.map +1 -0
- package/dist/{chunk-UNU2KPYJ.js → chunk-JTN3AKZO.js} +23 -15
- package/dist/chunk-JTN3AKZO.js.map +1 -0
- package/dist/{chunk-4GH2KA7V.js → chunk-KHO5WNTP.js} +1 -1
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/{chunk-S25MVWBP.js → chunk-KLZBRNFP.js} +12 -12
- package/dist/chunk-KLZBRNFP.js.map +1 -0
- package/dist/{chunk-DOPFBUCX.js → chunk-M6OS4OLU.js} +3 -3
- package/dist/chunk-M6OS4OLU.js.map +1 -0
- package/dist/{chunk-UZZTWWGG.js → chunk-MQPNU2CY.js} +1 -1
- package/dist/chunk-MQPNU2CY.js.map +1 -0
- package/dist/{chunk-LZL2YITN.js → chunk-N4STCQGP.js} +7 -7
- package/dist/chunk-N4STCQGP.js.map +1 -0
- package/dist/{chunk-KFPSJRHR.js → chunk-NBYKLUF6.js} +2 -2
- package/dist/chunk-NBYKLUF6.js.map +1 -0
- package/dist/{chunk-KM2YXO6V.js → chunk-O7SDRBVB.js} +1 -1
- package/dist/chunk-O7SDRBVB.js.map +1 -0
- package/dist/{chunk-LFWYYWLV.js → chunk-OP4KBXUO.js} +1 -1
- package/dist/chunk-OP4KBXUO.js.map +1 -0
- package/dist/{chunk-XN7S44U4.js → chunk-OPXAP3AC.js} +1 -1
- package/dist/chunk-OPXAP3AC.js.map +1 -0
- package/dist/{chunk-LD5HAN6O.js → chunk-PWCBWAM4.js} +6 -4
- package/dist/chunk-PWCBWAM4.js.map +1 -0
- package/dist/{chunk-W7AGWAMH.js → chunk-QSY74NAP.js} +2 -2
- package/dist/chunk-QSY74NAP.js.map +1 -0
- package/dist/{chunk-ZSOS2KOR.js → chunk-RK6VBLXP.js} +1 -1
- package/dist/chunk-RK6VBLXP.js.map +1 -0
- package/dist/{chunk-7VSZXOXJ.js → chunk-SFY6YLVK.js} +19 -12
- package/dist/chunk-SFY6YLVK.js.map +1 -0
- package/dist/{chunk-C747DYNT.js → chunk-UM5S7DKK.js} +1 -1
- package/dist/chunk-UM5S7DKK.js.map +1 -0
- package/dist/{chunk-ILWHLGIC.js → chunk-UMQ6NBQR.js} +2 -2
- package/dist/chunk-UMQ6NBQR.js.map +1 -0
- package/dist/{chunk-7PSNXUFK.js → chunk-XD7MY6HB.js} +1 -1
- package/dist/chunk-XD7MY6HB.js.map +1 -0
- package/dist/{chunk-FJ6F5U3W.js → chunk-XY3N2U6L.js} +5 -5
- package/dist/chunk-XY3N2U6L.js.map +1 -0
- package/dist/{chunk-XZWMJLIT.js → chunk-YT43MUSJ.js} +1 -1
- package/dist/chunk-YT43MUSJ.js.map +1 -0
- package/dist/{claude-code-TA53454O.js → claude-code-LJ6DVXWQ.js} +22 -12
- package/dist/claude-code-LJ6DVXWQ.js.map +1 -0
- package/dist/{claude-code-FS42PXZO.js → claude-code-NMRKTAP7.js} +4 -4
- package/dist/claude-code-NMRKTAP7.js.map +1 -0
- package/dist/cli/sdk.js +7 -7
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{cline-GZFN32BM.js → cline-JAPJNOZQ.js} +6 -6
- package/dist/cline-JAPJNOZQ.js.map +1 -0
- package/dist/{codebuddy-IYS3TQZ3.js → codebuddy-GC7VAE2Y.js} +7 -7
- package/dist/codebuddy-GC7VAE2Y.js.map +1 -0
- package/dist/{codebuff-D3MIKJHC.js → codebuff-3VODFPD4.js} +6 -6
- package/dist/codebuff-3VODFPD4.js.map +1 -0
- package/dist/{codebuff-6KWBW6CT.js → codebuff-ETYT5UBL.js} +4 -4
- package/dist/codebuff-ETYT5UBL.js.map +1 -0
- package/dist/{codex-ZKLP5IXZ.js → codex-RXIS5BHM.js} +9 -9
- package/dist/codex-RXIS5BHM.js.map +1 -0
- package/dist/{codex-DKBAAUCO.js → codex-YAORPCOD.js} +4 -4
- package/dist/codex-YAORPCOD.js.map +1 -0
- package/dist/{continue-I34FNSTJ.js → continue-MECVDV4Z.js} +8 -8
- package/dist/continue-MECVDV4Z.js.map +1 -0
- package/dist/{copilot-cli-CLBJACQ5.js → copilot-cli-MZTAWMPW.js} +4 -4
- package/dist/copilot-cli-MZTAWMPW.js.map +1 -0
- package/dist/{copilot-cli-NWPM5GE6.js → copilot-cli-WVWAWNSM.js} +7 -7
- package/dist/copilot-cli-WVWAWNSM.js.map +1 -0
- package/dist/{crush-A5C5USRL.js → crush-QBXLNN7T.js} +4 -4
- package/dist/crush-QBXLNN7T.js.map +1 -0
- package/dist/{crush-MDGPZSZU.js → crush-YB3SK6NK.js} +7 -7
- package/dist/crush-YB3SK6NK.js.map +1 -0
- package/dist/{cursor-D5SWDVSW.js → cursor-DIW43TRZ.js} +3 -3
- package/dist/cursor-DIW43TRZ.js.map +1 -0
- package/dist/cursor-RSLHA2CY.js +22 -0
- package/dist/{define-connector-B7tLHVnx.d.ts → define-connector-odRHEC4H.d.ts} +1 -1
- package/dist/{detect-FKJC36P4.js → detect-ALP4G7WG.js} +4 -4
- package/dist/detect-ALP4G7WG.js.map +1 -0
- package/dist/{devin-TZMRC57O.js → devin-WPDN3MXE.js} +7 -7
- package/dist/devin-WPDN3MXE.js.map +1 -0
- package/dist/{doctor-PGVYUQYG.js → doctor-YEQWCWZJ.js} +27 -26
- package/dist/doctor-YEQWCWZJ.js.map +1 -0
- package/dist/{droid-SCFWDJR4.js → droid-HS6MX3IL.js} +10 -8
- package/dist/droid-HS6MX3IL.js.map +1 -0
- package/dist/{droid-PFQ2PZSF.js → droid-U3ZBLQFO.js} +4 -4
- package/dist/droid-U3ZBLQFO.js.map +1 -0
- package/dist/{gemini-cli-Y6RJMU24.js → gemini-cli-NMVVBO3K.js} +4 -4
- package/dist/gemini-cli-NMVVBO3K.js.map +1 -0
- package/dist/{gemini-cli-MLDGOR2L.js → gemini-cli-VJ6X5DNF.js} +8 -8
- package/dist/gemini-cli-VJ6X5DNF.js.map +1 -0
- package/dist/{goose-5DBHDSJW.js → goose-3X7ID7YW.js} +9 -9
- package/dist/goose-3X7ID7YW.js.map +1 -0
- package/dist/{goose-K2HKUTBK.js → goose-64V46Y2W.js} +4 -4
- package/dist/goose-64V46Y2W.js.map +1 -0
- package/dist/{grok-cli-LX6Q6RUY.js → grok-cli-4VFVF2CQ.js} +7 -7
- package/dist/grok-cli-4VFVF2CQ.js.map +1 -0
- package/dist/{hermes-LJB3SJKB.js → hermes-AIVUE7LX.js} +10 -8
- package/dist/hermes-AIVUE7LX.js.map +1 -0
- package/dist/{hermes-MF3NX4ZY.js → hermes-F3EGTK6N.js} +4 -4
- package/dist/hermes-F3EGTK6N.js.map +1 -0
- package/dist/{hook-PVGBQUQI.js → hook-F63I3SD5.js} +17 -16
- package/dist/hook-F63I3SD5.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/{install-HPDIK7F6.js → install-23WRRFBY.js} +21 -21
- package/dist/install-23WRRFBY.js.map +1 -0
- package/dist/{introspect-DWCu0Krk.d.ts → introspect-gTx6GzpW.d.ts} +1 -1
- package/dist/{jetbrains-copilot-2DSVAJMJ.js → jetbrains-copilot-XBO2JZRO.js} +6 -6
- package/dist/jetbrains-copilot-XBO2JZRO.js.map +1 -0
- package/dist/{junie-GUBDRADP.js → junie-UCOS6Q37.js} +6 -6
- package/dist/junie-UCOS6Q37.js.map +1 -0
- package/dist/{kilo-SMHPOHJ5.js → kilo-SW7BH6EG.js} +4 -4
- package/dist/kilo-SW7BH6EG.js.map +1 -0
- package/dist/{kilo-HRLWMENX.js → kilo-T4OXNUYY.js} +8 -8
- package/dist/kilo-T4OXNUYY.js.map +1 -0
- package/dist/{kilo-cli-IQMFMYZF.js → kilo-cli-I2S3W245.js} +8 -8
- package/dist/kilo-cli-I2S3W245.js.map +1 -0
- package/dist/{kilo-cli-T2SRRRJS.js → kilo-cli-ZF272ZHN.js} +5 -5
- package/dist/kilo-cli-ZF272ZHN.js.map +1 -0
- package/dist/{kimi-MSIDEMCI.js → kimi-5FHEXGZD.js} +4 -4
- package/dist/kimi-5FHEXGZD.js.map +1 -0
- package/dist/{kimi-EPD46UJK.js → kimi-VLSUFLYV.js} +7 -7
- package/dist/kimi-VLSUFLYV.js.map +1 -0
- package/dist/{kiro-A7DL52FX.js → kiro-AQFXGOJX.js} +10 -8
- package/dist/kiro-AQFXGOJX.js.map +1 -0
- package/dist/{kiro-NYRRBIKW.js → kiro-WGOI5CGT.js} +4 -4
- package/dist/kiro-WGOI5CGT.js.map +1 -0
- package/dist/{leaderboard-KCT7XPCI.js → leaderboard-YBD3IKC2.js} +7 -7
- package/dist/leaderboard-YBD3IKC2.js.map +1 -0
- package/dist/{mimo-code-NDGLBXNC.js → mimo-code-KETL7W7D.js} +7 -7
- package/dist/mimo-code-KETL7W7D.js.map +1 -0
- package/dist/{mistral-vibe-LLWASF5X.js → mistral-vibe-3AU7N2CA.js} +6 -6
- package/dist/mistral-vibe-3AU7N2CA.js.map +1 -0
- package/dist/{mux-ON4QK3OC.js → mux-BO2L5CTW.js} +6 -6
- package/dist/mux-BO2L5CTW.js.map +1 -0
- package/dist/{mux-7PIJ7HUQ.js → mux-XM6AP35L.js} +4 -4
- package/dist/mux-XM6AP35L.js.map +1 -0
- package/dist/{nemoclaw-45R5MFBF.js → nemoclaw-WA7RSKF2.js} +7 -7
- package/dist/nemoclaw-WA7RSKF2.js.map +1 -0
- package/dist/{omp-ROCTFV3A.js → omp-UDYJ2PYY.js} +9 -7
- package/dist/omp-UDYJ2PYY.js.map +1 -0
- package/dist/{open-interpreter-V6CN542J.js → open-interpreter-WMBNM4MQ.js} +6 -6
- package/dist/open-interpreter-WMBNM4MQ.js.map +1 -0
- package/dist/openclaw-3DHVHX5P.js +17 -0
- package/dist/{openclaw-KAFTNLR2.js → openclaw-5EQFGOWL.js} +4 -4
- package/dist/openclaw-5EQFGOWL.js.map +1 -0
- package/dist/{opencode-YYWQ45LF.js → opencode-IKMI3RI7.js} +7 -7
- package/dist/opencode-IKMI3RI7.js.map +1 -0
- package/dist/{opencode-Z65JYILL.js → opencode-QGP4ALQY.js} +4 -4
- package/dist/opencode-QGP4ALQY.js.map +1 -0
- package/dist/{openhands-OFFMWCQW.js → openhands-QGXMQR6I.js} +7 -7
- package/dist/openhands-QGXMQR6I.js.map +1 -0
- package/dist/{package-TALOSRQ4.js → package-TAUTPP7Z.js} +15 -15
- package/dist/package-TAUTPP7Z.js.map +1 -0
- package/dist/{pi-4W74ETTI.js → pi-A2HCGRJG.js} +9 -7
- package/dist/pi-A2HCGRJG.js.map +1 -0
- package/dist/{pi-DLKCPOJE.js → pi-GGDQREVG.js} +4 -4
- package/dist/pi-GGDQREVG.js.map +1 -0
- package/dist/{qwen-code-JOBFNEVT.js → qwen-code-DNQTGJOF.js} +28 -10
- package/dist/qwen-code-DNQTGJOF.js.map +1 -0
- package/dist/{qwen-code-26CSFDX6.js → qwen-code-GQILBJ5B.js} +4 -4
- package/dist/qwen-code-GQILBJ5B.js.map +1 -0
- package/dist/{roo-code-HSAE2CJU.js → roo-code-SUWI4BBN.js} +4 -4
- package/dist/roo-code-SUWI4BBN.js.map +1 -0
- package/dist/{roo-code-RHIGJZNY.js → roo-code-VI2ZKTZC.js} +6 -6
- package/dist/roo-code-VI2ZKTZC.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +15 -14
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +12 -11
- package/dist/{serve-4TEHK726.js → serve-6MDLRQS2.js} +17 -16
- package/dist/serve-6MDLRQS2.js.map +1 -0
- package/dist/{status-DVD4EHMX.js → status-IUP75XHP.js} +11 -11
- package/dist/status-IUP75XHP.js.map +1 -0
- package/dist/{statusline-ZVNH7XBK.js → statusline-PRODZV2J.js} +16 -15
- package/dist/statusline-PRODZV2J.js.map +1 -0
- package/dist/{synthetic-LUT6V6SD.js → synthetic-6FRA7P5Q.js} +4 -4
- package/dist/synthetic-6FRA7P5Q.js.map +1 -0
- package/dist/{telemetry-NWUJPIK3.js → telemetry-X4PLZEDB.js} +10 -10
- package/dist/telemetry-X4PLZEDB.js.map +1 -0
- package/dist/{trae-SIQI3C66.js → trae-CPPYASR2.js} +4 -4
- package/dist/trae-CPPYASR2.js.map +1 -0
- package/dist/{trae-TLAFSQRQ.js → trae-VOJXUYRN.js} +6 -6
- package/dist/trae-VOJXUYRN.js.map +1 -0
- package/dist/{types-C6j18a6R.d.ts → types-DWXnnx-N.d.ts} +83 -8
- package/dist/{uninstall-DZVFV7KE.js → uninstall-BSIJ4QXN.js} +21 -21
- package/dist/uninstall-BSIJ4QXN.js.map +1 -0
- package/dist/{upgrade-OUE4ED52.js → upgrade-ZSICU3NE.js} +21 -21
- package/dist/upgrade-ZSICU3NE.js.map +1 -0
- package/dist/{usage-NT3ZXALZ.js → usage-EQUNVSCT.js} +4 -4
- package/dist/usage-EQUNVSCT.js.map +1 -0
- package/dist/{usage-event-IELZE6WO.js → usage-event-J5CQ6LNT.js} +16 -15
- package/dist/usage-event-J5CQ6LNT.js.map +1 -0
- package/dist/{vscode-copilot-VZ5XYSTK.js → vscode-copilot-ZBXRPKGG.js} +7 -7
- package/dist/vscode-copilot-ZBXRPKGG.js.map +1 -0
- package/dist/{warp-5YBSP7FP.js → warp-NRBBJQR2.js} +4 -4
- package/dist/warp-NRBBJQR2.js.map +1 -0
- package/dist/{warp-P2HWXIKT.js → warp-S444B2S3.js} +9 -7
- package/dist/warp-S444B2S3.js.map +1 -0
- package/dist/{windsurf-3JC73GZK.js → windsurf-R6D2JUTN.js} +6 -6
- package/dist/windsurf-R6D2JUTN.js.map +1 -0
- package/dist/{zed-6CMUKXLI.js → zed-DQV3ZUCU.js} +10 -8
- package/dist/zed-DQV3ZUCU.js.map +1 -0
- package/dist/{zed-XXCNYOIN.js → zed-XJFOOKCO.js} +4 -4
- package/dist/zed-XJFOOKCO.js.map +1 -0
- package/package.json +88 -88
- package/dist/action-5JM23CFJ.js.map +0 -1
- package/dist/amazon-q-LFZNGN27.js.map +0 -1
- package/dist/amp-CEWOSWQO.js.map +0 -1
- package/dist/amp-S22XTPEQ.js.map +0 -1
- package/dist/antigravity-LHFEFNMC.js.map +0 -1
- package/dist/antigravity-PZXYAO3X.js +0 -18
- package/dist/antigravity-cli-MOKFSWOU.js.map +0 -1
- package/dist/antigravity-cli-PN474FXM.js.map +0 -1
- package/dist/chunk-4GH2KA7V.js.map +0 -1
- package/dist/chunk-6XWORQM6.js.map +0 -1
- package/dist/chunk-7C2IPIIB.js.map +0 -1
- package/dist/chunk-7HHW23AC.js.map +0 -1
- package/dist/chunk-7PSNXUFK.js.map +0 -1
- package/dist/chunk-7VSZXOXJ.js.map +0 -1
- package/dist/chunk-B6PKHS5I.js.map +0 -1
- package/dist/chunk-C747DYNT.js.map +0 -1
- package/dist/chunk-DOPFBUCX.js.map +0 -1
- package/dist/chunk-DWZ5IWF4.js.map +0 -1
- package/dist/chunk-FJ6F5U3W.js.map +0 -1
- package/dist/chunk-HATCOSQT.js.map +0 -1
- package/dist/chunk-ILWHLGIC.js.map +0 -1
- package/dist/chunk-IOJDZJ72.js.map +0 -1
- package/dist/chunk-KFPSJRHR.js.map +0 -1
- package/dist/chunk-KM2YXO6V.js.map +0 -1
- package/dist/chunk-KTBAB556.js.map +0 -1
- package/dist/chunk-KWC5DQ5Z.js.map +0 -1
- package/dist/chunk-LD5HAN6O.js.map +0 -1
- package/dist/chunk-LFWYYWLV.js.map +0 -1
- package/dist/chunk-LZL2YITN.js.map +0 -1
- package/dist/chunk-PSGTHJQU.js.map +0 -1
- package/dist/chunk-Q4ISQHUQ.js.map +0 -1
- package/dist/chunk-Q7PR2WGT.js.map +0 -1
- package/dist/chunk-QYOUQCC6.js.map +0 -1
- package/dist/chunk-RNVIK5YJ.js.map +0 -1
- package/dist/chunk-RPWD5H6Y.js.map +0 -1
- package/dist/chunk-S25MVWBP.js.map +0 -1
- package/dist/chunk-THI4PI4H.js.map +0 -1
- package/dist/chunk-TOSNS2BY.js.map +0 -1
- package/dist/chunk-UNU2KPYJ.js.map +0 -1
- package/dist/chunk-UZZTWWGG.js.map +0 -1
- package/dist/chunk-W7AGWAMH.js.map +0 -1
- package/dist/chunk-XN7S44U4.js.map +0 -1
- package/dist/chunk-XXLCMSD3.js.map +0 -1
- package/dist/chunk-XZWMJLIT.js.map +0 -1
- package/dist/chunk-ZSOS2KOR.js.map +0 -1
- package/dist/claude-code-FS42PXZO.js.map +0 -1
- package/dist/claude-code-TA53454O.js.map +0 -1
- package/dist/cline-GZFN32BM.js.map +0 -1
- package/dist/codebuddy-IYS3TQZ3.js.map +0 -1
- package/dist/codebuff-6KWBW6CT.js.map +0 -1
- package/dist/codebuff-D3MIKJHC.js.map +0 -1
- package/dist/codex-DKBAAUCO.js.map +0 -1
- package/dist/codex-ZKLP5IXZ.js.map +0 -1
- package/dist/continue-I34FNSTJ.js.map +0 -1
- package/dist/copilot-cli-CLBJACQ5.js.map +0 -1
- package/dist/copilot-cli-NWPM5GE6.js.map +0 -1
- package/dist/crush-A5C5USRL.js.map +0 -1
- package/dist/crush-MDGPZSZU.js.map +0 -1
- package/dist/cursor-D5SWDVSW.js.map +0 -1
- package/dist/cursor-JRVK56QA.js +0 -22
- package/dist/detect-FKJC36P4.js.map +0 -1
- package/dist/devin-TZMRC57O.js.map +0 -1
- package/dist/doctor-PGVYUQYG.js.map +0 -1
- package/dist/droid-PFQ2PZSF.js.map +0 -1
- package/dist/droid-SCFWDJR4.js.map +0 -1
- package/dist/gemini-cli-MLDGOR2L.js.map +0 -1
- package/dist/gemini-cli-Y6RJMU24.js.map +0 -1
- package/dist/goose-5DBHDSJW.js.map +0 -1
- package/dist/goose-K2HKUTBK.js.map +0 -1
- package/dist/grok-cli-LX6Q6RUY.js.map +0 -1
- package/dist/hermes-LJB3SJKB.js.map +0 -1
- package/dist/hermes-MF3NX4ZY.js.map +0 -1
- package/dist/hook-PVGBQUQI.js.map +0 -1
- package/dist/install-HPDIK7F6.js.map +0 -1
- package/dist/jetbrains-copilot-2DSVAJMJ.js.map +0 -1
- package/dist/junie-GUBDRADP.js.map +0 -1
- package/dist/kilo-HRLWMENX.js.map +0 -1
- package/dist/kilo-SMHPOHJ5.js.map +0 -1
- package/dist/kilo-cli-IQMFMYZF.js.map +0 -1
- package/dist/kilo-cli-T2SRRRJS.js.map +0 -1
- package/dist/kimi-EPD46UJK.js.map +0 -1
- package/dist/kimi-MSIDEMCI.js.map +0 -1
- package/dist/kiro-A7DL52FX.js.map +0 -1
- package/dist/kiro-NYRRBIKW.js.map +0 -1
- package/dist/leaderboard-KCT7XPCI.js.map +0 -1
- package/dist/mimo-code-NDGLBXNC.js.map +0 -1
- package/dist/mistral-vibe-LLWASF5X.js.map +0 -1
- package/dist/mux-7PIJ7HUQ.js.map +0 -1
- package/dist/mux-ON4QK3OC.js.map +0 -1
- package/dist/nemoclaw-45R5MFBF.js.map +0 -1
- package/dist/omp-ROCTFV3A.js.map +0 -1
- package/dist/open-interpreter-V6CN542J.js.map +0 -1
- package/dist/openclaw-AOKFJGRQ.js +0 -17
- package/dist/openclaw-KAFTNLR2.js.map +0 -1
- package/dist/opencode-YYWQ45LF.js.map +0 -1
- package/dist/opencode-Z65JYILL.js.map +0 -1
- package/dist/openhands-OFFMWCQW.js.map +0 -1
- package/dist/package-TALOSRQ4.js.map +0 -1
- package/dist/pi-4W74ETTI.js.map +0 -1
- package/dist/pi-DLKCPOJE.js.map +0 -1
- package/dist/qwen-code-26CSFDX6.js.map +0 -1
- package/dist/qwen-code-JOBFNEVT.js.map +0 -1
- package/dist/roo-code-HSAE2CJU.js.map +0 -1
- package/dist/roo-code-RHIGJZNY.js.map +0 -1
- package/dist/serve-4TEHK726.js.map +0 -1
- package/dist/status-DVD4EHMX.js.map +0 -1
- package/dist/statusline-ZVNH7XBK.js.map +0 -1
- package/dist/synthetic-LUT6V6SD.js.map +0 -1
- package/dist/telemetry-NWUJPIK3.js.map +0 -1
- package/dist/trae-SIQI3C66.js.map +0 -1
- package/dist/trae-TLAFSQRQ.js.map +0 -1
- package/dist/uninstall-DZVFV7KE.js.map +0 -1
- package/dist/upgrade-OUE4ED52.js.map +0 -1
- package/dist/usage-NT3ZXALZ.js.map +0 -1
- package/dist/usage-event-IELZE6WO.js.map +0 -1
- package/dist/vscode-copilot-VZ5XYSTK.js.map +0 -1
- package/dist/warp-5YBSP7FP.js.map +0 -1
- package/dist/warp-P2HWXIKT.js.map +0 -1
- package/dist/windsurf-3JC73GZK.js.map +0 -1
- package/dist/zed-6CMUKXLI.js.map +0 -1
- package/dist/zed-XXCNYOIN.js.map +0 -1
- /package/dist/{antigravity-PZXYAO3X.js.map → antigravity-VXHL6ZPM.js.map} +0 -0
- /package/dist/{audit-2H7E3Z4N.js.map → audit-BO7JQYIH.js.map} +0 -0
- /package/dist/{cursor-JRVK56QA.js.map → cursor-RSLHA2CY.js.map} +0 -0
- /package/dist/{openclaw-AOKFJGRQ.js.map → openclaw-3DHVHX5P.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/package.ts","../src/core/package-formats/claude-family.ts","../src/core/package-formats/shared.ts","../src/core/package-formats/cursor.ts","../src/core/package-formats/gemini.ts","../src/core/package-formats/agy.ts","../src/core/package-formats/kimi.ts","../src/core/package-formats/npm.ts","../src/core/package-formats/mcp-server.ts","../src/core/package-formats/mcpb.ts"],"sourcesContent":["/**\r\n * core/package — emit a marketplace/extension-installable connector bundle.\r\n *\r\n * Turns a {@link ResolvedConnector} into a self-contained plugin/extension bundle\r\n * for ANY of the emit-feasible plugin/marketplace formats the agent ecosystem\r\n * supports. The format-specific emitters live under `package-formats/<family>.ts`,\r\n * each conforming to the shared {@link FormatEmitter} signature; this module is\r\n * the single, consistent dispatch over them.\r\n *\r\n * Supported formats (PackageFormat):\r\n * • claude-plugin — Claude Code / codex / vscode-copilot / openclaw / omp\r\n * • codex-plugin — Codex `.codex-plugin/` manifest variant of claude-plugin\r\n * • copilot-plugin — GitHub Copilot CLI (claude-plugin bundle, --host copilot-cli)\r\n * • factory-plugin — droid `.factory-plugin/` (droids/, mcp.json) variant\r\n * • gemini-extension — Gemini CLI extension (gemini-extension.json + TOML commands)\r\n * • qwen-extension — Qwen Code extension (qwen-extension.json + Markdown commands)\r\n * • agy-plugin — Antigravity CLI/IDE (root plugin.json + mcp_config.json)\r\n * • cursor-plugin — Cursor (.cursor-plugin/ + pointer fields + marketplace.json)\r\n * • kimi-plugin — Kimi (skills + MCP only; hooks/commands/subagents dropped)\r\n * • npm-plugin — opencode / kilo-cli / pi (publishable npm package + bridge)\r\n *\r\n * The command / skill / subagent markdown is rendered through the SAME shared\r\n * claude-code renderers the live adapters write with (where the target uses\r\n * markdown), hooks via buildHomeBinHookCommand, and MCP via buildServeWrapperCommand\r\n * with `--host <platform>` — so telemetry-wrap + the universal home-bin pointer\r\n * carry through every bundle exactly as an `agent-connector install` would.\r\n */\r\n\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { join, resolve } from \"node:path\";\r\n\r\nimport type { ResolvedConnector } from \"./types.js\";\r\nimport { homeBinPath as defaultHomeBinPath } from \"./paths.js\";\r\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./package-formats/shared.js\";\r\nimport {\r\n emitClaudePlugin,\r\n emitCodexPlugin,\r\n emitCopilotPlugin,\r\n emitFactoryPlugin,\r\n} from \"./package-formats/claude-family.js\";\r\nimport { emitCursorPlugin } from \"./package-formats/cursor.js\";\r\nimport {\r\n emitGeminiExtension,\r\n emitQwenExtension,\r\n} from \"./package-formats/gemini.js\";\r\nimport { emitAgyPlugin } from \"./package-formats/agy.js\";\r\nimport { emitKimiPlugin } from \"./package-formats/kimi.js\";\r\nimport { emitNpmPlugin } from \"./package-formats/npm.js\";\r\nimport { emitMcpServerJson } from \"./package-formats/mcp-server.js\";\r\nimport { emitMcpbBundle } from \"./package-formats/mcpb.js\";\r\n\r\nexport type { PackageResult } from \"./package-formats/shared.js\";\r\n\r\n/** Every packaging format `package` can emit. */\r\nexport type PackageFormat =\r\n | \"claude-plugin\"\r\n | \"codex-plugin\"\r\n | \"copilot-plugin\"\r\n | \"factory-plugin\"\r\n | \"gemini-extension\"\r\n | \"qwen-extension\"\r\n | \"agy-plugin\"\r\n | \"cursor-plugin\"\r\n | \"kimi-plugin\"\r\n | \"npm-plugin\"\r\n // Official MCP standard artifacts (describe the dev's REAL upstream server,\r\n // not our serve wrapper; require `publish` metadata, so they are opt-in and\r\n // excluded from `--format all`).\r\n | \"mcp-server-json\"\r\n | \"mcpb\";\r\n\r\n/** The single consistent dispatch map: format → emitter. */\r\nconst EMITTERS: Record<PackageFormat, FormatEmitter> = {\r\n \"claude-plugin\": emitClaudePlugin,\r\n \"codex-plugin\": emitCodexPlugin,\r\n \"copilot-plugin\": emitCopilotPlugin,\r\n \"factory-plugin\": emitFactoryPlugin,\r\n \"gemini-extension\": emitGeminiExtension,\r\n \"qwen-extension\": emitQwenExtension,\r\n \"agy-plugin\": emitAgyPlugin,\r\n \"cursor-plugin\": emitCursorPlugin,\r\n \"kimi-plugin\": emitKimiPlugin,\r\n \"npm-plugin\": emitNpmPlugin,\r\n \"mcp-server-json\": emitMcpServerJson,\r\n mcpb: emitMcpbBundle,\r\n};\r\n\r\n/** All formats, in a stable, documented order. */\r\nexport const ALL_FORMATS: readonly PackageFormat[] = [\r\n \"claude-plugin\",\r\n \"codex-plugin\",\r\n \"copilot-plugin\",\r\n \"factory-plugin\",\r\n \"gemini-extension\",\r\n \"qwen-extension\",\r\n \"agy-plugin\",\r\n \"cursor-plugin\",\r\n \"kimi-plugin\",\r\n \"npm-plugin\",\r\n \"mcp-server-json\",\r\n \"mcpb\",\r\n] as const;\r\n\r\n/**\r\n * The formats `--format all` emits — the host plugin/marketplace bundles that\r\n * work for ANY connector. The official MCP standard artifacts (mcp-server-json,\r\n * and the MCPB bundle) are deliberately EXCLUDED: they require `publish`\r\n * metadata (a namespace the dev owns, their published package) and would error\r\n * for a connector that has not opted into publishing, so they are emitted only\r\n * when requested explicitly by name.\r\n */\r\nexport const FEASIBLE_FORMATS: readonly PackageFormat[] = [\r\n \"claude-plugin\",\r\n \"codex-plugin\",\r\n \"copilot-plugin\",\r\n \"factory-plugin\",\r\n \"gemini-extension\",\r\n \"qwen-extension\",\r\n \"agy-plugin\",\r\n \"cursor-plugin\",\r\n \"kimi-plugin\",\r\n \"npm-plugin\",\r\n] as const;\r\n\r\n/** Type guard: is `s` a supported {@link PackageFormat}? */\r\nexport function isPackageFormat(s: string): s is PackageFormat {\r\n return Object.prototype.hasOwnProperty.call(EMITTERS, s);\r\n}\r\n\r\nexport interface PackageOptions {\r\n /** Directory the bundle is written under (the format root). */\r\n outDir: string;\r\n /** Output format. Defaults to \"claude-plugin\". */\r\n format?: PackageFormat;\r\n /**\r\n * Absolute path to agent-connector's stable home-bin that hooks + the MCP\r\n * serve-wrapper point at. Defaults to {@link defaultHomeBinPath}.\r\n */\r\n homeBinPath?: string;\r\n /** Compute the file list without writing anything. */\r\n dryRun?: boolean;\r\n}\r\n\r\n/**\r\n * Emit a bundle for `connector` in a single `format` (default claude-plugin).\r\n *\r\n * Writes (or, for dryRun, only enumerates) the bundle under `opts.outDir`.\r\n * Returns the absolute file list, the plugin root dir, an optional marketplace\r\n * path, and optional drop notes (for lossy formats like kimi-plugin).\r\n */\r\n/**\r\n * Host-bundle formats whose hooks/MCP entries embed the ABSOLUTE home-bin path\r\n * of the machine that ran `package`. They install fine locally, but on another\r\n * machine/user the baked path points at nothing — so every emit carries a note.\r\n * (npm-plugin resolves the CLI by name on PATH; mcp-server-json/mcpb describe\r\n * the dev's real upstream server — none of those embed a local path.)\r\n */\r\nconst HOME_BIN_EMBED_FORMATS: ReadonlySet<PackageFormat> = new Set([\r\n \"claude-plugin\",\r\n \"codex-plugin\",\r\n \"copilot-plugin\",\r\n \"factory-plugin\",\r\n \"gemini-extension\",\r\n \"qwen-extension\",\r\n \"agy-plugin\",\r\n \"cursor-plugin\",\r\n \"kimi-plugin\",\r\n]);\r\n\r\nexport function packageConnector(\r\n connector: ResolvedConnector,\r\n opts: PackageOptions,\r\n): PackageResult {\r\n const format = opts.format ?? \"claude-plugin\";\r\n const emitter = EMITTERS[format];\r\n if (!emitter) {\r\n throw new Error(`unsupported package format: ${format}`);\r\n }\r\n\r\n const ctx: EmitContext = {\r\n outDir: resolve(opts.outDir),\r\n homeBinPath: opts.homeBinPath ?? defaultHomeBinPath(),\r\n dryRun: opts.dryRun ?? false,\r\n };\r\n const result = emitter(connector, ctx);\r\n if (HOME_BIN_EMBED_FORMATS.has(format)) {\r\n const note =\r\n `bundle embeds this machine's agent-connector launcher path (${ctx.homeBinPath}) — ` +\r\n \"valid for LOCAL install; for a shared marketplace, consumers need agent-connector \" +\r\n \"at the same home path (run `agent-connector upgrade` there) or re-run `package` per machine\";\r\n result.notes = [...(result.notes ?? []), note];\r\n }\r\n return result;\r\n}\r\n\r\n/** One entry in a multi-format ({@link packageConnectorAll}) emit. */\r\nexport interface MultiPackageResult {\r\n format: PackageFormat;\r\n result: PackageResult;\r\n}\r\n\r\n/**\r\n * Emit EVERY feasible format, each into its own `<outDir>/<format>/` subdir, so a\r\n * single `package --format all` produces the whole matrix without collisions.\r\n */\r\nexport function packageConnectorAll(\r\n connector: ResolvedConnector,\r\n opts: { outDir: string; homeBinPath?: string; dryRun?: boolean },\r\n): MultiPackageResult[] {\r\n const base = resolve(opts.outDir);\r\n const homeBin = opts.homeBinPath ?? defaultHomeBinPath();\r\n const dryRun = opts.dryRun ?? false;\r\n return FEASIBLE_FORMATS.map((format) => ({\r\n format,\r\n result: packageConnector(connector, {\r\n outDir: resolve(base, format),\r\n format,\r\n homeBinPath: homeBin,\r\n dryRun,\r\n }),\r\n }));\r\n}\r\n\r\n/**\r\n * Per-format MANUAL install commands (the accurate two-step add+install where\r\n * applicable). Lives in core (not the CLI) so both `package`'s printed\r\n * instructions and the marketplace method's skip-warn records for non-drivable\r\n * hosts quote the SAME commands — one copy, no drift.\r\n */\r\nexport function installInstructions(\r\n format: PackageFormat,\r\n id: string,\r\n outDir: string,\r\n): string[] {\r\n switch (format) {\r\n case \"claude-plugin\":\r\n return [\r\n `/plugin marketplace add ${outDir}`,\r\n `/plugin install ${id}@agent-connector`,\r\n `(CLI: claude plugin marketplace add ${outDir} && claude plugin install ${id}@agent-connector)`,\r\n ];\r\n case \"codex-plugin\":\r\n return [\r\n `codex plugin marketplace add ${outDir}`,\r\n `codex plugin add ${id}@agent-connector`,\r\n ];\r\n case \"copilot-plugin\":\r\n return [\r\n `copilot plugin marketplace add ${outDir}`,\r\n `copilot plugin install ${id}@agent-connector`,\r\n ];\r\n case \"factory-plugin\":\r\n return [\r\n `droid plugin marketplace add ${outDir}`,\r\n `droid plugin install ${id}@agent-connector`,\r\n ];\r\n case \"gemini-extension\":\r\n return [`gemini extensions install ${join(outDir, id)}`];\r\n case \"qwen-extension\":\r\n return [`qwen extensions install ${join(outDir, id)}`];\r\n case \"agy-plugin\":\r\n return [\r\n `agy plugin install ${join(outDir, id)}`,\r\n `(validate: agy plugin validate ${join(outDir, id)})`,\r\n ];\r\n case \"cursor-plugin\":\r\n return [\r\n `link ${join(outDir, id)} into ~/.cursor/plugins/local/${id}/ then Developer: Reload Window`,\r\n `(or publish ${outDir} as a Cursor marketplace repo)`,\r\n ];\r\n case \"kimi-plugin\":\r\n return [`kimi plugin install ${join(outDir, id)}`];\r\n case \"npm-plugin\":\r\n return [\r\n `npm publish ${join(outDir, id)} (then: opencode plugin install <pkg> | kilo plugin <pkg> | pi install npm:<pkg>)`,\r\n ];\r\n case \"mcp-server-json\":\r\n return [\r\n `mcp-publisher login <github|dns|http> (prove ownership of your namespace once)`,\r\n `cd ${outDir} && mcp-publisher publish (uploads server.json to the official MCP Registry)`,\r\n ];\r\n case \"mcpb\":\r\n return [\r\n `vendor your built server under ${join(outDir, \"server\")}/ (see the emitted README)`,\r\n `npx @anthropic-ai/mcpb pack ${outDir} (then optionally: mcpb sign)`,\r\n ];\r\n default:\r\n return [];\r\n }\r\n}\r\n\r\n/** Read + parse a JSON file (used by callers/tests). Returns null on absence/parse error. */\r\nexport function readPackagedJson<T = unknown>(path: string): T | null {\r\n if (!existsSync(path)) return null;\r\n try {\r\n return JSON.parse(readFileSync(path, \"utf8\")) as T;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n","/**\r\n * core/package-formats/claude-family — the claude-plugin emitter + its\r\n * manifest-rename / host-restamp siblings (codex-plugin, factory-plugin,\r\n * copilot-plugin).\r\n *\r\n * All share ONE component tree (commands/ agents-or-droids/ skills/<n>/\r\n * SKILL.md + hooks/hooks.json + an MCP json) and differ only in:\r\n * • the manifest DIR + filename (.claude-plugin/ | .codex-plugin/ | .factory-plugin/)\r\n * • the subagent dir name (agents/ vs droids/ for factory)\r\n * • the MCP filename (.mcp.json vs mcp.json for factory)\r\n * • the manifest extra fields (claude adds $schema; factory pins version+author)\r\n * • the marketplace catalog shape (claude/codex object-owner; factory git-repo catalog)\r\n * • the platform stamped into hooks/MCP (--host, so telemetry routes per host)\r\n *\r\n * copilot-plugin is the claude-plugin bundle EXACTLY (GitHub Copilot CLI 1.0.63\r\n * accepts a Claude-shaped `.claude-plugin/` bundle byte-for-byte — live-verified:\r\n * `copilot plugin marketplace add <dir>` + `copilot plugin install <id>@<mkt>`\r\n * succeed and `copilot plugin list` shows it), differing ONLY in the --host\r\n * stamp (`copilot-cli`) so the wrapped MCP server + hook commands route telemetry\r\n * to the copilot host instead of claude.\r\n *\r\n * The command / skill / subagent markdown is rendered through the SAME shared\r\n * claude-code renderers the live adapter writes with, so an installed plugin and\r\n * an `agent-connector install` produce byte-identical content files. Hooks use\r\n * the universal home-bin command (telemetry-routed) and the MCP entry is\r\n * serve-wrapped with `--host <platform>` so telemetry carries through.\r\n */\r\n\r\nimport { join } from \"node:path\";\r\n\r\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\r\nimport {\r\n renderCommandMd,\r\n renderSkillMd,\r\n renderSubagentMd,\r\n} from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n buildClaudeHooksJson,\r\n buildMcpEntry,\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\n/** Per-variant layout + manifest knobs for a Claude-family bundle. */\r\ninterface ClaudeFamilySpec {\r\n /** Host platform stamped into the serve-wrapper + hook command (--host). */\r\n platformId: PlatformId;\r\n /** Manifest directory under the plugin root (e.g. \".claude-plugin\"). */\r\n manifestDir: string;\r\n /** Subagent directory name (claude/codex: \"agents\"; factory: \"droids\"). */\r\n subagentDir: string;\r\n /** MCP filename at the plugin root (claude/codex: \".mcp.json\"; factory: \"mcp.json\"). */\r\n mcpFile: string;\r\n /** Add `$schema` to plugin.json (claude only). */\r\n schemaUrl?: string;\r\n /** Always carry a version in plugin.json, defaulting placeholder to \"0.0.1\" (factory requires it). */\r\n requireVersion?: boolean;\r\n /** Always carry an `author` object in plugin.json (factory pins it). */\r\n alwaysAuthor?: boolean;\r\n /**\r\n * Where to write the marketplace catalog, relative to outDir, and which shape.\r\n * \"claude\": <outDir>/.claude-plugin/marketplace.json (object owner).\r\n * \"codex\": <outDir>/.agents/plugins/marketplace.json (same object-owner\r\n * catalog; codex's documented location — `codex plugin marketplace\r\n * add` REJECTS a `.codex-plugin/` catalog with \"marketplace root\r\n * does not contain a supported manifest\"; live-verified 0.139.0).\r\n * \"factory\":<outDir>/marketplace.json (git-repo catalog at the repo root).\r\n */\r\n marketplace: { dir: string | null; file: string; shape: \"claude\" | \"factory\" };\r\n}\r\n\r\nconst SPECS: Record<string, ClaudeFamilySpec> = {\r\n \"claude-plugin\": {\r\n platformId: \"claude-code\",\r\n manifestDir: \".claude-plugin\",\r\n subagentDir: \"agents\",\r\n mcpFile: \".mcp.json\",\r\n schemaUrl: \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\r\n marketplace: { dir: \".claude-plugin\", file: \"marketplace.json\", shape: \"claude\" },\r\n },\r\n \"codex-plugin\": {\r\n platformId: \"codex\",\r\n manifestDir: \".codex-plugin\",\r\n subagentDir: \"agents\",\r\n mcpFile: \".mcp.json\",\r\n marketplace: {\r\n dir: join(\".agents\", \"plugins\"),\r\n file: \"marketplace.json\",\r\n shape: \"claude\",\r\n },\r\n },\r\n \"copilot-plugin\": {\r\n // copilot-cli accepts a Claude-shaped bundle as-is; the ONLY difference from\r\n // claude-plugin is the --host stamp so the wrapped MCP + hook commands route\r\n // telemetry to the copilot host. Same `.claude-plugin/` manifest dir + schema\r\n // + `.claude-plugin/marketplace.json` catalog (live-verified on CLI 1.0.63).\r\n platformId: \"copilot-cli\",\r\n manifestDir: \".claude-plugin\",\r\n subagentDir: \"agents\",\r\n mcpFile: \".mcp.json\",\r\n schemaUrl: \"https://json.schemastore.org/claude-code-plugin-manifest.json\",\r\n marketplace: { dir: \".claude-plugin\", file: \"marketplace.json\", shape: \"claude\" },\r\n },\r\n \"factory-plugin\": {\r\n platformId: \"droid\",\r\n manifestDir: \".factory-plugin\",\r\n subagentDir: \"droids\",\r\n mcpFile: \"mcp.json\",\r\n requireVersion: true,\r\n alwaysAuthor: true,\r\n // droid marketplaces are Git-repo catalogs; the catalog sits at the repo root.\r\n marketplace: { dir: null, file: \"marketplace.json\", shape: \"factory\" },\r\n },\r\n};\r\n\r\n/** Build the plugin manifest for a Claude-family variant. */\r\nfunction buildManifest(\r\n connector: ResolvedConnector,\r\n spec: ClaudeFamilySpec,\r\n): Record<string, unknown> {\r\n const manifest: Record<string, unknown> = {};\r\n if (spec.schemaUrl) manifest.$schema = spec.schemaUrl;\r\n manifest.name = connector.id;\r\n manifest.description = `${connector.displayName} — connector emitted by agent-connector`;\r\n\r\n const hasRealVersion = connector.version && connector.version !== \"0.0.0\";\r\n if (hasRealVersion) {\r\n manifest.version = connector.version;\r\n } else if (spec.requireVersion) {\r\n // factory requires a semver version; supply a sane default when unpinned.\r\n manifest.version = \"0.0.1\";\r\n }\r\n // Attribute the bundle to the connector developer when they declared an\r\n // author (publish.author); the framework name is only the fallback.\r\n if (spec.alwaysAuthor) {\r\n manifest.author = { name: connector.publish?.author?.name ?? \"agent-connector\" };\r\n }\r\n return manifest;\r\n}\r\n\r\n/** Build the marketplace catalog for a Claude-family variant. */\r\nfunction buildMarketplace(connector: ResolvedConnector): Record<string, unknown> {\r\n // Both the claude/codex object-owner catalog and the droid git-repo catalog\r\n // use the same minimal { name, owner, plugins:[{name,source,description}] }\r\n // shape — droid reads source as a path relative to the marketplace repo root.\r\n // The catalog NAME stays \"agent-connector\" (the printed install instructions\r\n // `<id>@agent-connector` key on it); the OWNER is the developer when known.\r\n return {\r\n name: \"agent-connector\",\r\n owner: { name: connector.publish?.author?.name ?? \"agent-connector\" },\r\n plugins: [\r\n {\r\n name: connector.id,\r\n source: `./${connector.id}`,\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n },\r\n ],\r\n };\r\n}\r\n\r\n/** Emit a Claude-family bundle (claude-plugin | codex-plugin | factory-plugin). */\r\nfunction emitClaudeFamily(\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n format: keyof typeof SPECS,\r\n): PackageResult {\r\n const spec = SPECS[format];\r\n if (!spec) throw new Error(`unknown claude-family format: ${format}`);\r\n\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n\r\n // ── plugin.json (the ONLY file inside the manifest dir) ───────────────────\r\n emit(\r\n join(pluginDir, spec.manifestDir, \"plugin.json\"),\r\n json(buildManifest(connector, spec)),\r\n );\r\n\r\n // ── commands/<name>.md ────────────────────────────────────────────────────\r\n for (const cmd of connector.commands) {\r\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\r\n }\r\n\r\n // ── agents|droids/<name>.md ───────────────────────────────────────────────\r\n for (const agent of connector.subagents) {\r\n emit(\r\n join(pluginDir, spec.subagentDir, `${agent.name}.md`),\r\n renderSubagentMd(agent),\r\n );\r\n }\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue; // never write outside the skill dir\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── hooks/hooks.json (mapped events only) ─────────────────────────────────\r\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, spec.platformId);\r\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\r\n\r\n // ── MCP json (serve-wrapped stdio server) ─────────────────────────────────\r\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, spec.platformId);\r\n if (mcp) {\r\n emit(\r\n join(pluginDir, spec.mcpFile),\r\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\r\n );\r\n }\r\n\r\n // ── marketplace catalog ───────────────────────────────────────────────────\r\n const marketplacePath = spec.marketplace.dir\r\n ? join(ctx.outDir, spec.marketplace.dir, spec.marketplace.file)\r\n : join(ctx.outDir, spec.marketplace.file);\r\n emit(marketplacePath, json(buildMarketplace(connector)));\r\n\r\n return { files, pluginDir, marketplacePath };\r\n}\r\n\r\nexport const emitClaudePlugin: FormatEmitter = (connector, ctx) =>\r\n emitClaudeFamily(connector, ctx, \"claude-plugin\");\r\n\r\nexport const emitCodexPlugin: FormatEmitter = (connector, ctx) =>\r\n emitClaudeFamily(connector, ctx, \"codex-plugin\");\r\n\r\nexport const emitFactoryPlugin: FormatEmitter = (connector, ctx) =>\r\n emitClaudeFamily(connector, ctx, \"factory-plugin\");\r\n\r\nexport const emitCopilotPlugin: FormatEmitter = (connector, ctx) =>\r\n emitClaudeFamily(connector, ctx, \"copilot-plugin\");\r\n","/**\r\n * core/package-formats/shared — the common emitter contract + helpers every\r\n * format family is built on.\r\n *\r\n * A format emitter is a pure function conforming to {@link FormatEmitter}: it\r\n * takes a {@link ResolvedConnector} plus an {@link EmitContext} ({outDir,\r\n * homeBinPath, dryRun}) and either writes the bundle (dryRun=false) or only\r\n * enumerates the files it WOULD write (dryRun=true), returning a\r\n * {@link PackageResult} ({pluginDir, files[], marketplacePath?, notes?}).\r\n *\r\n * Everything below is shared across families so each emitter file is just the\r\n * format-specific manifest + layout, never a re-implementation of file writing,\r\n * JSON serialization, traversal-safe resource placement, the home-bin hooks\r\n * block, or the serve-wrapper MCP entry. Reusing these keeps telemetry-wrap +\r\n * the universal home-bin hook command byte-identical to the live adapters.\r\n */\r\n\r\nimport { dirname, relative, resolve, sep } from \"node:path\";\r\nimport { writeFileSync } from \"node:fs\";\r\n\r\nimport type {\r\n HookEventName,\r\n PlatformId,\r\n ResolvedConnector,\r\n} from \"../types.js\";\r\nimport { ensureDir, firstSymlinkInPath } from \"../paths.js\";\r\nimport {\r\n buildHomeBinHookCommand,\r\n buildServeWrapperCommand,\r\n shouldWrapForTelemetry,\r\n} from \"../spawn.js\";\r\n\r\n/** Inputs every format emitter receives. */\r\nexport interface EmitContext {\r\n /** Directory the bundle is written under (the format root). */\r\n outDir: string;\r\n /** Absolute path to agent-connector's stable home-bin (hooks + serve wrapper point here). */\r\n homeBinPath: string;\r\n /** Enumerate the file list without writing anything. */\r\n dryRun: boolean;\r\n}\r\n\r\n/** What every format emitter returns. */\r\nexport interface PackageResult {\r\n /** Absolute paths of every file the bundle comprises (written, or planned for dryRun). */\r\n files: string[];\r\n /** Absolute path to the plugin/extension root directory. */\r\n pluginDir: string;\r\n /** Absolute path to the emitted marketplace catalog, when the format has one. */\r\n marketplacePath?: string;\r\n /**\r\n * Human-readable notes about surfaces the format intentionally DROPS (e.g.\r\n * Kimi ignores hooks/commands/subagents). The CLI surfaces these so a lossy\r\n * bundle is never silent. Empty when nothing was dropped.\r\n */\r\n notes?: string[];\r\n}\r\n\r\n/** The shared signature every `package-formats/<family>.ts` exports. */\r\nexport type FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n) => PackageResult;\r\n\r\n/** A small file-collecting writer bound to one emit run (honors dryRun). */\r\nexport interface Emitter {\r\n /** Write `contents` to `path` (skipped under dryRun) and record it. */\r\n emit(path: string, contents: string): void;\r\n /** The accumulated absolute file list (in emit order). */\r\n readonly files: string[];\r\n}\r\n\r\n/** Build a dryRun-aware {@link Emitter} that records every (would-be) write. */\r\nexport function createEmitter(dryRun: boolean): Emitter {\r\n const files: string[] = [];\r\n return {\r\n files,\r\n emit(path: string, contents: string): void {\r\n if (!dryRun) {\r\n const symlink = firstSymlinkInPath(path);\r\n if (symlink !== null) {\r\n throw new Error(`refusing to emit through symbolic link: ${path} (${symlink})`);\r\n }\r\n ensureDir(dirname(path));\r\n writeFileSync(path, contents, \"utf8\");\r\n }\r\n files.push(path);\r\n },\r\n };\r\n}\r\n\r\n/** Pretty-print a value as 2-space JSON with a trailing newline. */\r\nexport function json(value: unknown): string {\r\n return `${JSON.stringify(value, null, 2)}\\n`;\r\n}\r\n\r\n/**\r\n * Resolve a skill-resource relative key against `baseDir`, returning the\r\n * absolute target ONLY when it stays inside the dir (defense-in-depth — config\r\n * validation already rejects traversal, but never trust input). Null otherwise.\r\n */\r\nexport function resolveWithin(baseDir: string, rel: string): string | null {\r\n const base = resolve(baseDir);\r\n const target = resolve(base, rel);\r\n if (target === base) return null;\r\n const rind = relative(base, target);\r\n if (rind === \"\" || rind.startsWith(\"..\") || resolve(base, rind) !== target) {\r\n return null;\r\n }\r\n if (rind === \"..\" || rind.startsWith(`..${sep}`)) return null;\r\n return target;\r\n}\r\n\r\n/** Pass env through unchanged when present, else undefined (drops empty objects). */\r\nexport function 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 { ...env };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Hooks — the Claude-shaped hooks.json block, shared by every format whose\r\n// hooks file mirrors Claude Code's `{ type:\"command\", command:\"<string>\" }`.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Claude event names a Claude-style plugin's hooks.json may key on. */\r\nexport const CLAUDE_MAPPED_EVENTS: ReadonlySet<HookEventName> =\r\n new Set<HookEventName>([\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"SessionStart\",\r\n \"SessionEnd\",\r\n \"UserPromptSubmit\",\r\n \"Stop\",\r\n \"Notification\",\r\n \"PermissionRequest\",\r\n \"PostToolUseFailure\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n \"PostCompact\",\r\n ]);\r\n\r\n/** A single hooks.json entry (identical in shape to a settings.json hooks block). */\r\nexport interface PluginHookEntry {\r\n matcher?: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/**\r\n * Build the Claude-shaped hooks.json body for the MAPPED events the connector\r\n * declares. Each command is the SAME single-string home-bin form the live\r\n * adapters write (via buildHomeBinHookCommand). `platformId` lets a format point\r\n * the hook at the right host (e.g. \"cursor\", \"claude-code\"). Returns null when\r\n * the connector declares no mapped events.\r\n */\r\nexport function buildClaudeHooksJson(\r\n connector: ResolvedConnector,\r\n homeBin: string,\r\n platformId: PlatformId,\r\n): { hooks: Record<string, PluginHookEntry[]> } | null {\r\n const events = connector.hookEvents.filter((e) => CLAUDE_MAPPED_EVENTS.has(e));\r\n if (events.length === 0) return null;\r\n\r\n const hooks: Record<string, PluginHookEntry[]> = {};\r\n for (const event of events) {\r\n const matcher = connector.hooks[event]?.matcher ?? \"\";\r\n const command = {\r\n type: \"command\" as const,\r\n command: buildHomeBinHookCommand(homeBin, platformId, event, connector.id),\r\n };\r\n hooks[event] = [matcher ? { matcher, hooks: [command] } : { hooks: [command] }];\r\n }\r\n return { hooks };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// MCP — the serve-wrapped stdio server entry, shared by every format whose MCP\r\n// file carries a launchable { command, args, env?, cwd? } (the Claude .mcp.json\r\n// dialect). Remote/non-stdio servers are out of scope for a launchable bundle.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Native MCP server entry shape a Claude-dialect mcpServers map accepts. */\r\nexport interface PluginMcpEntry {\r\n command: string;\r\n args: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\n\r\n/**\r\n * Render the connector's ServerDef into a serve-wrapped MCP entry for\r\n * `platformId`, so per-tool telemetry carries through the bundle exactly as the\r\n * live adapter's install does. Returns null when there is no stdio command to\r\n * launch (remote / server-less connectors). The returned `serverName` is the\r\n * connector id (the conventional single-server key).\r\n */\r\nexport function buildMcpEntry(\r\n connector: ResolvedConnector,\r\n homeBin: string,\r\n platformId: PlatformId,\r\n): { serverName: string; entry: PluginMcpEntry } | null {\r\n const server = connector.server;\r\n if (!server) return null;\r\n // A launchable bundle entry can only carry stdio servers; remote (http/sse/ws)\r\n // servers register a URL elsewhere, out of scope for the bundled plugin.\r\n if (server.transport !== \"stdio\") return null;\r\n\r\n const realCommand = server.command ?? \"\";\r\n if (realCommand === \"\") return null;\r\n const realArgs = [...(server.args ?? [])];\r\n\r\n let entry: PluginMcpEntry;\r\n if (shouldWrapForTelemetry(server, connector.telemetry)) {\r\n const wrapped = buildServeWrapperCommand(\r\n homeBin,\r\n connector.id,\r\n realCommand,\r\n realArgs,\r\n undefined,\r\n platformId,\r\n );\r\n entry = { command: wrapped.command, args: wrapped.args };\r\n } else {\r\n entry = { command: realCommand, args: realArgs };\r\n }\r\n\r\n const env = renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = server.cwd;\r\n\r\n return { serverName: connector.id, entry };\r\n}\r\n","/**\r\n * core/package-formats/cursor — the `cursor-plugin` emitter.\r\n *\r\n * Cursor's bundle is near-isomorphic to claude-plugin: manifest at\r\n * `.cursor-plugin/plugin.json` (only `name` required) with the surface fields\r\n * declared as POINTERS (\"skills\":\"./skills/\", \"hooks\":\"./hooks/hooks.json\",\r\n * \"mcpServers\":\"./mcp.json\") so a validator/IDE finds each dir; components live\r\n * at the plugin root: commands/<n>.md, agents/<n>.md, skills/<n>/SKILL.md,\r\n * mcp.json, hooks/hooks.json. A multi-plugin repo adds .cursor-plugin/\r\n * marketplace.json { name, owner:{name,email?}, plugins:[{name,source,description}] }.\r\n *\r\n * Markdown reuses the shared claude-code renderers (Cursor reads the same md +\r\n * frontmatter command/agent/skill documents). MCP uses the shared serve-wrap\r\n * builder with --host cursor so serve-wrapper telemetry carries through. Hooks\r\n * use Cursor's OWN flat hooks.json shape (NOT the Claude shape) via the cursor\r\n * install adapter's shared event-map + version — see buildCursorHooksJson.\r\n *\r\n * (Cursor also supports `rules/*.mdc`, but a connector declares no rules surface,\r\n * so no rules/ dir is emitted and the manifest omits the `rules` pointer.)\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nimport type { HookEventName, PlatformId, ResolvedConnector } from \"../types.js\";\r\nimport {\r\n renderCommandMd,\r\n renderSkillMd,\r\n renderSubagentMd,\r\n} from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n CURSOR_EVENT_MAP,\r\n CURSOR_HOOKS_VERSION,\r\n} from \"../../adapters/cursor/index.js\";\r\nimport { buildHomeBinHookCommand } from \"../spawn.js\";\r\nimport {\r\n buildMcpEntry,\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\nconst PLATFORM: PlatformId = \"cursor\";\r\n\r\n/** A single Cursor native hook entry — a FLAT command object (matcher optional). */\r\ninterface CursorHookEntry {\r\n command: string;\r\n matcher?: string;\r\n}\r\n\r\n/**\r\n * Build Cursor's native hooks.json body for the connector's declared events.\r\n *\r\n * Unlike the Claude shape (PascalCase keys, nested `{ matcher?, hooks:[{type,\r\n * command}] }`, no version), Cursor reads `{ version, hooks: { <cursorEvent>:\r\n * [ { command, matcher? } ] } }` — lower-camel native keys, FLAT command\r\n * entries, and a top-level version stamp. The event-map + version are imported\r\n * from the cursor INSTALL adapter (the repo authority on Cursor's schema) so a\r\n * packaged bundle and a live install can never diverge: only the events Cursor\r\n * actually maps are emitted, with the exact keys/version the adapter writes.\r\n *\r\n * The home-bin command STRING is the same single-string form the install\r\n * adapter writes (buildHomeBinHookCommand); only the envelope shape differs.\r\n *\r\n * Scope: this operates on the connector-level declared `hookEvents` only. Per-\r\n * platform override state (`platforms.cursor.hooks: false` / `nativeHooks`) is\r\n * intentionally NOT applied — a portable package bundle is platform-agnostic,\r\n * matching the Claude-family emitters. The consistency test covers the no-\r\n * override case (bundle bytes === a vanilla install).\r\n * Returns null when the connector declares no Cursor-mapped events.\r\n */\r\nfunction buildCursorHooksJson(\r\n connector: ResolvedConnector,\r\n homeBin: string,\r\n): { version: number; hooks: Record<string, CursorHookEntry[]> } | null {\r\n const hooks: Record<string, CursorHookEntry[]> = {};\r\n for (const event of connector.hookEvents) {\r\n const cursorEvent = CURSOR_EVENT_MAP[event as HookEventName];\r\n if (cursorEvent === undefined) continue; // no Cursor equivalent — skipped\r\n const command = buildHomeBinHookCommand(homeBin, PLATFORM, event, connector.id);\r\n const matcher = connector.hooks[event]?.matcher ?? \"\";\r\n hooks[cursorEvent] = [matcher ? { command, matcher } : { command }];\r\n }\r\n if (Object.keys(hooks).length === 0) return null;\r\n return { version: CURSOR_HOOKS_VERSION, hooks };\r\n}\r\n\r\n/** Build .cursor-plugin/plugin.json with pointer surface fields for what exists. */\r\nfunction buildManifest(\r\n connector: ResolvedConnector,\r\n has: { commands: boolean; agents: boolean; skills: boolean; hooks: boolean; mcp: boolean },\r\n): Record<string, unknown> {\r\n const manifest: Record<string, unknown> = {\r\n name: connector.id,\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n };\r\n if (connector.version && connector.version !== \"0.0.0\") {\r\n manifest.version = connector.version;\r\n }\r\n // Pointer fields: only declare a surface that actually ships in the bundle.\r\n if (has.commands) manifest.commands = \"./commands/\";\r\n if (has.agents) manifest.agents = \"./agents/\";\r\n if (has.skills) manifest.skills = \"./skills/\";\r\n if (has.hooks) manifest.hooks = \"./hooks/hooks.json\";\r\n if (has.mcp) manifest.mcpServers = \"./mcp.json\";\r\n return manifest;\r\n}\r\n\r\n/** Build .cursor-plugin/marketplace.json (owner object carries name; email optional). */\r\nfunction buildMarketplace(connector: ResolvedConnector): Record<string, unknown> {\r\n // Catalog NAME stays \"agent-connector\" (install instructions key on it); the\r\n // OWNER is the connector developer when publish.author is declared.\r\n return {\r\n name: \"agent-connector\",\r\n owner: { name: connector.publish?.author?.name ?? \"agent-connector\" },\r\n plugins: [\r\n {\r\n name: connector.id,\r\n source: `./${connector.id}`,\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n },\r\n ],\r\n };\r\n}\r\n\r\nexport const emitCursorPlugin: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n\r\n const hooksJson = buildCursorHooksJson(connector, ctx.homeBinPath);\r\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, PLATFORM);\r\n\r\n const has = {\r\n commands: connector.commands.length > 0,\r\n agents: connector.subagents.length > 0,\r\n skills: connector.skills.length > 0,\r\n hooks: hooksJson !== null,\r\n mcp: mcp !== null,\r\n };\r\n\r\n // ── .cursor-plugin/plugin.json (ONLY file under .cursor-plugin/) ───────────\r\n emit(\r\n join(pluginDir, \".cursor-plugin\", \"plugin.json\"),\r\n json(buildManifest(connector, has)),\r\n );\r\n\r\n // ── commands/<name>.md ────────────────────────────────────────────────────\r\n for (const cmd of connector.commands) {\r\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\r\n }\r\n\r\n // ── agents/<name>.md ──────────────────────────────────────────────────────\r\n for (const agent of connector.subagents) {\r\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\r\n }\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue;\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── hooks/hooks.json ──────────────────────────────────────────────────────\r\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\r\n\r\n // ── mcp.json (Cursor's MCP filename, no leading dot) ──────────────────────\r\n if (mcp) {\r\n emit(\r\n join(pluginDir, \"mcp.json\"),\r\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\r\n );\r\n }\r\n\r\n // ── .cursor-plugin/marketplace.json ───────────────────────────────────────\r\n const marketplacePath = join(ctx.outDir, \".cursor-plugin\", \"marketplace.json\");\r\n emit(marketplacePath, json(buildMarketplace(connector)));\r\n\r\n return { files, pluginDir, marketplacePath };\r\n};\r\n\r\n/** True when a local install of this plugin already exists (used by the CLI hint). */\r\nexport function cursorLocalInstallExists(name: string, home: string): boolean {\r\n return existsSync(join(home, \".cursor\", \"plugins\", \"local\", name));\r\n}\r\n","/**\r\n * core/package-formats/gemini — the `gemini-extension` emitter + its `qwen-extension`\r\n * variant.\r\n *\r\n * A Gemini CLI extension is a directory with `gemini-extension.json` at its root\r\n * carrying `{ name, version, description, mcpServers, contextFileName }` plus the\r\n * component dirs: commands/<n>.toml (slash commands), skills/<n>/SKILL.md,\r\n * agents/<n>.md, hooks/hooks.json, and a GEMINI.md context file. UNLIKE the\r\n * Claude family, MCP is declared INLINE in the manifest's `mcpServers` map (not a\r\n * separate .mcp.json) — we still serve-wrap it so telemetry carries through.\r\n *\r\n * Qwen Code is a Gemini-CLI fork with its own `qwen-extension.json` (same shape)\r\n * but two differences captured here: commands are MARKDOWN (commands/<n>.md) not\r\n * TOML, and the context file is QWEN.md.\r\n *\r\n * Commands render to Gemini's native TOML `{ description, prompt }` (the same\r\n * shape the live gemini-cli adapter writes); skills/subagents reuse the shared\r\n * claude-code renderers (Gemini/Qwen read the same SKILL.md + md+frontmatter).\r\n * Hooks use the universal home-bin command; the MCP entry is serve-wrapped with\r\n * --host gemini-cli | qwen-code.\r\n */\r\n\r\nimport { join } from \"node:path\";\r\n\r\nimport type { CommandDef, PlatformId, ResolvedConnector } from \"../types.js\";\r\nimport { writeTomlString } from \"../toml.js\";\r\nimport {\r\n renderCommandMd,\r\n renderSkillMd,\r\n renderSubagentMd,\r\n} from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n buildClaudeHooksJson,\r\n buildMcpEntry,\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\n/** Per-variant knobs for a Gemini-family extension. */\r\ninterface GeminiFamilySpec {\r\n platformId: PlatformId;\r\n /** Manifest filename at the extension root. */\r\n manifestFile: string;\r\n /** Context file name (GEMINI.md | QWEN.md). */\r\n contextFile: string;\r\n /** Command file format: TOML (gemini) or Markdown (qwen). */\r\n commandFormat: \"toml\" | \"md\";\r\n}\r\n\r\nconst SPECS: Record<string, GeminiFamilySpec> = {\r\n \"gemini-extension\": {\r\n platformId: \"gemini-cli\",\r\n manifestFile: \"gemini-extension.json\",\r\n contextFile: \"GEMINI.md\",\r\n commandFormat: \"toml\",\r\n },\r\n \"qwen-extension\": {\r\n platformId: \"qwen-code\",\r\n manifestFile: \"qwen-extension.json\",\r\n contextFile: \"QWEN.md\",\r\n commandFormat: \"md\",\r\n },\r\n};\r\n\r\n/** Render a command to Gemini's native TOML `{ description, prompt }`. */\r\nfunction renderCommandToml(cmd: CommandDef): string {\r\n const obj: Record<string, unknown> = {};\r\n if (cmd.description !== undefined) obj.description = cmd.description;\r\n obj.prompt = cmd.prompt;\r\n return writeTomlString(obj);\r\n}\r\n\r\n/** Build gemini-extension.json | qwen-extension.json (with optional inline mcpServers). */\r\nfunction buildManifest(\r\n connector: ResolvedConnector,\r\n spec: GeminiFamilySpec,\r\n homeBin: string,\r\n): Record<string, unknown> {\r\n const manifest: Record<string, unknown> = {\r\n name: connector.id,\r\n // gemini requires a version; default a placeholder to a real semver.\r\n version:\r\n connector.version && connector.version !== \"0.0.0\"\r\n ? connector.version\r\n : \"0.0.1\",\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n };\r\n\r\n const mcp = buildMcpEntry(connector, homeBin, spec.platformId);\r\n if (mcp) {\r\n manifest.mcpServers = { [mcp.serverName]: mcp.entry };\r\n }\r\n manifest.contextFileName = spec.contextFile;\r\n return manifest;\r\n}\r\n\r\nfunction emitGeminiFamily(\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n format: keyof typeof SPECS,\r\n): PackageResult {\r\n const spec = SPECS[format];\r\n if (!spec) throw new Error(`unknown gemini-family format: ${format}`);\r\n\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n\r\n // ── gemini-extension.json | qwen-extension.json (MCP is inline here) ──────\r\n emit(\r\n join(pluginDir, spec.manifestFile),\r\n json(buildManifest(connector, spec, ctx.homeBinPath)),\r\n );\r\n\r\n // ── context file (GEMINI.md | QWEN.md) ────────────────────────────────────\r\n emit(\r\n join(pluginDir, spec.contextFile),\r\n `# ${connector.displayName}\\n\\nConnector context emitted by agent-connector.\\n`,\r\n );\r\n\r\n // ── commands/<name>.{toml|md} ─────────────────────────────────────────────\r\n for (const cmd of connector.commands) {\r\n if (spec.commandFormat === \"toml\") {\r\n emit(join(pluginDir, \"commands\", `${cmd.name}.toml`), renderCommandToml(cmd));\r\n } else {\r\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\r\n }\r\n }\r\n\r\n // ── agents/<name>.md ──────────────────────────────────────────────────────\r\n for (const agent of connector.subagents) {\r\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\r\n }\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue;\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── hooks/hooks.json ──────────────────────────────────────────────────────\r\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, spec.platformId);\r\n if (hooksJson) emit(join(pluginDir, \"hooks\", \"hooks.json\"), json(hooksJson));\r\n\r\n // A Gemini/Qwen extension has no separate marketplace catalog (it installs by\r\n // URL/path); marketplacePath is left undefined.\r\n return { files, pluginDir };\r\n}\r\n\r\nexport const emitGeminiExtension: FormatEmitter = (connector, ctx) =>\r\n emitGeminiFamily(connector, ctx, \"gemini-extension\");\r\n\r\nexport const emitQwenExtension: FormatEmitter = (connector, ctx) =>\r\n emitGeminiFamily(connector, ctx, \"qwen-extension\");\r\n","/**\r\n * core/package-formats/agy — the `agy plugin` bundle emitter (Antigravity CLI +\r\n * Antigravity IDE, which share the bundle).\r\n *\r\n * Live-confirmed layout (`agy plugin validate`):\r\n * • REQUIRED root `plugin.json` marker { name, version, description } — its\r\n * absence is the one hard error the validator reports.\r\n * • MCP MUST be a SEPARATE `mcp_config.json` { mcpServers:{...} } — an inline\r\n * `mcpServers` in plugin.json is NOT picked up. (This is the one structural\r\n * difference from the Claude family.)\r\n * • hooks.json at the BUNDLE ROOT keyed { hooks:{ <Event>:[{matcher,hooks:[{type,command}]}] } }\r\n * — agy 1.0.7 NEVER reads hooks/hooks.json: validate+install report\r\n * \"hooks: skipped (not found)\" and copy the file unprocessed. The root\r\n * location was fix-proven live (\"hooks: 1 processed\", components +hooks).\r\n * • skills/<n>/SKILL.md, agents/<n>.md, commands/<n>.md (commands are converted\r\n * to skills on validate — still emitted as Markdown command files).\r\n *\r\n * Markdown reuses the shared claude-code renderers; hooks use the universal\r\n * home-bin command; the MCP entry is serve-wrapped with --host antigravity-cli so\r\n * telemetry carries through. No marketplace catalog ships in the bundle (agy\r\n * installs by target / plugin@marketplace).\r\n */\r\n\r\nimport { join } from \"node:path\";\r\n\r\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\r\nimport {\r\n renderCommandMd,\r\n renderSkillMd,\r\n renderSubagentMd,\r\n} from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n buildClaudeHooksJson,\r\n buildMcpEntry,\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\nconst PLATFORM: PlatformId = \"antigravity-cli\";\r\n\r\n/** Build the required root plugin.json marker. */\r\nfunction buildManifest(connector: ResolvedConnector): Record<string, unknown> {\r\n return {\r\n name: connector.id,\r\n // agy expects a version on the marker; default a placeholder to a real semver.\r\n version:\r\n connector.version && connector.version !== \"0.0.0\"\r\n ? connector.version\r\n : \"0.0.1\",\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n };\r\n}\r\n\r\nexport const emitAgyPlugin: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n\r\n // ── plugin.json (REQUIRED root marker) ────────────────────────────────────\r\n emit(join(pluginDir, \"plugin.json\"), json(buildManifest(connector)));\r\n\r\n // ── commands/<name>.md (validator converts these to skills) ───────────────\r\n for (const cmd of connector.commands) {\r\n emit(join(pluginDir, \"commands\", `${cmd.name}.md`), renderCommandMd(cmd));\r\n }\r\n\r\n // ── agents/<name>.md ──────────────────────────────────────────────────────\r\n for (const agent of connector.subagents) {\r\n emit(join(pluginDir, \"agents\", `${agent.name}.md`), renderSubagentMd(agent));\r\n }\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue;\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── hooks.json (bundle ROOT — agy silently ignores hooks/hooks.json) ──────\r\n const hooksJson = buildClaudeHooksJson(connector, ctx.homeBinPath, PLATFORM);\r\n if (hooksJson) emit(join(pluginDir, \"hooks.json\"), json(hooksJson));\r\n\r\n // ── mcp_config.json (SEPARATE file — inline mcpServers is NOT read by agy) ─\r\n const mcp = buildMcpEntry(connector, ctx.homeBinPath, PLATFORM);\r\n if (mcp) {\r\n emit(\r\n join(pluginDir, \"mcp_config.json\"),\r\n json({ mcpServers: { [mcp.serverName]: mcp.entry } }),\r\n );\r\n }\r\n\r\n return { files, pluginDir };\r\n};\r\n","/**\r\n * core/package-formats/kimi — the `kimi-plugin` emitter (skills + MCP ONLY).\r\n *\r\n * A Kimi plugin is a directory whose manifest is `kimi.plugin.json` at the root\r\n * carrying { name, version, description, skills, mcpServers }. Kimi plugins carry\r\n * exactly TWO functional surfaces:\r\n * • skills/<n>/SKILL.md (declared via the `skills` pointer)\r\n * • mcpServers (a standard MCP map, stdio + http)\r\n *\r\n * Kimi EXPLICITLY ignores `tools`, `commands`, `hooks`, `apps`, `inject`,\r\n * `configFile` (they surface as diagnostics). So when the connector declares\r\n * commands, subagents, or hooks, those surfaces are DROPPED — and a note is\r\n * returned so the lossy bundle is never silent. The MCP entry is still\r\n * serve-wrapped with --host kimi so telemetry carries through; hooks are NOT\r\n * emitted because Kimi has no hooks surface.\r\n */\r\n\r\nimport { join } from \"node:path\";\r\n\r\nimport type { PlatformId, ResolvedConnector } from \"../types.js\";\r\nimport { renderSkillMd } from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n buildMcpEntry,\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\nconst PLATFORM: PlatformId = \"kimi\";\r\n\r\n/** Build kimi.plugin.json (skills pointer + inline mcpServers when present). */\r\nfunction buildManifest(\r\n connector: ResolvedConnector,\r\n hasSkills: boolean,\r\n homeBin: string,\r\n): Record<string, unknown> {\r\n const manifest: Record<string, unknown> = {\r\n name: connector.id,\r\n version:\r\n connector.version && connector.version !== \"0.0.0\"\r\n ? connector.version\r\n : \"0.0.1\",\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n };\r\n if (hasSkills) manifest.skills = \"./skills/\";\r\n const mcp = buildMcpEntry(connector, homeBin, PLATFORM);\r\n if (mcp) manifest.mcpServers = { [mcp.serverName]: mcp.entry };\r\n return manifest;\r\n}\r\n\r\nexport const emitKimiPlugin: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n const notes: string[] = [];\r\n\r\n const hasSkills = connector.skills.length > 0;\r\n\r\n // ── kimi.plugin.json (root manifest; MCP inline; hooks/commands ignored) ──\r\n emit(join(pluginDir, \"kimi.plugin.json\"), json(buildManifest(connector, hasSkills, ctx.homeBinPath)));\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) ──────────────────────────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue;\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── Surfaces Kimi cannot carry → DROPPED, with an explicit note ───────────\r\n if (connector.commands.length > 0) {\r\n notes.push(\r\n `kimi-plugin: dropped ${connector.commands.length} command(s) — Kimi plugins ignore commands`,\r\n );\r\n }\r\n if (connector.subagents.length > 0) {\r\n notes.push(\r\n `kimi-plugin: dropped ${connector.subagents.length} subagent(s) — Kimi plugins ignore subagents`,\r\n );\r\n }\r\n if (connector.hookEvents.length > 0) {\r\n notes.push(\r\n `kimi-plugin: dropped ${connector.hookEvents.length} hook event(s) — Kimi plugins ignore hooks`,\r\n );\r\n }\r\n\r\n return { files, pluginDir, ...(notes.length > 0 ? { notes } : {}) };\r\n};\r\n","/**\r\n * core/package-formats/npm — the `npm-plugin` emitter (opencode + kilo-cli + pi).\r\n *\r\n * This is the one genuinely NET-NEW artifact: a publishable npm package whose\r\n * default export is a plugin module. It is emitted ONLY in its clean form — a\r\n * real package.json + an ESM `index.js` bridge — never a\r\n * half-baked stub. The surface limit (documented, and returned as notes) is\r\n * inherent to the opencode/kilo plugin contract: ONLY hook code rides inside the\r\n * npm package; commands/skills/subagents are native host dirs and MCP is a\r\n * config key, so they do NOT ride inside the published module.\r\n *\r\n * Layout:\r\n * <outDir>/<id>/\r\n * ├── package.json (type:module, exports \".\", keywords incl. \"opencode-plugin\"\r\n * │ + \"pi-package\", engines.node)\r\n * ├── index.js (default-export plugin fn; bridges each declared hook event\r\n * │ to `<homeBin> hook opencode <event> --connector <id>`)\r\n * ├── skills/<n>/SKILL.md (pi packages DO bundle skills; opencode ignores them)\r\n * └── README.md\r\n *\r\n * The bridge shells out to the framework runtime bundled as this plugin's npm\r\n * dependency, then falls back to a PATH `agent-connector` binary for hand-built\r\n * bundles. The SAME universal json-stdio dispatcher every other host uses serves\r\n * the npm host too. (MCP wrapping is NOT inlined here: opencode's MCP is the\r\n * opencode.json \"mcp\" key, out of band for the npm package; a note records this.)\r\n */\r\n\r\nimport { createRequire } from \"node:module\";\r\nimport { join } from \"node:path\";\r\n\r\nimport type { HookEventName, ResolvedConnector } from \"../types.js\";\r\nimport { renderSkillMd } from \"../../adapters/claude-code/render.js\";\r\nimport {\r\n createEmitter,\r\n json,\r\n resolveWithin,\r\n type EmitContext,\r\n type FormatEmitter,\r\n type PackageResult,\r\n} from \"./shared.js\";\r\n\r\nconst AGENT_CONNECTOR_PACKAGE_NAME = \"@ken-jo/agent-connector\";\r\n\r\n/** OpenCode event keys this connector can bridge (PreToolUse/PostToolUse/SessionStart). */\r\nconst EVENT_TO_OPENCODE: Partial<Record<HookEventName, string>> = {\r\n PreToolUse: \"tool.execute.before\",\r\n PostToolUse: \"tool.execute.after\",\r\n SessionStart: \"experimental.chat.system.transform\",\r\n};\r\n\r\nfunction resolveFrameworkDependencyRange(): string {\r\n const req = createRequire(import.meta.url);\r\n for (const rel of [\"../../../package.json\", \"../../package.json\", \"../package.json\"]) {\r\n try {\r\n const pkg = req(rel) as { name?: string; version?: string };\r\n if (\r\n pkg.name === AGENT_CONNECTOR_PACKAGE_NAME &&\r\n typeof pkg.version === \"string\" &&\r\n /^\\d+\\.\\d+\\.\\d+/.test(pkg.version)\r\n ) {\r\n return `^${pkg.version}`;\r\n }\r\n } catch {\r\n /* keep walking */\r\n }\r\n }\r\n return \"*\";\r\n}\r\n\r\n/** Build the publishable package.json for an opencode/kilo/pi plugin package. */\r\nfunction buildPackageJson(connector: ResolvedConnector): Record<string, unknown> {\r\n // Use an opencode- name prefix (the discovery-confirmed convention) so the\r\n // package is discoverable; keywords cover opencode + pi-package.\r\n const pkgName = connector.id.startsWith(\"opencode-\")\r\n ? connector.id\r\n : `opencode-${connector.id}`;\r\n const version =\r\n connector.version && connector.version !== \"0.0.0\" ? connector.version : \"0.0.1\";\r\n const pkg: Record<string, unknown> = {\r\n name: pkgName,\r\n version,\r\n description: `${connector.displayName} — connector emitted by agent-connector`,\r\n type: \"module\",\r\n main: \"index.js\",\r\n exports: { \".\": \"./index.js\" },\r\n keywords: [\"opencode\", \"opencode-plugin\", \"pi-package\", \"agent-connector\"],\r\n dependencies: { [AGENT_CONNECTOR_PACKAGE_NAME]: resolveFrameworkDependencyRange() },\r\n // pi reads skills/prompts/themes/extensions from the package.json \"pi\" key.\r\n pi: { extensions: [\"./index.js\"], skills: [\"./skills\"] },\r\n engines: { node: \">=18.17\", opencode: \">=1.0.0\" },\r\n // NOTE: no hardcoded license — this is the DEVELOPER'S publishable package\r\n // and agent-connector has no authority to license it. The emitter returns a\r\n // note telling the dev to set license (and author) before `npm publish`.\r\n };\r\n if (connector.publish?.author?.name) {\r\n pkg.author = connector.publish.author.name;\r\n }\r\n return pkg;\r\n}\r\n\r\n/** Compose the self-contained ESM plugin bridge (default-export plugin fn). */\r\nfunction buildIndexJs(connector: ResolvedConnector): string {\r\n const frameworkPackageName = JSON.stringify(AGENT_CONNECTOR_PACKAGE_NAME);\r\n const connectorId = JSON.stringify(connector.id);\r\n\r\n const events = connector.hookEvents.filter(\r\n (e): e is HookEventName => EVENT_TO_OPENCODE[e] !== undefined,\r\n );\r\n const has = (e: HookEventName): boolean => events.includes(e);\r\n\r\n const header = `/**\r\n * AUTO-GENERATED by agent-connector — DO NOT EDIT.\r\n *\r\n * Publishable OpenCode/Kilo/Pi plugin for connector ${connector.id}. It imports\r\n * no public framework APIs: every hook invocation shells out to the bundled\r\n * framework runtime's universal entrypoint and JSON-parses the normalized response.\r\n * Fail-open: any bridge error degrades to \"allow\".\r\n */\r\nimport { execFileSync, execSync } from \"node:child_process\";\r\nimport { createRequire } from \"node:module\";\r\nimport { dirname, join } from \"node:path\";\r\n\r\nconst FRAMEWORK_PACKAGE_NAME = ${frameworkPackageName};\r\nconst CONNECTOR_ID = ${connectorId};\r\nconst require = createRequire(import.meta.url);\r\n\r\nfunction resolveBridgeCommand() {\r\n try {\r\n const pkgJson = require.resolve(FRAMEWORK_PACKAGE_NAME + \"/package.json\");\r\n return { command: process.execPath, prefix: [join(dirname(pkgJson), \"dist\", \"cli.js\")] };\r\n } catch {\r\n return { command: \"agent-connector\", prefix: [] };\r\n }\r\n}\r\n\r\nconst BRIDGE_COMMAND = resolveBridgeCommand();\r\n\r\nfunction bridge(event, payload) {\r\n try {\r\n // Prefer the runtime bundled as this plugin's dependency. The bare\r\n // agent-connector command is only a recovery fallback for hand-built bundles.\r\n const args = [...BRIDGE_COMMAND.prefix, \"hook\", \"opencode\", event, \"--connector\", CONNECTOR_ID];\r\n const opts = { input: JSON.stringify(payload), encoding: \"utf8\" };\r\n const stdout =\r\n process.platform === \"win32\" && BRIDGE_COMMAND.command === \"agent-connector\"\r\n ? execSync([BRIDGE_COMMAND.command, ...args].map((a) => '\"' + a + '\"').join(\" \"), opts)\r\n : execFileSync(BRIDGE_COMMAND.command, args, opts);\r\n const text = (stdout || \"\").trim();\r\n if (text === \"\") return { decision: \"allow\" };\r\n return JSON.parse(text);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n`;\r\n\r\n const handlers: string[] = [];\r\n if (has(\"PreToolUse\")) {\r\n handlers.push(` \"tool.execute.before\": async (input, output) => {\r\n const res = bridge(\"PreToolUse\", {\r\n toolName: input.tool ?? \"\",\r\n toolInput: (output && output.args) ?? {},\r\n sessionId: input.sessionID ?? \"\",\r\n projectDir: PROJECT_DIR,\r\n });\r\n if (!res) return;\r\n if (res.decision === \"deny\" || res.decision === \"ask\") {\r\n throw new Error(res.reason || \"Blocked by ${connector.id}\");\r\n }\r\n if (res.updatedInput && output && output.args) Object.assign(output.args, res.updatedInput);\r\n },`);\r\n }\r\n if (has(\"PostToolUse\")) {\r\n handlers.push(` \"tool.execute.after\": async (input, output) => {\r\n const res = bridge(\"PostToolUse\", {\r\n toolName: input.tool ?? \"\",\r\n toolInput: input.args ?? {},\r\n toolOutput: output ? output.output : undefined,\r\n sessionId: input.sessionID ?? \"\",\r\n projectDir: PROJECT_DIR,\r\n });\r\n if (!res) return;\r\n if (typeof res.updatedOutput === \"string\" && output) output.output = res.updatedOutput;\r\n },`);\r\n }\r\n if (has(\"SessionStart\")) {\r\n handlers.push(` \"experimental.chat.system.transform\": async (input, output) => {\r\n const res = bridge(\"SessionStart\", {\r\n sessionId: (input && input.sessionID) ?? \"\",\r\n projectDir: PROJECT_DIR,\r\n });\r\n if (!res) return;\r\n if (res.additionalContext && output && Array.isArray(output.system)) {\r\n output.system.splice(1, 0, res.additionalContext);\r\n }\r\n },`);\r\n }\r\n\r\n const factory = `\r\nexport default async function (ctx) {\r\n const PROJECT_DIR =\r\n (ctx && (ctx.directory || (ctx.worktree && ctx.worktree.path))) || process.cwd();\r\n return {\r\n${handlers.join(\"\\n\")}\r\n };\r\n}\r\n`;\r\n return header + factory;\r\n}\r\n\r\nexport const emitNpmPlugin: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const { emit, files } = createEmitter(ctx.dryRun);\r\n const pluginDir = join(ctx.outDir, connector.id);\r\n const notes: string[] = [];\r\n\r\n // ── package.json (publishable) ────────────────────────────────────────────\r\n emit(join(pluginDir, \"package.json\"), json(buildPackageJson(connector)));\r\n\r\n // ── index.js (the default-export plugin bridge) ───────────────────────────\r\n emit(join(pluginDir, \"index.js\"), buildIndexJs(connector));\r\n\r\n // ── skills/<name>/SKILL.md (+ resources) — pi bundles skills ──────────────\r\n for (const skill of connector.skills) {\r\n const skillDir = join(pluginDir, \"skills\", skill.name);\r\n emit(join(skillDir, \"SKILL.md\"), renderSkillMd(skill));\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = resolveWithin(skillDir, rel);\r\n if (target === null) continue;\r\n emit(target, contents);\r\n }\r\n }\r\n\r\n // ── README.md ─────────────────────────────────────────────────────────────\r\n emit(\r\n join(pluginDir, \"README.md\"),\r\n `# ${connector.displayName}\\n\\nOpenCode / Kilo / Pi plugin package emitted by agent-connector.\\n\\n` +\r\n \"Install with `opencode plugin install <pkg>` / `kilo plugin <pkg>` / `pi install <pkg>`.\\n\\n\" +\r\n \"Local install (no npm publish needed — live-verified on opencode 1.17.0 / kilo 7.3.16):\\n\" +\r\n \"`opencode plugin --global file:///<abs-dir>` or `kilo plugin --global file:///<abs-dir>`\\n\" +\r\n \"(bare absolute paths work too; the entry lands in the config `plugin` array —\\n\" +\r\n \"there is no uninstall verb, remove it by editing that array).\\n\\n\" +\r\n \"## Prerequisite\\n\\n\" +\r\n \"The generated package depends on `@ken-jo/agent-connector` and hooks resolve that\\n\" +\r\n \"local runtime first. A global `agent-connector` binary is only a recovery fallback\\n\" +\r\n \"for hand-built bundles; hooks silently no-op, fail-open, if neither runtime exists.\\n\\n\" +\r\n \"## Before you publish\\n\\n\" +\r\n \"The emitted package.json carries **no `license` and no `author`** unless your\\n\" +\r\n \"connector declared `publish.author` — set them to YOUR terms before `npm publish`.\\n\",\r\n );\r\n\r\n notes.push(\r\n \"npm-plugin: hooks resolve the bundled @ken-jo/agent-connector dependency first; a global agent-connector binary is only a recovery fallback, and hooks silently fail-open without either runtime\",\r\n );\r\n notes.push(\r\n \"npm-plugin: set license/author in the emitted package.json before `npm publish` — agent-connector does not license your plugin for you\",\r\n );\r\n\r\n // Surface the inherent limits of the npm-plugin contract.\r\n if (connector.commands.length > 0) {\r\n notes.push(\r\n `npm-plugin: ${connector.commands.length} command(s) NOT bundled — opencode/kilo commands are native host dirs`,\r\n );\r\n }\r\n if (connector.subagents.length > 0) {\r\n notes.push(\r\n `npm-plugin: ${connector.subagents.length} subagent(s) NOT bundled — opencode/kilo subagents are native host dirs`,\r\n );\r\n }\r\n if (connector.server) {\r\n notes.push(\r\n `npm-plugin: MCP server NOT bundled inside the package — register it via the opencode.json \"mcp\" key`,\r\n );\r\n }\r\n\r\n return { files, pluginDir, ...(notes.length > 0 ? { notes } : {}) };\r\n};\r\n","/**\r\n * core/package-formats/mcp-server — emit an official MCP Registry `server.json`.\r\n *\r\n * Unlike the host plugin/marketplace bundles, server.json is a DISCOVERY +\r\n * PUBLISH artifact: it describes the developer's REAL upstream MCP server (what\r\n * a registry installer runs DIRECTLY), so it must NOT carry agent-connector's\r\n * `serve` telemetry wrapper. It is emitted from the connector's `publish`\r\n * metadata (the namespace the dev proved ownership of + their published package)\r\n * and conforms to the pinned 2025-12-11 schema:\r\n * • name = `${publish.registryNamespace}/${connector.id}` (one '/', regex-checked)\r\n * • version = concrete SemVer (ranges are rejected by the registry)\r\n * • stdio → packages[] { registryType:\"npm\", identifier:<dev pkg>, transport:{type:\"stdio\"} }\r\n * • remote → remotes[] { type:\"streamable-http\"|\"sse\", url, headers }\r\n * • token env vars are marked isSecret.\r\n *\r\n * agent-connector EMITS a conformant server.json; the dev runs the publish-time\r\n * ownership proof + upload themselves with the official `mcp-publisher` CLI.\r\n */\r\n\r\nimport { resolve } from \"node:path\";\r\n\r\nimport type { ResolvedConnector, ServerDef } from \"../types.js\";\r\nimport {\r\n MCP_SERVER_SCHEMA_URL,\r\n NPM_REGISTRY_BASE_URL,\r\n REGISTRY_NAME_RE,\r\n isConcreteSemver,\r\n isPlaceholderVersion,\r\n registryTransportType,\r\n} from \"../mcp-standard.js\";\r\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./shared.js\";\r\nimport { createEmitter, json } from \"./shared.js\";\r\n\r\n/** A server.json KeyValueInput (environmentVariables[] / headers[] entry). */\r\ninterface KeyValueInput {\r\n name: string;\r\n isSecret?: boolean;\r\n isRequired?: boolean;\r\n}\r\n\r\n/** Build environmentVariables[] from a stdio ServerDef, marking the bearer token secret. */\r\nfunction buildEnvVars(server: ServerDef): KeyValueInput[] {\r\n const vars: KeyValueInput[] = [];\r\n const byName = new Map<string, KeyValueInput>();\r\n for (const key of Object.keys(server.env ?? {})) {\r\n const v: KeyValueInput = { name: key };\r\n vars.push(v);\r\n byName.set(key, v);\r\n }\r\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\r\n const name = server.auth.bearerEnvVar;\r\n const existing = byName.get(name);\r\n if (existing) {\r\n existing.isSecret = true;\r\n existing.isRequired = true;\r\n } else {\r\n vars.push({ name, isSecret: true, isRequired: true });\r\n }\r\n }\r\n return vars;\r\n}\r\n\r\n/** Build the conformant server.json object (throws a clear error on missing inputs). */\r\nfunction buildServerJson(\r\n connector: ResolvedConnector,\r\n notes: string[],\r\n): Record<string, unknown> {\r\n const publish = connector.publish ?? {};\r\n\r\n if (!publish.registryNamespace) {\r\n throw new Error(\r\n 'package --format mcp-server-json needs publish.registryNamespace — a reverse-DNS ' +\r\n 'namespace you OWN (e.g. \"io.github.<your-handle>\" or \"com.<your-domain>\"). ' +\r\n \"agent-connector never publishes under a namespace it owns; set it in your connector config.\",\r\n );\r\n }\r\n const name = `${publish.registryNamespace}/${connector.id}`;\r\n if (!REGISTRY_NAME_RE.test(name)) {\r\n throw new Error(\r\n `server.json name \"${name}\" must match ${REGISTRY_NAME_RE} (exactly one \"/\").`,\r\n );\r\n }\r\n if (!isConcreteSemver(connector.version)) {\r\n throw new Error(\r\n `server.json version must be a concrete SemVer (the registry rejects ranges); got \"${connector.version}\".`,\r\n );\r\n }\r\n if (isPlaceholderVersion(connector.version)) {\r\n notes.push(\r\n 'version is the unset placeholder \"0.0.0\" — set a real version before publishing to the registry.',\r\n );\r\n }\r\n\r\n const out: Record<string, unknown> = {\r\n $schema: MCP_SERVER_SCHEMA_URL,\r\n name,\r\n description: connector.displayName,\r\n version: connector.version,\r\n };\r\n\r\n const server = connector.server;\r\n if (!server) {\r\n notes.push(\r\n \"connector declares no server — emitted server.json carries neither packages nor remotes \" +\r\n \"(a hooks/commands-only connector is not a registry server).\",\r\n );\r\n return out;\r\n }\r\n\r\n const tt = registryTransportType(server.transport);\r\n if (tt === null) {\r\n notes.push(\r\n `transport \"${server.transport}\" is not an MCP spec transport and cannot be represented in ` +\r\n \"server.json; emitted server metadata without a package/remote entry.\",\r\n );\r\n return out;\r\n }\r\n\r\n if (server.transport === \"stdio\") {\r\n if (!publish.packageName) {\r\n throw new Error(\r\n \"package --format mcp-server-json needs publish.packageName — your REAL published npm \" +\r\n 'package that runs the MCP server (e.g. \"@acme/acme-db-mcp\"). The registry runs that ' +\r\n \"package directly, not agent-connector's serve wrapper.\",\r\n );\r\n }\r\n const pkg: Record<string, unknown> = {\r\n registryType: \"npm\",\r\n registryBaseUrl: publish.registryBaseUrl ?? NPM_REGISTRY_BASE_URL,\r\n identifier: publish.packageName,\r\n version: connector.version,\r\n transport: { type: \"stdio\" },\r\n };\r\n const envVars = buildEnvVars(server);\r\n if (envVars.length > 0) pkg.environmentVariables = envVars;\r\n out.packages = [pkg];\r\n } else {\r\n // streamable-http | sse → remotes[]\r\n const remote: Record<string, unknown> = { type: tt, url: server.url };\r\n const headers = Object.keys(server.headers ?? {}).map((k): KeyValueInput => ({ name: k }));\r\n if (headers.length > 0) remote.headers = headers;\r\n if (server.auth && server.auth.type !== \"none\") {\r\n notes.push(\r\n `remote server uses auth \"${server.auth.type}\" — add the credential header (isSecret) to ` +\r\n \"the emitted remotes[].headers before publishing.\",\r\n );\r\n }\r\n out.remotes = [remote];\r\n }\r\n\r\n return out;\r\n}\r\n\r\n/** Emit a registry-conformant server.json for `connector` into ctx.outDir. */\r\nexport const emitMcpServerJson: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const emitter = createEmitter(ctx.dryRun);\r\n const notes: string[] = [];\r\n const serverJson = buildServerJson(connector, notes);\r\n const path = resolve(ctx.outDir, \"server.json\");\r\n emitter.emit(path, json(serverJson));\r\n return {\r\n files: emitter.files,\r\n pluginDir: ctx.outDir,\r\n ...(notes.length > 0 ? { notes } : {}),\r\n };\r\n};\r\n","/**\r\n * core/package-formats/mcpb — emit an MCPB (.mcpb, formerly DXT) bundle manifest.\r\n *\r\n * MCPB is the official cross-client one-click LOCAL-install bundle (Claude\r\n * Desktop + any MCPB host). A real .mcpb is a SELF-CONTAINED zip (manifest.json\r\n * + the server + vendored node_modules), which agent-connector cannot assemble\r\n * at emit time — we do not have the developer's built server tree. So, per the\r\n * conformance analysis, we emit a CONFORMANT manifest.json describing a\r\n * self-contained node bundle (NOT an out-of-spec `npx` command-reference, which\r\n * would assume network + node on PATH at launch and break offline/signing) plus\r\n * a packaging RECIPE, and leave the `mcpb pack`/`mcpb sign` to the developer —\r\n * mirroring how server.json defers the publish-time ownership proof.\r\n *\r\n * Secrets (the bearer token / sensitive env) are routed through `user_config`\r\n * (sensitive:true) and referenced as `${user_config.<key>}` in mcp_config.env,\r\n * so credentials are collected by the host keychain, never inlined.\r\n */\r\n\r\nimport { resolve } from \"node:path\";\r\n\r\nimport type { ResolvedConnector, ServerDef } from \"../types.js\";\r\nimport {\r\n MCPB_MANIFEST_VERSION,\r\n isConcreteSemver,\r\n isPlaceholderVersion,\r\n} from \"../mcp-standard.js\";\r\nimport type { EmitContext, FormatEmitter, PackageResult } from \"./shared.js\";\r\nimport { createEmitter, json } from \"./shared.js\";\r\n\r\n/** \"ACME_DB_TOKEN\" → \"Acme Db Token\" for a user_config field title. */\r\nfunction titleize(s: string): string {\r\n return s\r\n .toLowerCase()\r\n .split(/[_-]+/)\r\n .filter(Boolean)\r\n .map((w) => w[0]!.toUpperCase() + w.slice(1))\r\n .join(\" \");\r\n}\r\n\r\n/** The names of env vars that hold secrets (the bearer token). */\r\nfunction secretEnvNames(server: ServerDef): Set<string> {\r\n const names = new Set<string>();\r\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\r\n names.add(server.auth.bearerEnvVar);\r\n }\r\n return names;\r\n}\r\n\r\nfunction recipeReadme(connector: ResolvedConnector): string {\r\n return `# ${connector.displayName} — MCPB bundle\r\n\r\n\\`agent-connector package --format mcpb\\` emitted the conformant **manifest.json**\r\n(manifest_version ${MCPB_MANIFEST_VERSION}) for this connector. It does NOT build\r\nthe \\`.mcpb\\` zip — that step vendors your server and is yours to run, so the\r\nbundle stays self-contained and signable.\r\n\r\n## Finish the bundle\r\n\r\n1. Put your built, self-contained MCP server at \\`server/index.js\\`\r\n (the manifest's \\`entry_point\\` / \\`mcp_config\\`).\r\n2. Vendor production dependencies into the bundle:\r\n\r\n \\`\\`\\`bash\r\n cd server && npm install --omit=dev && cd ..\r\n \\`\\`\\`\r\n\r\n3. Pack (and optionally sign) with the official MCPB CLI:\r\n\r\n \\`\\`\\`bash\r\n npx @anthropic-ai/mcpb pack . # → ${connector.id}.mcpb\r\n npx @anthropic-ai/mcpb sign ${connector.id}.mcpb\r\n \\`\\`\\`\r\n\r\nThe resulting \\`.mcpb\\` installs one-click into Claude Desktop and any MCPB host.\r\nSecrets are declared under \\`user_config\\` and collected by the host keychain at\r\ninstall time — never inline them in the manifest.\r\n`;\r\n}\r\n\r\n/** Emit a conformant MCPB manifest.json + packaging recipe for `connector`. */\r\nexport const emitMcpbBundle: FormatEmitter = (\r\n connector: ResolvedConnector,\r\n ctx: EmitContext,\r\n): PackageResult => {\r\n const publish = connector.publish ?? {};\r\n if (!publish.author?.name) {\r\n throw new Error(\r\n \"package --format mcpb needs publish.author.name — the MCPB manifest requires an author.\",\r\n );\r\n }\r\n if (!isConcreteSemver(connector.version)) {\r\n throw new Error(\r\n `mcpb manifest version must be a concrete SemVer; got \"${connector.version}\".`,\r\n );\r\n }\r\n\r\n const server = connector.server;\r\n if (!server) {\r\n throw new Error(\"package --format mcpb needs a server (an MCPB bundle packages an MCP server).\");\r\n }\r\n if (server.transport !== \"stdio\") {\r\n throw new Error(\r\n `package --format mcpb supports stdio servers; \"${server.transport}\" is a remote server — ` +\r\n \"publish it via the registry (--format mcp-server-json) instead.\",\r\n );\r\n }\r\n\r\n const notes: string[] = [];\r\n if (isPlaceholderVersion(connector.version)) {\r\n notes.push('version is the unset placeholder \"0.0.0\" — set a real version before packing.');\r\n }\r\n\r\n // Route secret env vars through user_config; pass the rest through verbatim.\r\n const secrets = secretEnvNames(server);\r\n const env: Record<string, string> = {};\r\n const userConfig: Record<string, Record<string, unknown>> = {};\r\n for (const [k, v] of Object.entries(server.env ?? {})) {\r\n if (secrets.has(k)) {\r\n const key = k.toLowerCase();\r\n userConfig[key] = {\r\n type: \"string\",\r\n title: titleize(k),\r\n description: `Value for ${k}`,\r\n sensitive: true,\r\n required: true,\r\n };\r\n env[k] = `\\${user_config.${key}}`;\r\n } else {\r\n env[k] = v;\r\n }\r\n }\r\n // A bearer-token env not already present in server.env still needs a field.\r\n for (const name of secrets) {\r\n if (!(name in env)) {\r\n const key = name.toLowerCase();\r\n userConfig[key] = {\r\n type: \"string\",\r\n title: titleize(name),\r\n description: `Value for ${name}`,\r\n sensitive: true,\r\n required: true,\r\n };\r\n env[name] = `\\${user_config.${key}}`;\r\n }\r\n }\r\n\r\n const author: Record<string, string> = { name: publish.author.name };\r\n if (publish.author.email) author.email = publish.author.email;\r\n if (publish.author.url) author.url = publish.author.url;\r\n\r\n const mcpConfig: Record<string, unknown> = {\r\n command: \"node\",\r\n args: [\"${__dirname}/server/index.js\"],\r\n };\r\n if (Object.keys(env).length > 0) mcpConfig.env = env;\r\n\r\n const manifest: Record<string, unknown> = {\r\n manifest_version: MCPB_MANIFEST_VERSION,\r\n name: connector.id,\r\n version: connector.version,\r\n description: connector.displayName,\r\n author,\r\n server: {\r\n type: \"node\",\r\n entry_point: \"server/index.js\",\r\n mcp_config: mcpConfig,\r\n },\r\n };\r\n if (Object.keys(userConfig).length > 0) manifest.user_config = userConfig;\r\n\r\n // If the dev's real command is not node-ish, the node template needs adjusting.\r\n if (server.command && !/\\b(node|npx)\\b/.test(server.command)) {\r\n notes.push(\r\n `your server command is \"${server.command}\" — the emitted manifest assumes a node ` +\r\n \"server (server.type:node); adjust server.type/entry_point for your runtime (python|binary).\",\r\n );\r\n }\r\n notes.push(\r\n \"emitted manifest.json + README recipe; this format does NOT build the .mcpb zip. \" +\r\n \"Place your self-contained server at server/index.js, vendor deps, then run `mcpb pack` (see README).\",\r\n );\r\n\r\n const emitter = createEmitter(ctx.dryRun);\r\n emitter.emit(resolve(ctx.outDir, \"manifest.json\"), json(manifest));\r\n emitter.emit(resolve(ctx.outDir, \"README.md\"), recipeReadme(connector));\r\n return { files: emitter.files, pluginDir: ctx.outDir, notes };\r\n};\r\n"],"mappings":"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","names":["existsSync","join","resolve","join","buildManifest","buildMarketplace","join","join","SPECS","buildManifest","join","join","PLATFORM","buildManifest","join","join","PLATFORM","buildManifest","join","join","join","resolve","resolve","resolve","resolve","resolve","join"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/claude-code/wire.ts"],"sourcesContent":["/**\r\n * adapters/claude-code/wire — Claude Code hook wire protocol.\r\n *\r\n * Claude Code pipes a JSON object to a hook command on stdin and reads a JSON\r\n * object (or empty) from stdout, interpreting the exit code as well. This module\r\n * captures the exact stdin shape and the canonical reply shape so the adapter's\r\n * parse/format methods are a single source of truth.\r\n *\r\n * Stdin (documented Claude Code hook input):\r\n * {\r\n * session_id, transcript_path, cwd, hook_event_name,\r\n * tool_name, tool_input, tool_response, // tool events\r\n * permission_suggestions, // PermissionRequest\r\n * tool_use_id, error, is_interrupt, duration_ms, // PostToolUseFailure\r\n * agent_id, agent_type, // SubagentStart/Stop\r\n * agent_transcript_path, last_assistant_message, // SubagentStop\r\n * source, // SessionStart\r\n * reason, // SessionEnd\r\n * prompt, // UserPromptSubmit\r\n * trigger, // PreCompact\r\n * stop_hook_active, // Stop / SubagentStop\r\n * message // Notification\r\n * }\r\n *\r\n * Stdout (canonical reply): a `hookSpecificOutput` object keyed by\r\n * `hookEventName`, carrying `permissionDecision` (allow|deny|ask) +\r\n * `permissionDecisionReason`, `additionalContext`, and (PreToolUse)\r\n * `updatedInput`; PermissionRequest instead takes a nested\r\n * `decision: { behavior: \"allow\"|\"deny\", ... }`; Stop-class blocks\r\n * (Stop / SubagentStop / UserPromptSubmit / PostToolUse) take the TOP-LEVEL\r\n * `{\"decision\":\"block\",\"reason\"}`. Exit 0 = proceed; the JSON refines the\r\n * decision.\r\n */\r\n\r\nimport type { SessionStartEvent } from \"../../core/types.js\";\r\n\r\n/** Canonical Claude Code hook event names (the values of `hook_event_name`). */\r\nexport const CLAUDE_HOOK_EVENTS = [\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"SessionStart\",\r\n \"SessionEnd\",\r\n \"UserPromptSubmit\",\r\n \"Stop\",\r\n \"Notification\",\r\n \"PermissionRequest\",\r\n \"PostToolUseFailure\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n] as const;\r\n\r\nexport type ClaudeHookEvent = (typeof CLAUDE_HOOK_EVENTS)[number];\r\n\r\n/**\r\n * Raw Claude Code hook stdin payload. Every field is optional — a given event\r\n * only populates the subset relevant to it. `connector` is NOT a Claude field;\r\n * it is threaded in by the universal entrypoint so parseEvent can recover the\r\n * connector id (the home binary passes `--connector <id>` and may inject it).\r\n */\r\nexport interface ClaudeWireInput {\r\n session_id?: string;\r\n transcript_path?: string;\r\n cwd?: string;\r\n hook_event_name?: string;\r\n\r\n // tool events\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n /** PostToolUse result payload (string or structured). */\r\n tool_response?: unknown;\r\n\r\n // PermissionRequest — permission-update entries the dialog would offer.\r\n // NOTE: the docs explicitly state PermissionRequest has NO tool_use_id.\r\n permission_suggestions?: unknown[];\r\n\r\n // PostToolUseFailure\r\n tool_use_id?: string;\r\n error?: string;\r\n is_interrupt?: boolean;\r\n duration_ms?: number;\r\n\r\n // SubagentStart / SubagentStop — agent_type is unreliable on SubagentStop\r\n // (the SDK may not populate it); treat both as optional everywhere.\r\n agent_id?: string;\r\n agent_type?: string;\r\n // SubagentStop — the subagent's OWN transcript (transcript_path stays the\r\n // parent session's) + the text of its final response.\r\n agent_transcript_path?: string;\r\n last_assistant_message?: string;\r\n\r\n // SessionStart\r\n source?: string;\r\n // SessionEnd\r\n reason?: string;\r\n // UserPromptSubmit\r\n prompt?: string;\r\n // PreCompact\r\n trigger?: string;\r\n // Stop / SubagentStop\r\n stop_hook_active?: boolean;\r\n // Notification\r\n message?: string;\r\n\r\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\r\n connector?: string;\r\n}\r\n\r\n/**\r\n * Extract a stable session id from a Claude wire payload.\r\n * Priority mirrors the proven adapter: transcript UUID > session_id > \"\".\r\n * (The framework's normalized event uses \"\" when no id is available, per\r\n * core/types BaseEvent.sessionId docstring — no ppid fabrication here.)\r\n */\r\nexport function extractSessionId(input: ClaudeWireInput): string {\r\n if (typeof input.transcript_path === \"string\") {\r\n const m = input.transcript_path.match(/([a-f0-9-]{36})\\.jsonl$/);\r\n if (m && m[1]) return m[1];\r\n }\r\n if (typeof input.session_id === \"string\" && input.session_id !== \"\") {\r\n return input.session_id;\r\n }\r\n return \"\";\r\n}\r\n\r\n/** Coerce a Claude PostToolUse `tool_response` into a string for the normalized event. */\r\nexport function 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\n/** Map a host's raw session-start \"source\" to the canonical SessionStart source. */\r\nexport function normalizeSessionSource(source: string | undefined): SessionStartEvent[\"source\"] {\r\n switch (source) {\r\n case \"compact\":\r\n return \"compact\";\r\n case \"resume\":\r\n return \"resume\";\r\n case \"clear\":\r\n return \"clear\";\r\n default:\r\n return \"startup\";\r\n }\r\n}\r\n"],"mappings":";;;AAkHO,SAAS,iBAAiB,OAAgC;AAC/D,MAAI,OAAO,MAAM,oBAAoB,UAAU;AAC7C,UAAM,IAAI,MAAM,gBAAgB,MAAM,yBAAyB;AAC/D,QAAI,KAAK,EAAE,CAAC,EAAG,QAAO,EAAE,CAAC;AAAA,EAC3B;AACA,MAAI,OAAO,MAAM,eAAe,YAAY,MAAM,eAAe,IAAI;AACnE,WAAO,MAAM;AAAA,EACf;AACA,SAAO;AACT;AAGO,SAAS,qBAAqB,OAAoC;AACvE,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAGO,SAAS,uBAAuB,QAAyD;AAC9F,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/ts-plugin-bridge.ts"],"sourcesContent":["/**\r\n * Pure string-builder for the byte-identical HEAD of every ts-plugin host's\r\n * generated plugin module: the `HOME_BIN`/`CONNECTOR_ID` consts plus the\r\n * cross-OS `bridge(event, payload)` entrypoint (win32 `execSync`-quoted vs\r\n * POSIX `execFileSync`, fail-open `JSON.parse`).\r\n *\r\n * This module emits SOURCE TEXT only — it imports nothing at runtime and is\r\n * never loaded by a generated plugin. The 6 adopting hosts (amp, kilo,\r\n * kilo-cli, mimo-code, omp, opencode) differ in this region by exactly four\r\n * host-specific tokens, captured below. Changing the emitted bytes here changes\r\n * every host's generated plugin in lockstep; each host's adapter suite runs the\r\n * generated plugin live and asserts source substrings, so it is the byte oracle.\r\n */\r\n\r\nexport interface BridgePreludeOptions {\r\n /** Absolute home-bin path (raw — JSON.stringified inside). */\r\n homeBin: string;\r\n /** Connector id (raw — JSON.stringified inside). */\r\n connectorId: string;\r\n /** Host hook subcommand slug used in the `hook <slug>` argv (e.g. \"opencode\", \"amp\"). */\r\n hookSlug: string;\r\n /** Host noun for the jsdoc `@param payload <noun>-shaped …` line (e.g. \"OpenCode\", \"amp\", \"OMP\"). */\r\n payloadNoun: string;\r\n /** Optional suffix on the jsdoc `@param event canonical event name<eventDoc>` line (e.g. \" (PreToolUse|PostToolUse|SessionStart)\"). Default \"\". */\r\n eventDoc?: string;\r\n /** The exact fail-open catch-comment line (host wording differs). */\r\n failOpenComment: string;\r\n}\r\n\r\n/**\r\n * Render the HOME_BIN/CONNECTOR_ID consts + the universal-entrypoint bridge() —\r\n * the byte-identical head of every ts-plugin host's generated plugin module.\r\n */\r\nexport function renderBridgePrelude(opts: BridgePreludeOptions): string {\r\n return `const HOME_BIN = ${JSON.stringify(opts.homeBin)};\r\nconst CONNECTOR_ID = ${JSON.stringify(opts.connectorId)};\r\n\r\n/**\r\n * Invoke the universal hook entrypoint for one event.\r\n * @param {string} event canonical event name${opts.eventDoc ?? \"\"}\r\n * @param {object} payload ${opts.payloadNoun}-shaped payload posted on stdin\r\n * @returns {object|null} normalized HookResponse, or null on any failure\r\n */\r\nfunction bridge(event, payload) {\r\n try {\r\n // On Windows HOME_BIN is the agent-connector.cmd launcher: Node cannot\r\n // execFile a batch file, and shell+args is deprecated (DEP0190), so run one\r\n // quoted command line via a shell. POSIX keeps the direct execFile (no shell).\r\n const args = [\"hook\", ${JSON.stringify(opts.hookSlug)}, event, \"--connector\", CONNECTOR_ID];\r\n const opts = { input: JSON.stringify(payload), encoding: \"utf8\" };\r\n const stdout =\r\n process.platform === \"win32\"\r\n ? execSync([HOME_BIN, ...args].map((a) => '\"' + a + '\"').join(\" \"), opts)\r\n : execFileSync(HOME_BIN, args, opts);\r\n const text = (stdout || \"\").trim();\r\n if (text === \"\") return { decision: \"allow\" };\r\n return JSON.parse(text);\r\n } catch {\r\n // ${opts.failOpenComment}\r\n return null;\r\n }\r\n}`;\r\n}\r\n"],"mappings":";;;AAiCO,SAAS,oBAAoB,MAAoC;AACtE,SAAO,oBAAoB,KAAK,UAAU,KAAK,OAAO,CAAC;AAAA,uBAClC,KAAK,UAAU,KAAK,WAAW,CAAC;AAAA;AAAA;AAAA;AAAA,+CAIR,KAAK,YAAY,EAAE;AAAA,6BACrC,KAAK,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAQjB,KAAK,UAAU,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAUhD,KAAK,eAAe;AAAA;AAAA;AAAA;AAI7B;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/telemetry/surface-footprint.ts","../src/telemetry/leaderboard.ts"],"sourcesContent":["/**\r\n * telemetry/surface-footprint — the STATIC developer-axis surfaces.\r\n *\r\n * Commands, skills, and subagents are NOT runtime-intercepted: the host loads\r\n * them as context (slash-command bodies, SKILL.md + resources, subagent system\r\n * prompts) and we never sit in the byte path the way the serve-proxy does for a\r\n * server or the hook runtime does for a hook. So we do NOT (and must not) write\r\n * fake usage rows for them. Instead we compute a deterministic STATIC FOOTPRINT:\r\n * the token cost the surface IMPOSES on a host that loads it, tokenized with the\r\n * SAME shared tokenizer the proxy + hook runtime use.\r\n *\r\n * This is pure: the only input is the passed {@link ResolvedConnector}; there is\r\n * no IO beyond reading that object's already-loaded fields.\r\n */\r\n\r\nimport type { ResolvedConnector } from \"../core/types.js\";\r\nimport { getTokenizer, inferModelFamily } from \"./tokenizer.js\";\r\nimport type { ModelFamily, SurfaceKind, Tokenizer } from \"./types.js\";\r\n\r\n/**\r\n * One static surface footprint: a content surface (command/skill/subagent) and\r\n * the token cost it imposes on a host that loads it. `kind` is the surface kind\r\n * (never `server`/`hook` — those are runtime-measured), `name` is the surface's\r\n * declared name, and `tokens` is the tokenized whole-surface footprint.\r\n */\r\nexport interface SurfaceFootprint {\r\n surfaceKind: Extract<SurfaceKind, \"command\" | \"skill\" | \"subagent\">;\r\n name: string;\r\n tokens: number;\r\n}\r\n\r\n/** Tokenize a list of text fragments (joined with \"\\n\") under `family`. */\r\nfunction countParts(\r\n parts: readonly string[],\r\n family: ModelFamily,\r\n tok: Tokenizer,\r\n): number {\r\n // A surface's footprint is its concatenated content — joining with a newline\r\n // mirrors how the host renders the fields together as one context blob.\r\n return tok.count(parts.join(\"\\n\"), family).tokens;\r\n}\r\n\r\n/**\r\n * Compute the STATIC footprints of every content surface declared on a\r\n * connector, deterministically (same input → same output) and without IO.\r\n *\r\n * • command → description + prompt + argumentHint\r\n * • skill → description + body + every resource value (sorted by path for\r\n * deterministic ordering, so the joined text is stable)\r\n * • subagent → description + prompt\r\n *\r\n * The shared {@link Tokenizer} is used so a command/skill/subagent footprint is\r\n * directly comparable with the runtime `server`/`hook` token counts. The model\r\n * family is inferred from the connector's telemetry hint (no host context here).\r\n */\r\nexport function computeSurfaceFootprints(\r\n connector: ResolvedConnector,\r\n tok: Tokenizer = getTokenizer(),\r\n): SurfaceFootprint[] {\r\n const family = inferModelFamily(\"\", connector.telemetry.modelFamilyHint);\r\n const out: SurfaceFootprint[] = [];\r\n\r\n for (const cmd of connector.commands) {\r\n const parts: string[] = [];\r\n if (cmd.description !== undefined) parts.push(cmd.description);\r\n parts.push(cmd.prompt);\r\n if (cmd.argumentHint !== undefined) parts.push(cmd.argumentHint);\r\n out.push({\r\n surfaceKind: \"command\",\r\n name: cmd.name,\r\n tokens: countParts(parts, family, tok),\r\n });\r\n }\r\n\r\n for (const skill of connector.skills) {\r\n const parts: string[] = [skill.description, skill.body];\r\n if (skill.resources !== undefined) {\r\n // Sort by resource path so the joined text (and thus the count) is stable\r\n // regardless of object key insertion order.\r\n const paths = Object.keys(skill.resources).sort();\r\n for (const p of paths) {\r\n const value = skill.resources[p];\r\n if (value !== undefined) parts.push(value);\r\n }\r\n }\r\n out.push({\r\n surfaceKind: \"skill\",\r\n name: skill.name,\r\n tokens: countParts(parts, family, tok),\r\n });\r\n }\r\n\r\n for (const agent of connector.subagents) {\r\n out.push({\r\n surfaceKind: \"subagent\",\r\n name: agent.name,\r\n tokens: countParts([agent.description, agent.prompt], family, tok),\r\n });\r\n }\r\n\r\n return out;\r\n}\r\n","/**\r\n * telemetry/leaderboard — the PLUGIN / MCP leaderboard, derived from the per-MCP\r\n * serve-proxy telemetry store (src/telemetry/*).\r\n *\r\n * This is the signature MCP-dev metric: of the MCP servers WE wrap, which one\r\n * costs the most tokens — platform-independent, because it measures the server's\r\n * OWN bytes (tool args in, tool result out, tool-defs schemas) tokenized locally,\r\n * the only signal identical across every host. Origin is always `mcp-self`; it is\r\n * NEVER summed with host-native usage (src/usage/*), which measures a different\r\n * thing (whole-conversation tokens).\r\n *\r\n * Pure aggregation + pure formatting over {@link TelemetryStore.query}. The scope\r\n * dimension (installScope/launchMethod) is OPTIONAL on each row — rows written\r\n * before those fields existed are read as \"unknown\" and are honestly labeled.\r\n */\r\n\r\nimport type { ResolvedConnector } from \"../core/types.js\";\r\nimport { openStore } from \"./store.js\";\r\nimport { computeSurfaceFootprints } from \"./surface-footprint.js\";\r\nimport { worstConfidence } from \"./types.js\";\r\nimport type {\r\n ConfidenceSource,\r\n LaunchMethod,\r\n QueryFilter,\r\n SurfaceKind,\r\n TelemetryInstallScope,\r\n TelemetryStore,\r\n ToolEventRecord,\r\n} from \"./types.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Options + scope filter\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * A scope filter value the leaderboards accept. The two install buckets\r\n * (`user`/`project`) and the launch methods (`npx`/`bunx`/`uvx`/`node`/`binary`/\r\n * `http`) plus the honest `unknown` fallback. A record matches a `user`/`project`\r\n * value by its `installScope`, and a launch-method value by its `launchMethod`.\r\n */\r\nexport type ScopeFilter =\r\n | TelemetryInstallScope\r\n | LaunchMethod;\r\n\r\n/** Every accepted {@link ScopeFilter} string, for CLI validation. */\r\nexport const SCOPE_FILTER_VALUES: readonly ScopeFilter[] = [\r\n \"user\",\r\n \"project\",\r\n \"npx\",\r\n \"bunx\",\r\n \"uvx\",\r\n \"node\",\r\n \"binary\",\r\n \"http\",\r\n \"unknown\",\r\n] as const;\r\n\r\n/** Options shared by every leaderboard query. */\r\nexport interface LeaderboardOptions {\r\n /** An open store to read from. Defaults to {@link openStore} on the data-root. */\r\n store?: TelemetryStore;\r\n /** Lower-bound epoch ms (inclusive) — forwarded as the store's sinceMs filter. */\r\n sinceMs?: number;\r\n /** Restrict to one connector. */\r\n connectorId?: string;\r\n /** Slice by install scope (user|project) or launch method (npx|binary|http|…). */\r\n scope?: ScopeFilter;\r\n}\r\n\r\n/** Is `value` one of the accepted scope-filter strings? */\r\nexport function isScopeFilter(value: string): value is ScopeFilter {\r\n return (SCOPE_FILTER_VALUES as readonly string[]).includes(value);\r\n}\r\n\r\n/** The install/launch values a `user`/`project` scope filter matches against. */\r\nconst INSTALL_SCOPES: ReadonlySet<string> = new Set<string>([\"user\", \"project\"]);\r\n\r\n/**\r\n * Does a record satisfy the requested scope slice? `user`/`project` match the\r\n * record's `installScope`; any concrete launch method matches the record's\r\n * `launchMethod`. The honest `unknown` filter is special: it matches ONLY a\r\n * record that lacks BOTH dimensions (a truly pre-scope row) — a record carrying\r\n * a known installScope but no launchMethod (or vice-versa) is NOT \"unknown\" and\r\n * must not be swept into that bucket.\r\n */\r\nfunction matchesScope(record: ToolEventRecord, scope: ScopeFilter): boolean {\r\n if (scope === \"unknown\") {\r\n return record.installScope === undefined && record.launchMethod === undefined;\r\n }\r\n if (INSTALL_SCOPES.has(scope)) {\r\n return record.installScope === scope;\r\n }\r\n return record.launchMethod === scope;\r\n}\r\n\r\n/** Build the store {@link QueryFilter} from the shared options. */\r\nfunction toFilter(opts: LeaderboardOptions): QueryFilter {\r\n const filter: QueryFilter = {};\r\n if (opts.sinceMs !== undefined) filter.sinceMs = opts.sinceMs;\r\n if (opts.connectorId !== undefined && opts.connectorId !== \"\") {\r\n filter.connectorId = opts.connectorId;\r\n }\r\n return filter;\r\n}\r\n\r\n/**\r\n * Query the store and apply the (in-memory) scope slice the store cannot. By\r\n * default EXCLUDES the host-native `model_turn` rows: this selector feeds the\r\n * per-MCP/plugin views (mcp/tool/scope), which measure per-MCP `call` + the\r\n * `tool_defs` overhead and must NEVER sum the whole-conversation host-native\r\n * turns. Pass `includeModelTurn: true` to read those rows instead (used by\r\n * {@link hostNativeTurns}).\r\n */\r\nfunction selectRecords(\r\n opts: LeaderboardOptions,\r\n includeModelTurn = false,\r\n): ToolEventRecord[] {\r\n const store = opts.store ?? openStore({});\r\n const owned = opts.store === undefined;\r\n try {\r\n let rows = store.query(toFilter(opts));\r\n rows = includeModelTurn\r\n ? rows.filter((r) => r.scope === \"model_turn\")\r\n : rows.filter((r) => r.scope !== \"model_turn\");\r\n if (opts.scope === undefined) return rows;\r\n const scope = opts.scope;\r\n return rows.filter((r) => matchesScope(r, scope));\r\n } finally {\r\n if (owned) store.close();\r\n }\r\n}\r\n\r\n// Confidence ranking + worst-of comparison live in ./types (the single source\r\n// of truth, imported as worstConfidence above) so a new ConfidenceSource value\r\n// orders correctly here as well.\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Leaderboard rows\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * One row of the MCP/plugin leaderboard — a connector ranked by total measured\r\n * tokens. `tools` is the count of distinct tool names seen (excluding the\r\n * tool-defs `*` pseudo-tool); `hostPlatforms` is the distinct set of hosts that\r\n * ran this server, evidence that the count aggregates across machines.\r\n */\r\nexport interface McpLeaderboardRow {\r\n connectorId: string;\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n /** Count of distinct real tool names (the tool-defs `*` row is excluded). */\r\n tools: number;\r\n /** Distinct host platforms that produced records, sorted for stable output. */\r\n hostPlatforms: string[];\r\n /** Worst (least-confident) source in the group, for honest labeling. */\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * One row of the per-tool leaderboard — a (connector, tool) pair ranked by total\r\n * measured tokens. The tool-defs pseudo-tool (`*`, scope `tool_defs`) is kept as\r\n * its own row so the fixed schema overhead is visible rather than hidden.\r\n */\r\nexport interface ToolLeaderboardRow {\r\n connectorId: string;\r\n toolName: string;\r\n /** \"call\" round-trips vs the one-time \"tool_defs\" overhead measurement. */\r\n scope: ToolEventRecord[\"scope\"];\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * One row of the scope breakdown — usage grouped by (installScope, launchMethod),\r\n * both honestly reported as \"unknown\" when the underlying record lacks the field.\r\n */\r\nexport interface ScopeBreakdownRow {\r\n installScope: TelemetryInstallScope | \"unknown\";\r\n launchMethod: LaunchMethod;\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * One row of the host-native turns aggregation — a (host, session) pair ranked by\r\n * total host-reported tokens for that whole-conversation turn stream. This is the\r\n * THIRD origin (`host-native-live`): it comes from the opt-in AfterModel /\r\n * PostInvocation usage hook (scope `model_turn`, confidence `host-native`) and is\r\n * NEVER summed with the per-MCP `call` rows or the usage-reader host-scan numbers.\r\n */\r\nexport interface HostNativeTurnsRow {\r\n hostPlatform: string;\r\n sessionId: string;\r\n /** Number of recorded model turns (scope `model_turn` rows) in this group. */\r\n turns: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n /** Distinct connector ids that produced turns under this host/session. */\r\n connectors: string[];\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/** Mutable accumulator for the host-native turns fold (set finalized to count). */\r\ninterface HostNativeAcc {\r\n hostPlatform: string;\r\n sessionId: string;\r\n turns: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n connectors: Set<string>;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/** Mutable accumulator for the MCP leaderboard fold (sets finalized to counts). */\r\ninterface McpAcc {\r\n connectorId: string;\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n tools: Set<string>;\r\n hostPlatforms: Set<string>;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * The PLUGIN / MCP leaderboard: rank connectors by total measured tokens desc\r\n * (ties broken by recency). This is the headline \"which MCP server costs the\r\n * most\" metric, platform-independent by construction.\r\n */\r\nexport function mcpLeaderboard(opts: LeaderboardOptions = {}): McpLeaderboardRow[] {\r\n const groups = new Map<string, McpAcc>();\r\n\r\n for (const r of selectRecords(opts)) {\r\n let g = groups.get(r.connectorId);\r\n if (g === undefined) {\r\n g = {\r\n connectorId: r.connectorId,\r\n calls: 0,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n totalTokens: 0,\r\n tools: new Set<string>(),\r\n hostPlatforms: new Set<string>(),\r\n confidence: r.confidenceSource,\r\n lastTs: r.ts,\r\n };\r\n groups.set(r.connectorId, g);\r\n }\r\n // A tool_defs row is a one-time schema overhead, not a call: count its\r\n // tokens but do not inflate the call count or the distinct-tool count.\r\n if (r.scope === \"call\") {\r\n g.calls += 1;\r\n g.tools.add(r.toolName);\r\n }\r\n g.inputTokens += r.inputTokens;\r\n g.outputTokens += r.outputTokens;\r\n g.totalTokens += r.inputTokens + r.outputTokens;\r\n g.hostPlatforms.add(r.hostPlatform);\r\n g.confidence = worstConfidence(g.confidence, r.confidenceSource);\r\n if (r.ts > g.lastTs) g.lastTs = r.ts;\r\n }\r\n\r\n const rows: McpLeaderboardRow[] = [];\r\n for (const g of groups.values()) {\r\n rows.push({\r\n connectorId: g.connectorId,\r\n calls: g.calls,\r\n inputTokens: g.inputTokens,\r\n outputTokens: g.outputTokens,\r\n totalTokens: g.totalTokens,\r\n tools: g.tools.size,\r\n hostPlatforms: [...g.hostPlatforms].sort(),\r\n confidence: g.confidence,\r\n lastTs: g.lastTs,\r\n });\r\n }\r\n rows.sort((a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n\r\n/**\r\n * The per-tool leaderboard: rank (connector, tool) pairs by total tokens desc\r\n * (ties broken by recency). Drills the MCP leaderboard down to which individual\r\n * tool is the expensive one.\r\n */\r\nexport function toolLeaderboard(opts: LeaderboardOptions = {}): ToolLeaderboardRow[] {\r\n const groups = new Map<string, ToolLeaderboardRow>();\r\n\r\n for (const r of selectRecords(opts)) {\r\n const key = `${r.connectorId}\\u0000${r.toolName}\\u0000${r.scope}`;\r\n const g = groups.get(key);\r\n if (g === undefined) {\r\n groups.set(key, {\r\n connectorId: r.connectorId,\r\n toolName: r.toolName,\r\n scope: r.scope,\r\n calls: r.scope === \"call\" ? 1 : 0,\r\n inputTokens: r.inputTokens,\r\n outputTokens: r.outputTokens,\r\n totalTokens: r.inputTokens + r.outputTokens,\r\n confidence: r.confidenceSource,\r\n lastTs: r.ts,\r\n });\r\n } else {\r\n if (r.scope === \"call\") g.calls += 1;\r\n g.inputTokens += r.inputTokens;\r\n g.outputTokens += r.outputTokens;\r\n g.totalTokens += r.inputTokens + r.outputTokens;\r\n g.confidence = worstConfidence(g.confidence, r.confidenceSource);\r\n if (r.ts > g.lastTs) g.lastTs = r.ts;\r\n }\r\n }\r\n\r\n const rows = [...groups.values()];\r\n rows.sort((a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n\r\n/**\r\n * The scope breakdown: group usage by (installScope, launchMethod). Both\r\n * dimensions read \"unknown\" when the source row lacks the field, so a pre-scope\r\n * row is honestly bucketed rather than dropped or mis-attributed.\r\n */\r\nexport function scopeBreakdown(opts: LeaderboardOptions = {}): ScopeBreakdownRow[] {\r\n const groups = new Map<string, ScopeBreakdownRow>();\r\n\r\n for (const r of selectRecords(opts)) {\r\n const installScope: TelemetryInstallScope | \"unknown\" = r.installScope ?? \"unknown\";\r\n const launchMethod: LaunchMethod = r.launchMethod ?? \"unknown\";\r\n const key = `${installScope}\\u0000${launchMethod}`;\r\n const g = groups.get(key);\r\n if (g === undefined) {\r\n groups.set(key, {\r\n installScope,\r\n launchMethod,\r\n calls: r.scope === \"call\" ? 1 : 0,\r\n inputTokens: r.inputTokens,\r\n outputTokens: r.outputTokens,\r\n totalTokens: r.inputTokens + r.outputTokens,\r\n confidence: r.confidenceSource,\r\n lastTs: r.ts,\r\n });\r\n } else {\r\n if (r.scope === \"call\") g.calls += 1;\r\n g.inputTokens += r.inputTokens;\r\n g.outputTokens += r.outputTokens;\r\n g.totalTokens += r.inputTokens + r.outputTokens;\r\n g.confidence = worstConfidence(g.confidence, r.confidenceSource);\r\n if (r.ts > g.lastTs) g.lastTs = r.ts;\r\n }\r\n }\r\n\r\n const rows = [...groups.values()];\r\n rows.sort((a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n\r\n/**\r\n * The THIRD origin: host-native turns. Aggregates ONLY the `model_turn` rows (the\r\n * opt-in AfterModel / PostInvocation host-native usage hook) by (host, session),\r\n * ranked by total host-reported tokens desc. This is whole-conversation usage the\r\n * host itself reported — exact, but a DIFFERENT thing than the per-MCP `call`\r\n * rows; it is surfaced separately and NEVER summed with the other two origins.\r\n */\r\nexport function hostNativeTurns(opts: LeaderboardOptions = {}): HostNativeTurnsRow[] {\r\n const groups = new Map<string, HostNativeAcc>();\r\n\r\n for (const r of selectRecords(opts, /* includeModelTurn */ true)) {\r\n const key = `${r.hostPlatform}\\u0000${r.sessionId}`;\r\n let g = groups.get(key);\r\n if (g === undefined) {\r\n g = {\r\n hostPlatform: r.hostPlatform,\r\n sessionId: r.sessionId,\r\n turns: 0,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n totalTokens: 0,\r\n connectors: new Set<string>(),\r\n confidence: r.confidenceSource,\r\n lastTs: r.ts,\r\n };\r\n groups.set(key, g);\r\n }\r\n g.turns += 1;\r\n g.inputTokens += r.inputTokens;\r\n g.outputTokens += r.outputTokens;\r\n g.totalTokens += r.inputTokens + r.outputTokens;\r\n g.connectors.add(r.connectorId);\r\n g.confidence = worstConfidence(g.confidence, r.confidenceSource);\r\n if (r.ts > g.lastTs) g.lastTs = r.ts;\r\n }\r\n\r\n const rows: HostNativeTurnsRow[] = [];\r\n for (const g of groups.values()) {\r\n rows.push({\r\n hostPlatform: g.hostPlatform,\r\n sessionId: g.sessionId,\r\n turns: g.turns,\r\n inputTokens: g.inputTokens,\r\n outputTokens: g.outputTokens,\r\n totalTokens: g.totalTokens,\r\n connectors: [...g.connectors].sort(),\r\n confidence: g.confidence,\r\n lastTs: g.lastTs,\r\n });\r\n }\r\n rows.sort((a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Per-surface leaderboard (the FIVE developer-axis surfaces)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * One row of the per-surface developer breakdown — a (surfaceKind, name) pair.\r\n * Combines the RUNTIME-measured surfaces (server `call`+`tool_defs` rows and the\r\n * new `hook` rows from the telemetry store) with the STATIC content footprints\r\n * (command/skill/subagent) from {@link computeSurfaceFootprints}.\r\n *\r\n * • `kind` distinguishes RUNTIME (measured live) from STATIC (footprint of\r\n * context the host loads — never an intercepted usage row).\r\n * • For static rows `calls` is 0, `outputTokens` is 0, the cost sits in\r\n * `inputTokens`/`totalTokens`, and `confidence` is the tokenizer source for\r\n * the connector's family. For runtime rows everything aggregates the store.\r\n */\r\nexport interface SurfaceLeaderboardRow {\r\n surfaceKind: SurfaceKind;\r\n /** Per-item name: the tool name (server), the event name (hook), or the\r\n * command/skill/subagent name (static surfaces). */\r\n name: string;\r\n /** RUNTIME (server/hook store rows) vs STATIC (command/skill/subagent footprint). */\r\n kind: \"runtime\" | \"static\";\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/** Mutable accumulator for the runtime side of the per-surface fold. */\r\ninterface SurfaceAcc {\r\n surfaceKind: SurfaceKind;\r\n name: string;\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * A record's developer-axis surface kind, backward-compatibly. Rows written\r\n * before `surfaceKind` existed (every legacy serve-proxy `call`/`tool_defs` row)\r\n * lack it and are read as `server`; the `hook` runtime stamps it explicitly.\r\n */\r\nfunction recordSurfaceKind(r: ToolEventRecord): SurfaceKind {\r\n if (r.surfaceKind !== undefined) return r.surfaceKind;\r\n // No explicit kind → it predates this field → it is a serve-proxy server row.\r\n return \"server\";\r\n}\r\n\r\n/** Options for {@link surfaceLeaderboard}: the shared query opts + the connectors\r\n * whose STATIC footprints are folded in. */\r\nexport interface SurfaceLeaderboardOptions extends LeaderboardOptions {\r\n /** Registered connectors to compute static command/skill/subagent footprints\r\n * over. Omit/empty → only the runtime (server/hook) rows are reported. */\r\n connectors?: readonly ResolvedConnector[];\r\n}\r\n\r\n/**\r\n * The PER-SURFACE developer leaderboard across all FIVE surfaces.\r\n *\r\n * RUNTIME side: the store's `call`/`tool_defs` rows (surface `server`) and the\r\n * `hook` rows (surface `hook`), grouped by (surfaceKind, name) with IN/OUT/TOTAL\r\n * and a call count. (`model_turn` rows are excluded by `selectRecords`, exactly\r\n * as the per-MCP views exclude them.)\r\n *\r\n * STATIC side: one row per command/skill/subagent from\r\n * {@link computeSurfaceFootprints} over each passed connector, deduped by\r\n * (surfaceKind, name) and summed when the same surface is declared by more than\r\n * one connector. Static rows carry the footprint in `inputTokens` (the cost the\r\n * host pays to load that context); `outputTokens`/`calls` are 0.\r\n *\r\n * Sorted by total tokens desc, ties broken by recency (static rows have lastTs 0\r\n * so they sort after equal-token runtime rows).\r\n */\r\nexport function surfaceLeaderboard(\r\n opts: SurfaceLeaderboardOptions = {},\r\n): SurfaceLeaderboardRow[] {\r\n // ── RUNTIME: aggregate server + hook store rows by (surfaceKind, name) ──\r\n const runtime = new Map<string, SurfaceAcc>();\r\n for (const r of selectRecords(opts)) {\r\n const surfaceKind = recordSurfaceKind(r);\r\n const key = `${surfaceKind} ${r.toolName}`;\r\n let g = runtime.get(key);\r\n if (g === undefined) {\r\n g = {\r\n surfaceKind,\r\n name: r.toolName,\r\n calls: 0,\r\n inputTokens: 0,\r\n outputTokens: 0,\r\n totalTokens: 0,\r\n confidence: r.confidenceSource,\r\n lastTs: r.ts,\r\n };\r\n runtime.set(key, g);\r\n }\r\n // tool_defs is a one-time schema overhead, not a call — count tokens only.\r\n if (r.scope === \"call\" || r.scope === \"hook\") g.calls += 1;\r\n g.inputTokens += r.inputTokens;\r\n g.outputTokens += r.outputTokens;\r\n g.totalTokens += r.inputTokens + r.outputTokens;\r\n g.confidence = worstConfidence(g.confidence, r.confidenceSource);\r\n if (r.ts > g.lastTs) g.lastTs = r.ts;\r\n }\r\n\r\n const rows: SurfaceLeaderboardRow[] = [];\r\n for (const g of runtime.values()) {\r\n rows.push({\r\n surfaceKind: g.surfaceKind,\r\n name: g.name,\r\n kind: \"runtime\",\r\n calls: g.calls,\r\n inputTokens: g.inputTokens,\r\n outputTokens: g.outputTokens,\r\n totalTokens: g.totalTokens,\r\n confidence: g.confidence,\r\n lastTs: g.lastTs,\r\n });\r\n }\r\n\r\n // ── STATIC: fold in command/skill/subagent footprints per connector ──────\r\n const staticRows = new Map<\r\n string,\r\n { surfaceKind: SurfaceKind; name: string; tokens: number }\r\n >();\r\n for (const connector of opts.connectors ?? []) {\r\n for (const fp of computeSurfaceFootprints(connector)) {\r\n const key = `${fp.surfaceKind} ${fp.name}`;\r\n const existing = staticRows.get(key);\r\n if (existing === undefined) {\r\n staticRows.set(key, { surfaceKind: fp.surfaceKind, name: fp.name, tokens: fp.tokens });\r\n } else {\r\n existing.tokens += fp.tokens;\r\n }\r\n }\r\n }\r\n // A pure tokenizer footprint carries no host-reported truth — label it with the\r\n // tokenizer source the connector's family would yield. We derive that once via\r\n // a throwaway count so the static confidence is honest (approx vs exact).\r\n const staticConfidence: ConfidenceSource = staticFootprintConfidence(opts.connectors ?? []);\r\n for (const s of staticRows.values()) {\r\n rows.push({\r\n surfaceKind: s.surfaceKind,\r\n name: s.name,\r\n kind: \"static\",\r\n calls: 0,\r\n inputTokens: s.tokens,\r\n outputTokens: 0,\r\n totalTokens: s.tokens,\r\n confidence: staticConfidence,\r\n lastTs: 0,\r\n });\r\n }\r\n\r\n rows.sort((a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs);\r\n return rows;\r\n}\r\n\r\n/**\r\n * The confidence label for the static footprints: the tokenizer source for the\r\n * first connector's family (exact for openai, approx otherwise). Defaults to\r\n * `tokenizer-approx` when no connector is supplied — an honest estimate label.\r\n */\r\nfunction staticFootprintConfidence(\r\n connectors: readonly ResolvedConnector[],\r\n): ConfidenceSource {\r\n const first = connectors[0];\r\n if (first === undefined) return \"tokenizer-approx\";\r\n // openai family → exact BPE; everything else → approx. Mirrors tokenizer.bpeSource.\r\n return first.telemetry.modelFamilyHint === \"openai\"\r\n ? \"tokenizer-exact\"\r\n : \"tokenizer-approx\";\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Formatting (mirrors telemetry/report.ts: aligned table + honesty legend)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Sources whose counts are estimates (vs real / host-reported numbers).\r\n * `tokenizer-calibrated` is still an estimate — an approximation nudged toward\r\n * truth by a sampled Anthropic count_tokens factor — so it belongs here too.\r\n */\r\nconst ESTIMATE_SOURCES: ReadonlySet<ConfidenceSource> = new Set<ConfidenceSource>([\r\n \"heuristic\",\r\n \"tokenizer-approx\",\r\n \"tokenizer-calibrated\",\r\n]);\r\n\r\n/** Compact integer formatting with thousands separators. */\r\nfunction fmtInt(n: number): string {\r\n return n.toLocaleString(\"en-US\");\r\n}\r\n\r\n/** Right-pad (left-aligned columns). */\r\nfunction padRight(s: string, width: number): string {\r\n return s.length >= width ? s : s + \" \".repeat(width - s.length);\r\n}\r\n\r\n/** Left-pad (right-aligned numeric columns). */\r\nfunction padLeft(s: string, width: number): string {\r\n return s.length >= width ? s : \" \".repeat(width - s.length) + s;\r\n}\r\n\r\n/**\r\n * Render an aligned table given headers, the data cells, and which columns are\r\n * left-aligned (text) vs right-aligned (numbers). Adds rule lines and a TOTAL\r\n * footer. Shared by every leaderboard formatter for one consistent style.\r\n */\r\nfunction renderTable(\r\n headers: string[],\r\n dataRows: string[][],\r\n leftAlignedCols: ReadonlySet<number>,\r\n totalRow: string[],\r\n emptyMessage: string,\r\n): string[] {\r\n const widths = headers.map((h, col) => {\r\n let w = h.length;\r\n for (const row of dataRows) w = Math.max(w, (row[col] ?? \"\").length);\r\n w = Math.max(w, (totalRow[col] ?? \"\").length);\r\n return w;\r\n });\r\n\r\n const renderRow = (cells: string[]): string =>\r\n cells\r\n .map((c, col) =>\r\n leftAlignedCols.has(col)\r\n ? padRight(c, widths[col] ?? 0)\r\n : padLeft(c, widths[col] ?? 0),\r\n )\r\n .join(\" \")\r\n .trimEnd();\r\n\r\n const ruleWidth = widths.reduce((a, b) => a + b, 0) + 2 * (widths.length - 1);\r\n const rule = \"-\".repeat(ruleWidth);\r\n\r\n const lines: string[] = [];\r\n lines.push(renderRow(headers));\r\n lines.push(rule);\r\n if (dataRows.length === 0) {\r\n lines.push(emptyMessage);\r\n } else {\r\n for (const row of dataRows) lines.push(renderRow(row));\r\n }\r\n lines.push(rule);\r\n lines.push(renderRow(totalRow));\r\n return lines;\r\n}\r\n\r\n/** Append the estimate legend when any row carries an estimate confidence. */\r\nfunction appendEstimateLegend(\r\n lines: string[],\r\n confidences: ConfidenceSource[],\r\n): void {\r\n if (confidences.some((c) => ESTIMATE_SOURCES.has(c))) {\r\n lines.push(\"\");\r\n lines.push(\r\n \"note: heuristic and tokenizer-approx token counts are estimates, \" +\r\n \"not exact host-reported usage.\",\r\n );\r\n if (confidences.some((c) => c === \"tokenizer-calibrated\")) {\r\n lines.push(\r\n \"note: tokenizer-calibrated = local approx adjusted by a sampled \" +\r\n \"Anthropic count_tokens factor (opt-in; content sampled off-box only \" +\r\n \"when AGENT_CONNECTOR_CALIBRATE=anthropic).\",\r\n );\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Format the MCP/plugin leaderboard as an aligned table:\r\n * RANK | CONNECTOR | CALLS | TOOLS | IN | OUT | TOTAL | HOSTS | CONFIDENCE\r\n * sorted by total tokens desc, with a TOTAL footer and the honesty legend.\r\n */\r\nexport function formatMcpLeaderboard(rows: McpLeaderboardRow[]): string {\r\n const sorted = [...rows].sort(\r\n (a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs,\r\n );\r\n const headers = [\r\n \"RANK\",\r\n \"CONNECTOR\",\r\n \"CALLS\",\r\n \"TOOLS\",\r\n \"IN\",\r\n \"OUT\",\r\n \"TOTAL\",\r\n \"HOSTS\",\r\n \"CONFIDENCE\",\r\n ];\r\n const dataRows = sorted.map((r, i) => [\r\n `${i + 1}`,\r\n r.connectorId,\r\n fmtInt(r.calls),\r\n fmtInt(r.tools),\r\n fmtInt(r.inputTokens),\r\n fmtInt(r.outputTokens),\r\n fmtInt(r.totalTokens),\r\n r.hostPlatforms.length === 0 ? \"-\" : r.hostPlatforms.join(\",\"),\r\n r.confidence,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.calls += r.calls;\r\n acc.inputTokens += r.inputTokens;\r\n acc.outputTokens += r.outputTokens;\r\n acc.totalTokens += r.totalTokens;\r\n return acc;\r\n },\r\n { calls: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0 },\r\n );\r\n const totalRow = [\r\n \"\",\r\n \"TOTAL\",\r\n fmtInt(totals.calls),\r\n \"\",\r\n fmtInt(totals.inputTokens),\r\n fmtInt(totals.outputTokens),\r\n fmtInt(totals.totalTokens),\r\n \"\",\r\n \"\",\r\n ];\r\n\r\n // Left-align RANK (0), CONNECTOR (1), HOSTS (7), CONFIDENCE (8); numbers right.\r\n const leftCols = new Set<number>([0, 1, 7, 8]);\r\n const lines = renderTable(\r\n headers,\r\n dataRows,\r\n leftCols,\r\n totalRow,\r\n \"(no MCP telemetry recorded)\",\r\n );\r\n appendEstimateLegend(\r\n lines,\r\n sorted.map((r) => r.confidence),\r\n );\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format the per-tool leaderboard:\r\n * RANK | CONNECTOR | TOOL | SCOPE | CALLS | IN | OUT | TOTAL | CONFIDENCE\r\n * sorted by total tokens desc, with a TOTAL footer and the honesty legend.\r\n */\r\nexport function formatToolLeaderboard(rows: ToolLeaderboardRow[]): string {\r\n const sorted = [...rows].sort(\r\n (a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs,\r\n );\r\n const headers = [\r\n \"RANK\",\r\n \"CONNECTOR\",\r\n \"TOOL\",\r\n \"SCOPE\",\r\n \"CALLS\",\r\n \"IN\",\r\n \"OUT\",\r\n \"TOTAL\",\r\n \"CONFIDENCE\",\r\n ];\r\n const dataRows = sorted.map((r, i) => [\r\n `${i + 1}`,\r\n r.connectorId,\r\n r.toolName,\r\n r.scope,\r\n fmtInt(r.calls),\r\n fmtInt(r.inputTokens),\r\n fmtInt(r.outputTokens),\r\n fmtInt(r.totalTokens),\r\n r.confidence,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.calls += r.calls;\r\n acc.inputTokens += r.inputTokens;\r\n acc.outputTokens += r.outputTokens;\r\n acc.totalTokens += r.totalTokens;\r\n return acc;\r\n },\r\n { calls: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0 },\r\n );\r\n const totalRow = [\r\n \"\",\r\n \"TOTAL\",\r\n \"\",\r\n \"\",\r\n fmtInt(totals.calls),\r\n fmtInt(totals.inputTokens),\r\n fmtInt(totals.outputTokens),\r\n fmtInt(totals.totalTokens),\r\n \"\",\r\n ];\r\n\r\n // Left-align RANK (0), CONNECTOR (1), TOOL (2), SCOPE (3), CONFIDENCE (8).\r\n const leftCols = new Set<number>([0, 1, 2, 3, 8]);\r\n const lines = renderTable(\r\n headers,\r\n dataRows,\r\n leftCols,\r\n totalRow,\r\n \"(no MCP telemetry recorded)\",\r\n );\r\n appendEstimateLegend(\r\n lines,\r\n sorted.map((r) => r.confidence),\r\n );\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format the scope breakdown:\r\n * INSTALL | LAUNCH | CALLS | IN | OUT | TOTAL | CONFIDENCE\r\n * with a TOTAL footer and the honesty legend.\r\n */\r\nexport function formatScopeBreakdown(rows: ScopeBreakdownRow[]): string {\r\n const sorted = [...rows].sort(\r\n (a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs,\r\n );\r\n const headers = [\"INSTALL\", \"LAUNCH\", \"CALLS\", \"IN\", \"OUT\", \"TOTAL\", \"CONFIDENCE\"];\r\n const dataRows = sorted.map((r) => [\r\n r.installScope,\r\n r.launchMethod,\r\n fmtInt(r.calls),\r\n fmtInt(r.inputTokens),\r\n fmtInt(r.outputTokens),\r\n fmtInt(r.totalTokens),\r\n r.confidence,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.calls += r.calls;\r\n acc.inputTokens += r.inputTokens;\r\n acc.outputTokens += r.outputTokens;\r\n acc.totalTokens += r.totalTokens;\r\n return acc;\r\n },\r\n { calls: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0 },\r\n );\r\n const totalRow = [\r\n \"TOTAL\",\r\n \"\",\r\n fmtInt(totals.calls),\r\n fmtInt(totals.inputTokens),\r\n fmtInt(totals.outputTokens),\r\n fmtInt(totals.totalTokens),\r\n \"\",\r\n ];\r\n\r\n // Left-align INSTALL (0), LAUNCH (1), CONFIDENCE (6); numbers right-aligned.\r\n const leftCols = new Set<number>([0, 1, 6]);\r\n const lines = renderTable(\r\n headers,\r\n dataRows,\r\n leftCols,\r\n totalRow,\r\n \"(no MCP telemetry recorded)\",\r\n );\r\n appendEstimateLegend(\r\n lines,\r\n sorted.map((r) => r.confidence),\r\n );\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format the host-native turns aggregation (the THIRD origin):\r\n * RANK | HOST | SESSION | TURNS | IN | OUT | TOTAL | CONNECTORS | CONFIDENCE\r\n * sorted by total tokens desc, with a TOTAL footer. These are whole-conversation,\r\n * host-reported (exact) counts — a DIFFERENT thing than the per-MCP rows, so the\r\n * footer total is for THIS section alone and is never added to the others.\r\n */\r\nexport function formatHostNativeTurns(rows: HostNativeTurnsRow[]): string {\r\n const sorted = [...rows].sort(\r\n (a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs,\r\n );\r\n const headers = [\r\n \"RANK\",\r\n \"HOST\",\r\n \"SESSION\",\r\n \"TURNS\",\r\n \"IN\",\r\n \"OUT\",\r\n \"TOTAL\",\r\n \"CONNECTORS\",\r\n \"CONFIDENCE\",\r\n ];\r\n const dataRows = sorted.map((r, i) => [\r\n `${i + 1}`,\r\n r.hostPlatform,\r\n r.sessionId === \"\" ? \"-\" : r.sessionId,\r\n fmtInt(r.turns),\r\n fmtInt(r.inputTokens),\r\n fmtInt(r.outputTokens),\r\n fmtInt(r.totalTokens),\r\n r.connectors.length === 0 ? \"-\" : r.connectors.join(\",\"),\r\n r.confidence,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.turns += r.turns;\r\n acc.inputTokens += r.inputTokens;\r\n acc.outputTokens += r.outputTokens;\r\n acc.totalTokens += r.totalTokens;\r\n return acc;\r\n },\r\n { turns: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0 },\r\n );\r\n const totalRow = [\r\n \"\",\r\n \"TOTAL\",\r\n \"\",\r\n fmtInt(totals.turns),\r\n fmtInt(totals.inputTokens),\r\n fmtInt(totals.outputTokens),\r\n fmtInt(totals.totalTokens),\r\n \"\",\r\n \"\",\r\n ];\r\n\r\n // Left-align RANK (0), HOST (1), SESSION (2), CONNECTORS (7), CONFIDENCE (8).\r\n const leftCols = new Set<number>([0, 1, 2, 7, 8]);\r\n const lines = renderTable(\r\n headers,\r\n dataRows,\r\n leftCols,\r\n totalRow,\r\n \"(no host-native turns recorded — enable opt-in host-native usage)\",\r\n );\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Format the per-surface developer breakdown:\r\n * SURFACE | NAME | IN | OUT | TOTAL | KIND\r\n * one row per (surfaceKind, name) across all FIVE surfaces — server + hook\r\n * (runtime, measured from the store) and command/skill/subagent (static\r\n * footprints). Sorted by total tokens desc, with a TOTAL footer and the honesty\r\n * legend (static footprints + any estimate-confidence runtime rows).\r\n *\r\n * NOTE: the TOTAL footer sums BOTH runtime and static tokens for at-a-glance\r\n * scale; the KIND column keeps the distinction explicit so the two are never\r\n * silently conflated (runtime = live usage; static = context-load footprint).\r\n */\r\nexport function formatSurfaceLeaderboard(rows: SurfaceLeaderboardRow[]): string {\r\n const sorted = [...rows].sort(\r\n (a, b) => b.totalTokens - a.totalTokens || b.lastTs - a.lastTs,\r\n );\r\n const headers = [\"SURFACE\", \"NAME\", \"IN\", \"OUT\", \"TOTAL\", \"KIND\"];\r\n const dataRows = sorted.map((r) => [\r\n r.surfaceKind,\r\n r.name,\r\n fmtInt(r.inputTokens),\r\n fmtInt(r.outputTokens),\r\n fmtInt(r.totalTokens),\r\n r.kind,\r\n ]);\r\n\r\n const totals = sorted.reduce(\r\n (acc, r) => {\r\n acc.inputTokens += r.inputTokens;\r\n acc.outputTokens += r.outputTokens;\r\n acc.totalTokens += r.totalTokens;\r\n return acc;\r\n },\r\n { inputTokens: 0, outputTokens: 0, totalTokens: 0 },\r\n );\r\n const totalRow = [\r\n \"TOTAL\",\r\n \"\",\r\n fmtInt(totals.inputTokens),\r\n fmtInt(totals.outputTokens),\r\n fmtInt(totals.totalTokens),\r\n \"\",\r\n ];\r\n\r\n // Left-align SURFACE (0), NAME (1), KIND (5); numbers right-aligned.\r\n const leftCols = new Set<number>([0, 1, 5]);\r\n const lines = renderTable(\r\n headers,\r\n dataRows,\r\n leftCols,\r\n totalRow,\r\n \"(no developer surfaces recorded)\",\r\n );\r\n if (sorted.some((r) => r.kind === \"static\")) {\r\n lines.push(\"\");\r\n lines.push(\r\n \"note: KIND=static rows are the tokenized FOOTPRINT a command/skill/subagent \" +\r\n \"imposes on a host that loads it as context — not intercepted usage rows.\",\r\n );\r\n }\r\n appendEstimateLegend(\r\n lines,\r\n sorted.map((r) => r.confidence),\r\n );\r\n return lines.join(\"\\n\");\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/ids.ts","../src/core/paths.ts"],"sourcesContent":["/** Shared connector-id grammar for author-time configs and runtime ids. */\r\nexport const CONNECTOR_ID_RE = /^[a-z0-9][a-z0-9-]*$/;\r\n\r\nexport function isValidConnectorId(id: unknown): id is string {\r\n return typeof id === \"string\" && CONNECTOR_ID_RE.test(id);\r\n}\r\n\r\nexport function assertConnectorId(id: unknown, label = \"connector id\"): string {\r\n if (isValidConnectorId(id)) return id;\r\n throw new Error(\r\n `${label} must be kebab-case matching ${CONNECTOR_ID_RE} (got ${JSON.stringify(id)})`,\r\n );\r\n}\r\n","/**\r\n * core/paths — home data-root, stable home binary, and project identity.\r\n *\r\n * Operating model (docs/ARCHITECTURE.md §3):\r\n * • One home data-root holds the single binary + shared telemetry + state.\r\n * Override with AGENT_CONNECTOR_DATA_DIR (the cross-agent shared-DB key).\r\n * This relocates FRAMEWORK state only — never platform-native config files.\r\n * • The home binary lives at a STABLE path so every host's pointer config\r\n * keeps working across updates (no versioned cache dir → no cache-heal bug).\r\n * • Per-project data is keyed by a stable project identity (git remote ||\r\n * normalized absolute path), hashed — not by code location.\r\n */\r\n\r\nimport { createHash } from \"node:crypto\";\r\nimport {\r\n chmodSync,\r\n existsSync,\r\n lstatSync,\r\n mkdirSync,\r\n readFileSync,\r\n writeFileSync,\r\n} from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { basename, isAbsolute, join, parse, relative, resolve, sep } from \"node:path\";\r\n\r\nimport { assertConnectorId } from \"./ids.js\";\r\n\r\n/** The built-in default framework data-root (`~/.agent-connector`), ignoring\r\n * any AGENT_CONNECTOR_DATA_DIR override. */\r\nexport function defaultDataRoot(): string {\r\n return join(homedir(), \".agent-connector\");\r\n}\r\n\r\n/** Framework data-root: AGENT_CONNECTOR_DATA_DIR || ~/.agent-connector. */\r\nexport function dataRoot(): string {\r\n const override = process.env.AGENT_CONNECTOR_DATA_DIR;\r\n if (override && override.trim() !== \"\") return resolve(override);\r\n return defaultDataRoot();\r\n}\r\n\r\n/**\r\n * True when `root` is a NON-DEFAULT data root — i.e. it differs from the\r\n * built-in `~/.agent-connector`. Compared after `resolve()` so two spellings of\r\n * the same dir read as equal. Used at install time to decide whether the\r\n * telemetry serve-wrap must carry an explicit `--data-dir` flag: a default-root\r\n * install relies on the (correct) fallback and stays flag-free, but an overridden\r\n * root must be passed explicitly because some hosts (codex) strip the child env,\r\n * so the spawned `serve` would otherwise resolve the default root and fail to\r\n * find the connector record written under the overridden one.\r\n */\r\nexport function isNonDefaultDataRoot(root: string): boolean {\r\n return resolve(root) !== resolve(defaultDataRoot());\r\n}\r\n\r\nexport function connectorsDir(): string {\r\n return join(dataRoot(), \"connectors\");\r\n}\r\n/**\r\n * Stable cache root for REMOTE connector sources fetched by `install <source>`\r\n * (one subdir per `<owner>__<repo>[__<ref>]`). Lives under the data-root — NOT a\r\n * temp dir — so a fetched connector whose server is a LOCAL stdio command\r\n * (`node <path-in-the-clone>`) keeps resolving after install across reboots.\r\n */\r\nexport function sourcesDir(): string {\r\n return join(dataRoot(), \"sources\");\r\n}\r\nexport function connectorDir(id: string): string {\r\n const root = resolve(connectorsDir());\r\n const safeId = assertConnectorId(id);\r\n const dir = resolve(root, safeId);\r\n const rel = relative(root, dir);\r\n if (rel === \"\" || rel.startsWith(\"..\") || isAbsolute(rel)) {\r\n throw new Error(`connector record path escapes ${root}: ${id}`);\r\n }\r\n return dir;\r\n}\r\nexport function backupsDir(): string {\r\n return join(dataRoot(), \"backups\");\r\n}\r\nexport function logsDir(): string {\r\n return join(dataRoot(), \"logs\");\r\n}\r\n\r\n/** Telemetry store path for the selected backend. */\r\nexport function telemetryPath(store: \"ndjson\" | \"sqlite\" = \"ndjson\"): string {\r\n return join(dataRoot(), store === \"sqlite\" ? \"telemetry.db\" : \"telemetry.ndjson\");\r\n}\r\n\r\n/** Stable, OS-correct path to the single home binary pointer. */\r\nexport function homeBinPath(): string {\r\n const name = process.platform === \"win32\" ? \"agent-connector.cmd\" : \"agent-connector\";\r\n return join(dataRoot(), \"bin\", name);\r\n}\r\n\r\nexport function ensureDir(dir: string): void {\r\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\r\n}\r\n\r\n/**\r\n * Return the first existing symbolic-link component in `path`, or null when the\r\n * existing prefix is symlink-free. Stops at the first missing component so new\r\n * directories/files can still be created normally.\r\n */\r\nexport function firstSymlinkInPath(path: string): string | null {\r\n const abs = resolve(path);\r\n const root = parse(abs).root;\r\n const rest = relative(root, abs);\r\n if (rest === \"\") return null;\r\n\r\n let cur = root;\r\n for (const part of rest.split(sep)) {\r\n if (part === \"\") continue;\r\n cur = join(cur, part);\r\n try {\r\n if (lstatSync(cur).isSymbolicLink()) return cur;\r\n } catch (err) {\r\n const code = (err as NodeJS.ErrnoException).code;\r\n if (code === \"ENOENT\") return null;\r\n throw err;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nexport function assertNoSymlinkInPath(path: string): void {\r\n const symlink = firstSymlinkInPath(path);\r\n if (symlink !== null) {\r\n throw new Error(`${basename(path)} skipped: symbolic link in path (${symlink})`);\r\n }\r\n}\r\n\r\n/**\r\n * Write a stable launcher at homeBinPath() that execs the real CLI entry.\r\n * Avoids symlinks (Windows constraint) and versioned paths. Idempotent.\r\n *\r\n * @param cliEntry absolute path to the installed cli.js\r\n * @param nodePath node runtime to exec with (defaults to current process.execPath)\r\n * @returns the stable launcher path\r\n */\r\nexport function ensureHomeBin(cliEntry: string, nodePath: string = process.execPath): string {\r\n const binPath = homeBinPath();\r\n assertNoSymlinkInPath(binPath);\r\n ensureDir(join(dataRoot(), \"bin\"));\r\n const node = nodePath.replace(/\\\\/g, \"/\");\r\n const cli = cliEntry.replace(/\\\\/g, \"/\");\r\n if (process.platform === \"win32\") {\r\n writeFileSync(binPath, `@echo off\\r\\n\"${node}\" \"${cli}\" %*\\r\\n`, \"utf8\");\r\n } else {\r\n writeFileSync(binPath, `#!/bin/sh\\nexec \"${node}\" \"${cli}\" \"$@\"\\n`, \"utf8\");\r\n chmodSync(binPath, 0o755);\r\n }\r\n return binPath;\r\n}\r\n\r\n/** Read remote.origin.url from a project's .git/config without spawning git. */\r\nfunction gitRemoteUrl(projectDir: string): string | null {\r\n const cfg = join(projectDir, \".git\", \"config\");\r\n if (!existsSync(cfg)) return null;\r\n try {\r\n const text = readFileSync(cfg, \"utf8\");\r\n // Find [remote \"origin\"] ... url = X\r\n const lines = text.split(/\\r?\\n/);\r\n let inOrigin = false;\r\n for (const line of lines) {\r\n const s = line.trim();\r\n if (s.startsWith(\"[\")) inOrigin = /^\\[remote\\s+\"origin\"\\]$/.test(s);\r\n else if (inOrigin) {\r\n const m = s.match(/^url\\s*=\\s*(.+)$/);\r\n if (m && m[1]) return m[1].trim();\r\n }\r\n }\r\n } catch {\r\n /* ignore */\r\n }\r\n return null;\r\n}\r\n\r\nexport interface ProjectIdentity {\r\n /** Hashed stable key used to partition telemetry/state. */\r\n key: string;\r\n /** Human-readable label (git remote or directory name). */\r\n label: string;\r\n /** Absolute project directory. */\r\n dir: string;\r\n}\r\n\r\n/**\r\n * Derive a stable project identity. Prefers the git origin URL (stable across\r\n * clones/locations); falls back to the normalized absolute path.\r\n */\r\nexport function projectIdentity(projectDir: string): ProjectIdentity {\r\n const dir = resolve(projectDir);\r\n const remote = gitRemoteUrl(dir);\r\n const basis = remote ?? dir;\r\n const key = createHash(\"sha256\").update(basis).digest(\"hex\").slice(0, 16);\r\n return { key, label: remote ?? basename(dir), dir };\r\n}\r\n"],"mappings":";;;AACO,IAAM,kBAAkB;AAExB,SAAS,mBAAmB,IAA2B;AAC5D,SAAO,OAAO,OAAO,YAAY,gBAAgB,KAAK,EAAE;AAC1D;AAEO,SAAS,kBAAkB,IAAa,QAAQ,gBAAwB;AAC7E,MAAI,mBAAmB,EAAE,EAAG,QAAO;AACnC,QAAM,IAAI;AAAA,IACR,GAAG,KAAK,gCAAgC,eAAe,SAAS,KAAK,UAAU,EAAE,CAAC;AAAA,EACpF;AACF;;;ACCA,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,eAAe;AACxB,SAAS,UAAU,YAAY,MAAM,OAAO,UAAU,SAAS,WAAW;AAMnE,SAAS,kBAA0B;AACxC,SAAO,KAAK,QAAQ,GAAG,kBAAkB;AAC3C;AAGO,SAAS,WAAmB;AACjC,QAAM,WAAW,QAAQ,IAAI;AAC7B,MAAI,YAAY,SAAS,KAAK,MAAM,GAAI,QAAO,QAAQ,QAAQ;AAC/D,SAAO,gBAAgB;AACzB;AAYO,SAAS,qBAAqB,MAAuB;AAC1D,SAAO,QAAQ,IAAI,MAAM,QAAQ,gBAAgB,CAAC;AACpD;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,SAAS,GAAG,YAAY;AACtC;AAOO,SAAS,aAAqB;AACnC,SAAO,KAAK,SAAS,GAAG,SAAS;AACnC;AACO,SAAS,aAAa,IAAoB;AAC/C,QAAM,OAAO,QAAQ,cAAc,CAAC;AACpC,QAAM,SAAS,kBAAkB,EAAE;AACnC,QAAM,MAAM,QAAQ,MAAM,MAAM;AAChC,QAAM,MAAM,SAAS,MAAM,GAAG;AAC9B,MAAI,QAAQ,MAAM,IAAI,WAAW,IAAI,KAAK,WAAW,GAAG,GAAG;AACzD,UAAM,IAAI,MAAM,iCAAiC,IAAI,KAAK,EAAE,EAAE;AAAA,EAChE;AACA,SAAO;AACT;AACO,SAAS,aAAqB;AACnC,SAAO,KAAK,SAAS,GAAG,SAAS;AACnC;AAMO,SAAS,cAAc,QAA6B,UAAkB;AAC3E,SAAO,KAAK,SAAS,GAAG,UAAU,WAAW,iBAAiB,kBAAkB;AAClF;AAGO,SAAS,cAAsB;AACpC,QAAM,OAAO,QAAQ,aAAa,UAAU,wBAAwB;AACpE,SAAO,KAAK,SAAS,GAAG,OAAO,IAAI;AACrC;AAEO,SAAS,UAAU,KAAmB;AAC3C,MAAI,CAAC,WAAW,GAAG,EAAG,WAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAC1D;AAOO,SAAS,mBAAmB,MAA6B;AAC9D,QAAM,MAAM,QAAQ,IAAI;AACxB,QAAM,OAAO,MAAM,GAAG,EAAE;AACxB,QAAM,OAAO,SAAS,MAAM,GAAG;AAC/B,MAAI,SAAS,GAAI,QAAO;AAExB,MAAI,MAAM;AACV,aAAW,QAAQ,KAAK,MAAM,GAAG,GAAG;AAClC,QAAI,SAAS,GAAI;AACjB,UAAM,KAAK,KAAK,IAAI;AACpB,QAAI;AACF,UAAI,UAAU,GAAG,EAAE,eAAe,EAAG,QAAO;AAAA,IAC9C,SAAS,KAAK;AACZ,YAAM,OAAQ,IAA8B;AAC5C,UAAI,SAAS,SAAU,QAAO;AAC9B,YAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,MAAoB;AACxD,QAAM,UAAU,mBAAmB,IAAI;AACvC,MAAI,YAAY,MAAM;AACpB,UAAM,IAAI,MAAM,GAAG,SAAS,IAAI,CAAC,oCAAoC,OAAO,GAAG;AAAA,EACjF;AACF;AAUO,SAAS,cAAc,UAAkB,WAAmB,QAAQ,UAAkB;AAC3F,QAAM,UAAU,YAAY;AAC5B,wBAAsB,OAAO;AAC7B,YAAU,KAAK,SAAS,GAAG,KAAK,CAAC;AACjC,QAAM,OAAO,SAAS,QAAQ,OAAO,GAAG;AACxC,QAAM,MAAM,SAAS,QAAQ,OAAO,GAAG;AACvC,MAAI,QAAQ,aAAa,SAAS;AAChC,kBAAc,SAAS;AAAA,GAAiB,IAAI,MAAM,GAAG;AAAA,GAAY,MAAM;AAAA,EACzE,OAAO;AACL,kBAAc,SAAS;AAAA,QAAoB,IAAI,MAAM,GAAG;AAAA,GAAY,MAAM;AAC1E,cAAU,SAAS,GAAK;AAAA,EAC1B;AACA,SAAO;AACT;AAGA,SAAS,aAAa,YAAmC;AACvD,QAAM,MAAM,KAAK,YAAY,QAAQ,QAAQ;AAC7C,MAAI,CAAC,WAAW,GAAG,EAAG,QAAO;AAC7B,MAAI;AACF,UAAM,OAAO,aAAa,KAAK,MAAM;AAErC,UAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,QAAI,WAAW;AACf,eAAW,QAAQ,OAAO;AACxB,YAAM,IAAI,KAAK,KAAK;AACpB,UAAI,EAAE,WAAW,GAAG,EAAG,YAAW,0BAA0B,KAAK,CAAC;AAAA,eACzD,UAAU;AACjB,cAAM,IAAI,EAAE,MAAM,kBAAkB;AACpC,YAAI,KAAK,EAAE,CAAC,EAAG,QAAO,EAAE,CAAC,EAAE,KAAK;AAAA,MAClC;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAeO,SAAS,gBAAgB,YAAqC;AACnE,QAAM,MAAM,QAAQ,UAAU;AAC9B,QAAM,SAAS,aAAa,GAAG;AAC/B,QAAM,QAAQ,UAAU;AACxB,QAAM,MAAM,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AACxE,SAAO,EAAE,KAAK,OAAO,UAAU,SAAS,GAAG,GAAG,IAAI;AACpD;","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/spawn-child.ts"],"sourcesContent":["/**\r\n * core/spawn-child — the cross-platform child_process.spawn wrapper.\r\n *\r\n * Kept SEPARATE from core/spawn.ts (pure string/path helpers, imported widely\r\n * and early) so that pulling in `node:child_process` here does not perturb the\r\n * module-eval order of test suites that vi.mock(\"node:child_process\").\r\n */\r\n\r\nimport { type ChildProcess, type SpawnOptions, spawn } from \"node:child_process\";\r\n\r\nimport { resolveSpawnCommand } from \"./spawn.js\";\r\n\r\n/**\r\n * Quote one token for a cmd.exe command line: wrap in double quotes, doubling any\r\n * embedded double quote. Sufficient for the paths / package names / flags we\r\n * spawn (connector config, not untrusted end-user input) — we intentionally do\r\n * not escape cmd metacharacters (& | ^ %), which never appear in those tokens.\r\n */\r\nfunction winQuoteArg(s: string): string {\r\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\r\n}\r\n\r\n/**\r\n * Cross-platform child spawn that fixes native-Windows package-runner launches.\r\n * Direct spawn on macOS/Linux. On win32 it routes through\r\n * {@link resolveSpawnCommand}; an `.exe` runs directly, while a `.cmd`/`.bat`\r\n * (npx.cmd, the agent-connector.cmd launcher) is launched via a SINGLE quoted\r\n * command line with `shell: true` — a string rather than an args array, which\r\n * Node requires for a batch file AND which avoids the DEP0190 deprecation that\r\n * `shell: true` + an args array triggers on Node ≥ 24.\r\n */\r\nexport function spawnChild(\r\n command: string,\r\n args: string[],\r\n options: SpawnOptions,\r\n): ChildProcess {\r\n const resolved = resolveSpawnCommand(command);\r\n if (!resolved.needsShell) return spawn(resolved.file, args, options);\r\n const line = [resolved.file, ...args].map(winQuoteArg).join(\" \");\r\n return spawn(line, { ...options, shell: true });\r\n}\r\n"],"mappings":";;;;;;AAQA,SAA+C,aAAa;AAU5D,SAAS,YAAY,GAAmB;AACtC,SAAO,IAAI,EAAE,QAAQ,MAAM,IAAI,CAAC;AAClC;AAWO,SAAS,WACd,SACA,MACA,SACc;AACd,QAAM,WAAW,oBAAoB,OAAO;AAC5C,MAAI,CAAC,SAAS,WAAY,QAAO,MAAM,SAAS,MAAM,MAAM,OAAO;AACnE,QAAM,OAAO,CAAC,SAAS,MAAM,GAAG,IAAI,EAAE,IAAI,WAAW,EAAE,KAAK,GAAG;AAC/D,SAAO,MAAM,MAAM,EAAE,GAAG,SAAS,OAAO,KAAK,CAAC;AAChD;","names":[]}
|