@ken-jo/agent-connector 0.4.95 → 0.4.98
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 +605 -599
- package/dist/{action-Q7GGO4PA.js → action-5JM23CFJ.js} +16 -16
- package/dist/action-5JM23CFJ.js.map +1 -0
- package/dist/{amazon-q-ETMAGY3D.js → amazon-q-LFZNGN27.js} +6 -6
- package/dist/amazon-q-LFZNGN27.js.map +1 -0
- package/dist/{amp-BQZOL5GR.js → amp-CEWOSWQO.js} +4 -4
- package/dist/amp-CEWOSWQO.js.map +1 -0
- package/dist/{amp-67BZONGF.js → amp-S22XTPEQ.js} +7 -7
- package/dist/amp-S22XTPEQ.js.map +1 -0
- package/dist/{antigravity-EA4L225L.js → antigravity-LHFEFNMC.js} +5 -5
- package/dist/antigravity-LHFEFNMC.js.map +1 -0
- package/dist/antigravity-PZXYAO3X.js +18 -0
- package/dist/{antigravity-cli-B2HXZFYQ.js → antigravity-cli-MOKFSWOU.js} +5 -5
- package/dist/antigravity-cli-MOKFSWOU.js.map +1 -0
- package/dist/{antigravity-cli-OM6SC3PE.js → antigravity-cli-PN474FXM.js} +9 -9
- package/dist/antigravity-cli-PN474FXM.js.map +1 -0
- package/dist/audit-2H7E3Z4N.js +311 -0
- package/dist/audit-2H7E3Z4N.js.map +1 -0
- package/dist/{chunk-KHO5WNTP.js → chunk-4GH2KA7V.js} +1 -1
- package/dist/chunk-4GH2KA7V.js.map +1 -0
- package/dist/{chunk-7F5KHLEP.js → chunk-6XWORQM6.js} +4 -4
- package/dist/chunk-6XWORQM6.js.map +1 -0
- package/dist/{chunk-2Y2MZRLP.js → chunk-7C2IPIIB.js} +3 -3
- package/dist/chunk-7C2IPIIB.js.map +1 -0
- package/dist/{chunk-NLE2J5P4.js → chunk-7HHW23AC.js} +29 -29
- package/dist/chunk-7HHW23AC.js.map +1 -0
- package/dist/{chunk-XD7MY6HB.js → chunk-7PSNXUFK.js} +1 -1
- package/dist/chunk-7PSNXUFK.js.map +1 -0
- package/dist/{chunk-YPAXJ7EW.js → chunk-7VSZXOXJ.js} +13 -13
- package/dist/chunk-7VSZXOXJ.js.map +1 -0
- package/dist/{chunk-ISEJWBFF.js → chunk-B6PKHS5I.js} +2 -2
- package/dist/chunk-B6PKHS5I.js.map +1 -0
- package/dist/{chunk-UM5S7DKK.js → chunk-C747DYNT.js} +1 -1
- package/dist/chunk-C747DYNT.js.map +1 -0
- package/dist/{chunk-PW42ZXCB.js → chunk-DOPFBUCX.js} +3 -3
- package/dist/chunk-DOPFBUCX.js.map +1 -0
- package/dist/{chunk-I5UXHIDT.js → chunk-DWZ5IWF4.js} +8 -8
- package/dist/chunk-DWZ5IWF4.js.map +1 -0
- package/dist/{chunk-6WZODR3Z.js → chunk-FJ6F5U3W.js} +5 -5
- package/dist/chunk-FJ6F5U3W.js.map +1 -0
- package/dist/{chunk-H33M77DD.js → chunk-HATCOSQT.js} +22 -19
- package/dist/chunk-HATCOSQT.js.map +1 -0
- package/dist/{chunk-UMQ6NBQR.js → chunk-ILWHLGIC.js} +2 -2
- package/dist/chunk-ILWHLGIC.js.map +1 -0
- package/dist/{chunk-IVAWP6HH.js → chunk-IOJDZJ72.js} +2 -2
- package/dist/chunk-IOJDZJ72.js.map +1 -0
- package/dist/{chunk-NBYKLUF6.js → chunk-KFPSJRHR.js} +2 -2
- package/dist/chunk-KFPSJRHR.js.map +1 -0
- package/dist/{chunk-O7SDRBVB.js → chunk-KM2YXO6V.js} +1 -1
- package/dist/chunk-KM2YXO6V.js.map +1 -0
- package/dist/{chunk-3NH2ARIS.js → chunk-KTBAB556.js} +6 -6
- package/dist/chunk-KTBAB556.js.map +1 -0
- package/dist/{chunk-5IOTP7LQ.js → chunk-KWC5DQ5Z.js} +7 -5
- package/dist/chunk-KWC5DQ5Z.js.map +1 -0
- package/dist/{chunk-JKKU2WKG.js → chunk-LD5HAN6O.js} +4 -4
- package/dist/chunk-LD5HAN6O.js.map +1 -0
- package/dist/{chunk-OP4KBXUO.js → chunk-LFWYYWLV.js} +1 -1
- package/dist/chunk-LFWYYWLV.js.map +1 -0
- package/dist/{chunk-APZDTY76.js → chunk-LZL2YITN.js} +7 -7
- package/dist/chunk-LZL2YITN.js.map +1 -0
- package/dist/{chunk-H53QZQJI.js → chunk-PSGTHJQU.js} +1 -1
- package/dist/chunk-PSGTHJQU.js.map +1 -0
- package/dist/{chunk-FBJQGRET.js → chunk-Q4ISQHUQ.js} +1 -1
- package/dist/chunk-Q4ISQHUQ.js.map +1 -0
- package/dist/{chunk-6TF7MHG5.js → chunk-Q7PR2WGT.js} +2 -2
- package/dist/chunk-Q7PR2WGT.js.map +1 -0
- package/dist/{chunk-GZGLCCEE.js → chunk-QYOUQCC6.js} +1 -1
- package/dist/chunk-QYOUQCC6.js.map +1 -0
- package/dist/{chunk-Z2MRSS2I.js → chunk-RNVIK5YJ.js} +2 -2
- package/dist/chunk-RNVIK5YJ.js.map +1 -0
- package/dist/{chunk-XC5SJ35F.js → chunk-RPWD5H6Y.js} +5 -5
- package/dist/chunk-RPWD5H6Y.js.map +1 -0
- package/dist/{chunk-PAPMUAR5.js → chunk-S25MVWBP.js} +12 -12
- package/dist/chunk-S25MVWBP.js.map +1 -0
- package/dist/{chunk-FJCUKXGX.js → chunk-THI4PI4H.js} +2 -2
- package/dist/chunk-THI4PI4H.js.map +1 -0
- package/dist/{chunk-D4ELPBB5.js → chunk-TOSNS2BY.js} +43 -43
- package/dist/chunk-TOSNS2BY.js.map +1 -0
- package/dist/{chunk-MGTDQLJJ.js → chunk-UNU2KPYJ.js} +11 -9
- package/dist/chunk-UNU2KPYJ.js.map +1 -0
- package/dist/{chunk-MQPNU2CY.js → chunk-UZZTWWGG.js} +1 -1
- package/dist/chunk-UZZTWWGG.js.map +1 -0
- package/dist/{chunk-4NHXLXSD.js → chunk-W7AGWAMH.js} +2 -2
- package/dist/chunk-W7AGWAMH.js.map +1 -0
- package/dist/{chunk-OPXAP3AC.js → chunk-XN7S44U4.js} +1 -1
- package/dist/chunk-XN7S44U4.js.map +1 -0
- package/dist/{chunk-BEFVJ2OE.js → chunk-XXLCMSD3.js} +1 -1
- package/dist/chunk-XXLCMSD3.js.map +1 -0
- package/dist/{chunk-YT43MUSJ.js → chunk-XZWMJLIT.js} +1 -1
- package/dist/chunk-XZWMJLIT.js.map +1 -0
- package/dist/{chunk-RK6VBLXP.js → chunk-ZSOS2KOR.js} +1 -1
- package/dist/chunk-ZSOS2KOR.js.map +1 -0
- package/dist/{claude-code-NMRKTAP7.js → claude-code-FS42PXZO.js} +4 -4
- package/dist/claude-code-FS42PXZO.js.map +1 -0
- package/dist/{claude-code-GRWO6XBZ.js → claude-code-TA53454O.js} +13 -13
- package/dist/claude-code-TA53454O.js.map +1 -0
- package/dist/cli/sdk.js +9 -8
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{cline-25KW25IN.js → cline-GZFN32BM.js} +6 -6
- package/dist/cline-GZFN32BM.js.map +1 -0
- package/dist/{codebuddy-ZNYQACMF.js → codebuddy-IYS3TQZ3.js} +7 -7
- package/dist/codebuddy-IYS3TQZ3.js.map +1 -0
- package/dist/{codebuff-ETYT5UBL.js → codebuff-6KWBW6CT.js} +4 -4
- package/dist/codebuff-6KWBW6CT.js.map +1 -0
- package/dist/{codebuff-VR6JUDIY.js → codebuff-D3MIKJHC.js} +6 -6
- package/dist/codebuff-D3MIKJHC.js.map +1 -0
- package/dist/{codex-YAORPCOD.js → codex-DKBAAUCO.js} +4 -4
- package/dist/codex-DKBAAUCO.js.map +1 -0
- package/dist/{codex-CPNKTXG3.js → codex-ZKLP5IXZ.js} +9 -9
- package/dist/codex-ZKLP5IXZ.js.map +1 -0
- package/dist/{continue-WU2IB5KS.js → continue-I34FNSTJ.js} +8 -8
- package/dist/continue-I34FNSTJ.js.map +1 -0
- package/dist/{copilot-cli-MZTAWMPW.js → copilot-cli-CLBJACQ5.js} +4 -4
- package/dist/copilot-cli-CLBJACQ5.js.map +1 -0
- package/dist/{copilot-cli-PAP377OM.js → copilot-cli-NWPM5GE6.js} +7 -7
- package/dist/copilot-cli-NWPM5GE6.js.map +1 -0
- package/dist/{crush-QBXLNN7T.js → crush-A5C5USRL.js} +4 -4
- package/dist/crush-A5C5USRL.js.map +1 -0
- package/dist/{crush-3AVQA4YU.js → crush-MDGPZSZU.js} +7 -7
- package/dist/crush-MDGPZSZU.js.map +1 -0
- package/dist/{cursor-DIW43TRZ.js → cursor-D5SWDVSW.js} +3 -3
- package/dist/cursor-D5SWDVSW.js.map +1 -0
- package/dist/cursor-JRVK56QA.js +22 -0
- package/dist/{define-connector-DTWb46UB.d.ts → define-connector-B7tLHVnx.d.ts} +1 -1
- package/dist/{detect-6V4LC3MA.js → detect-FKJC36P4.js} +4 -4
- package/dist/detect-FKJC36P4.js.map +1 -0
- package/dist/{devin-QMEM3OFA.js → devin-TZMRC57O.js} +7 -7
- package/dist/devin-TZMRC57O.js.map +1 -0
- package/dist/{doctor-2YDUVSAU.js → doctor-PGVYUQYG.js} +26 -26
- package/dist/doctor-PGVYUQYG.js.map +1 -0
- package/dist/{droid-U3ZBLQFO.js → droid-PFQ2PZSF.js} +4 -4
- package/dist/droid-PFQ2PZSF.js.map +1 -0
- package/dist/{droid-MOKV53J4.js → droid-SCFWDJR4.js} +7 -7
- package/dist/droid-SCFWDJR4.js.map +1 -0
- package/dist/{gemini-cli-47ZHCOZR.js → gemini-cli-MLDGOR2L.js} +8 -8
- package/dist/gemini-cli-MLDGOR2L.js.map +1 -0
- package/dist/{gemini-cli-NMVVBO3K.js → gemini-cli-Y6RJMU24.js} +4 -4
- package/dist/gemini-cli-Y6RJMU24.js.map +1 -0
- package/dist/{goose-4EI5MYTI.js → goose-5DBHDSJW.js} +9 -9
- package/dist/goose-5DBHDSJW.js.map +1 -0
- package/dist/{goose-64V46Y2W.js → goose-K2HKUTBK.js} +4 -4
- package/dist/goose-K2HKUTBK.js.map +1 -0
- package/dist/{grok-cli-QYQPDSVB.js → grok-cli-LX6Q6RUY.js} +7 -7
- package/dist/grok-cli-LX6Q6RUY.js.map +1 -0
- package/dist/{hermes-F75OSK3Y.js → hermes-LJB3SJKB.js} +7 -7
- package/dist/hermes-LJB3SJKB.js.map +1 -0
- package/dist/{hermes-F3EGTK6N.js → hermes-MF3NX4ZY.js} +4 -4
- package/dist/hermes-MF3NX4ZY.js.map +1 -0
- package/dist/{hook-OEVRDMXD.js → hook-PVGBQUQI.js} +16 -16
- package/dist/hook-PVGBQUQI.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/{install-5NMCUDG5.js → install-HPDIK7F6.js} +192 -28
- package/dist/install-HPDIK7F6.js.map +1 -0
- package/dist/{introspect-dNekqPDY.d.ts → introspect-DWCu0Krk.d.ts} +1 -1
- package/dist/{jetbrains-copilot-ZGIWI6YV.js → jetbrains-copilot-2DSVAJMJ.js} +6 -6
- package/dist/jetbrains-copilot-2DSVAJMJ.js.map +1 -0
- package/dist/{junie-DIFN2P22.js → junie-GUBDRADP.js} +6 -6
- package/dist/junie-GUBDRADP.js.map +1 -0
- package/dist/{kilo-EMZJBEBB.js → kilo-HRLWMENX.js} +8 -8
- package/dist/kilo-HRLWMENX.js.map +1 -0
- package/dist/{kilo-SW7BH6EG.js → kilo-SMHPOHJ5.js} +4 -4
- package/dist/kilo-SMHPOHJ5.js.map +1 -0
- package/dist/{kilo-cli-S3GXBPAE.js → kilo-cli-IQMFMYZF.js} +8 -8
- package/dist/kilo-cli-IQMFMYZF.js.map +1 -0
- package/dist/{kilo-cli-ZF272ZHN.js → kilo-cli-T2SRRRJS.js} +5 -5
- package/dist/kilo-cli-T2SRRRJS.js.map +1 -0
- package/dist/{kimi-IQJOIY6B.js → kimi-EPD46UJK.js} +7 -7
- package/dist/kimi-EPD46UJK.js.map +1 -0
- package/dist/{kimi-5FHEXGZD.js → kimi-MSIDEMCI.js} +4 -4
- package/dist/kimi-MSIDEMCI.js.map +1 -0
- package/dist/{kiro-BYX4HEAJ.js → kiro-A7DL52FX.js} +7 -7
- package/dist/kiro-A7DL52FX.js.map +1 -0
- package/dist/{kiro-WGOI5CGT.js → kiro-NYRRBIKW.js} +4 -4
- package/dist/kiro-NYRRBIKW.js.map +1 -0
- package/dist/{leaderboard-XEKS7B3H.js → leaderboard-KCT7XPCI.js} +7 -7
- package/dist/leaderboard-KCT7XPCI.js.map +1 -0
- package/dist/{mimo-code-7R53QDHB.js → mimo-code-NDGLBXNC.js} +7 -7
- package/dist/mimo-code-NDGLBXNC.js.map +1 -0
- package/dist/{mistral-vibe-LHJ55FSB.js → mistral-vibe-LLWASF5X.js} +6 -6
- package/dist/mistral-vibe-LLWASF5X.js.map +1 -0
- package/dist/{mux-XM6AP35L.js → mux-7PIJ7HUQ.js} +4 -4
- package/dist/mux-7PIJ7HUQ.js.map +1 -0
- package/dist/{mux-NYCNGL43.js → mux-ON4QK3OC.js} +6 -6
- package/dist/mux-ON4QK3OC.js.map +1 -0
- package/dist/{nemoclaw-WSIPSE7U.js → nemoclaw-45R5MFBF.js} +7 -7
- package/dist/nemoclaw-45R5MFBF.js.map +1 -0
- package/dist/{omp-562NK5BJ.js → omp-ROCTFV3A.js} +7 -7
- package/dist/omp-ROCTFV3A.js.map +1 -0
- package/dist/{open-interpreter-I2CNOEXY.js → open-interpreter-V6CN542J.js} +6 -6
- package/dist/open-interpreter-V6CN542J.js.map +1 -0
- package/dist/openclaw-AOKFJGRQ.js +17 -0
- package/dist/{openclaw-5EQFGOWL.js → openclaw-KAFTNLR2.js} +4 -4
- package/dist/openclaw-KAFTNLR2.js.map +1 -0
- package/dist/{opencode-YS4WX2E2.js → opencode-YYWQ45LF.js} +7 -7
- package/dist/opencode-YYWQ45LF.js.map +1 -0
- package/dist/{opencode-QGP4ALQY.js → opencode-Z65JYILL.js} +4 -4
- package/dist/opencode-Z65JYILL.js.map +1 -0
- package/dist/{openhands-QMYIKNOS.js → openhands-OFFMWCQW.js} +7 -7
- package/dist/openhands-OFFMWCQW.js.map +1 -0
- package/dist/{package-G25GVTH2.js → package-TALOSRQ4.js} +15 -15
- package/dist/package-TALOSRQ4.js.map +1 -0
- package/dist/{pi-644FIN3A.js → pi-4W74ETTI.js} +6 -6
- package/dist/pi-4W74ETTI.js.map +1 -0
- package/dist/{pi-GGDQREVG.js → pi-DLKCPOJE.js} +4 -4
- package/dist/pi-DLKCPOJE.js.map +1 -0
- package/dist/{qwen-code-GQILBJ5B.js → qwen-code-26CSFDX6.js} +4 -4
- package/dist/qwen-code-26CSFDX6.js.map +1 -0
- package/dist/{qwen-code-STDMX7EM.js → qwen-code-JOBFNEVT.js} +16 -16
- package/dist/qwen-code-JOBFNEVT.js.map +1 -0
- package/dist/{roo-code-SUWI4BBN.js → roo-code-HSAE2CJU.js} +4 -4
- package/dist/roo-code-HSAE2CJU.js.map +1 -0
- package/dist/{roo-code-DLPIHHQ6.js → roo-code-RHIGJZNY.js} +6 -6
- package/dist/roo-code-RHIGJZNY.js.map +1 -0
- package/dist/runtime/index.d.ts +9 -8
- package/dist/runtime/index.js +14 -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 +11 -11
- package/dist/{serve-XTMIUHKK.js → serve-4TEHK726.js} +16 -16
- package/dist/serve-4TEHK726.js.map +1 -0
- package/dist/{status-VJAGO4Z7.js → status-DVD4EHMX.js} +11 -11
- package/dist/status-DVD4EHMX.js.map +1 -0
- package/dist/{statusline-EY2E2UGF.js → statusline-ZVNH7XBK.js} +15 -15
- package/dist/statusline-ZVNH7XBK.js.map +1 -0
- package/dist/{synthetic-6FRA7P5Q.js → synthetic-LUT6V6SD.js} +4 -4
- package/dist/synthetic-LUT6V6SD.js.map +1 -0
- package/dist/{telemetry-OLZQBADT.js → telemetry-NWUJPIK3.js} +10 -10
- package/dist/telemetry-NWUJPIK3.js.map +1 -0
- package/dist/{trae-CPPYASR2.js → trae-SIQI3C66.js} +4 -4
- package/dist/trae-SIQI3C66.js.map +1 -0
- package/dist/{trae-UOYD6JZZ.js → trae-TLAFSQRQ.js} +6 -6
- package/dist/trae-TLAFSQRQ.js.map +1 -0
- package/dist/{types-JyhpJHJa.d.ts → types-C6j18a6R.d.ts} +13 -14
- package/dist/{uninstall-AZEUPAND.js → uninstall-DZVFV7KE.js} +21 -21
- package/dist/uninstall-DZVFV7KE.js.map +1 -0
- package/dist/{upgrade-CAUUHSSC.js → upgrade-OUE4ED52.js} +21 -21
- package/dist/upgrade-OUE4ED52.js.map +1 -0
- package/dist/{usage-3KHZ4RYZ.js → usage-NT3ZXALZ.js} +4 -4
- package/dist/usage-NT3ZXALZ.js.map +1 -0
- package/dist/{usage-event-TZWOZPRJ.js → usage-event-IELZE6WO.js} +15 -15
- package/dist/usage-event-IELZE6WO.js.map +1 -0
- package/dist/{vscode-copilot-NIMH2DGU.js → vscode-copilot-VZ5XYSTK.js} +7 -7
- package/dist/vscode-copilot-VZ5XYSTK.js.map +1 -0
- package/dist/{warp-NRBBJQR2.js → warp-5YBSP7FP.js} +4 -4
- package/dist/warp-5YBSP7FP.js.map +1 -0
- package/dist/{warp-QYJGKURM.js → warp-P2HWXIKT.js} +6 -6
- package/dist/warp-P2HWXIKT.js.map +1 -0
- package/dist/{windsurf-75LLZ37C.js → windsurf-3JC73GZK.js} +6 -6
- package/dist/windsurf-3JC73GZK.js.map +1 -0
- package/dist/{zed-HKAZXEJW.js → zed-6CMUKXLI.js} +7 -7
- package/dist/zed-6CMUKXLI.js.map +1 -0
- package/dist/{zed-XJFOOKCO.js → zed-XXCNYOIN.js} +4 -4
- package/dist/zed-XXCNYOIN.js.map +1 -0
- package/package.json +92 -88
- package/dist/action-Q7GGO4PA.js.map +0 -1
- package/dist/amazon-q-ETMAGY3D.js.map +0 -1
- package/dist/amp-67BZONGF.js.map +0 -1
- package/dist/amp-BQZOL5GR.js.map +0 -1
- package/dist/antigravity-EA4L225L.js.map +0 -1
- package/dist/antigravity-VXLDLTO7.js +0 -18
- package/dist/antigravity-cli-B2HXZFYQ.js.map +0 -1
- package/dist/antigravity-cli-OM6SC3PE.js.map +0 -1
- package/dist/chunk-2Y2MZRLP.js.map +0 -1
- package/dist/chunk-3NH2ARIS.js.map +0 -1
- package/dist/chunk-4NHXLXSD.js.map +0 -1
- package/dist/chunk-5IOTP7LQ.js.map +0 -1
- package/dist/chunk-6TF7MHG5.js.map +0 -1
- package/dist/chunk-6WZODR3Z.js.map +0 -1
- package/dist/chunk-7F5KHLEP.js.map +0 -1
- package/dist/chunk-APZDTY76.js.map +0 -1
- package/dist/chunk-BEFVJ2OE.js.map +0 -1
- package/dist/chunk-D4ELPBB5.js.map +0 -1
- package/dist/chunk-FBJQGRET.js.map +0 -1
- package/dist/chunk-FJCUKXGX.js.map +0 -1
- package/dist/chunk-GZGLCCEE.js.map +0 -1
- package/dist/chunk-H33M77DD.js.map +0 -1
- package/dist/chunk-H53QZQJI.js.map +0 -1
- package/dist/chunk-I5UXHIDT.js.map +0 -1
- package/dist/chunk-ISEJWBFF.js.map +0 -1
- package/dist/chunk-IVAWP6HH.js.map +0 -1
- package/dist/chunk-JKKU2WKG.js.map +0 -1
- package/dist/chunk-KHO5WNTP.js.map +0 -1
- package/dist/chunk-MGTDQLJJ.js.map +0 -1
- package/dist/chunk-MQPNU2CY.js.map +0 -1
- package/dist/chunk-NBYKLUF6.js.map +0 -1
- package/dist/chunk-NLE2J5P4.js.map +0 -1
- package/dist/chunk-O7SDRBVB.js.map +0 -1
- package/dist/chunk-OP4KBXUO.js.map +0 -1
- package/dist/chunk-OPXAP3AC.js.map +0 -1
- package/dist/chunk-PAPMUAR5.js.map +0 -1
- package/dist/chunk-PW42ZXCB.js.map +0 -1
- package/dist/chunk-RK6VBLXP.js.map +0 -1
- package/dist/chunk-UM5S7DKK.js.map +0 -1
- package/dist/chunk-UMQ6NBQR.js.map +0 -1
- package/dist/chunk-XC5SJ35F.js.map +0 -1
- package/dist/chunk-XD7MY6HB.js.map +0 -1
- package/dist/chunk-YPAXJ7EW.js.map +0 -1
- package/dist/chunk-YT43MUSJ.js.map +0 -1
- package/dist/chunk-Z2MRSS2I.js.map +0 -1
- package/dist/claude-code-GRWO6XBZ.js.map +0 -1
- package/dist/claude-code-NMRKTAP7.js.map +0 -1
- package/dist/cline-25KW25IN.js.map +0 -1
- package/dist/codebuddy-ZNYQACMF.js.map +0 -1
- package/dist/codebuff-ETYT5UBL.js.map +0 -1
- package/dist/codebuff-VR6JUDIY.js.map +0 -1
- package/dist/codex-CPNKTXG3.js.map +0 -1
- package/dist/codex-YAORPCOD.js.map +0 -1
- package/dist/continue-WU2IB5KS.js.map +0 -1
- package/dist/copilot-cli-MZTAWMPW.js.map +0 -1
- package/dist/copilot-cli-PAP377OM.js.map +0 -1
- package/dist/crush-3AVQA4YU.js.map +0 -1
- package/dist/crush-QBXLNN7T.js.map +0 -1
- package/dist/cursor-DIW43TRZ.js.map +0 -1
- package/dist/cursor-GSLUET3V.js +0 -22
- package/dist/detect-6V4LC3MA.js.map +0 -1
- package/dist/devin-QMEM3OFA.js.map +0 -1
- package/dist/doctor-2YDUVSAU.js.map +0 -1
- package/dist/droid-MOKV53J4.js.map +0 -1
- package/dist/droid-U3ZBLQFO.js.map +0 -1
- package/dist/gemini-cli-47ZHCOZR.js.map +0 -1
- package/dist/gemini-cli-NMVVBO3K.js.map +0 -1
- package/dist/goose-4EI5MYTI.js.map +0 -1
- package/dist/goose-64V46Y2W.js.map +0 -1
- package/dist/grok-cli-QYQPDSVB.js.map +0 -1
- package/dist/hermes-F3EGTK6N.js.map +0 -1
- package/dist/hermes-F75OSK3Y.js.map +0 -1
- package/dist/hook-OEVRDMXD.js.map +0 -1
- package/dist/install-5NMCUDG5.js.map +0 -1
- package/dist/jetbrains-copilot-ZGIWI6YV.js.map +0 -1
- package/dist/junie-DIFN2P22.js.map +0 -1
- package/dist/kilo-EMZJBEBB.js.map +0 -1
- package/dist/kilo-SW7BH6EG.js.map +0 -1
- package/dist/kilo-cli-S3GXBPAE.js.map +0 -1
- package/dist/kilo-cli-ZF272ZHN.js.map +0 -1
- package/dist/kimi-5FHEXGZD.js.map +0 -1
- package/dist/kimi-IQJOIY6B.js.map +0 -1
- package/dist/kiro-BYX4HEAJ.js.map +0 -1
- package/dist/kiro-WGOI5CGT.js.map +0 -1
- package/dist/leaderboard-XEKS7B3H.js.map +0 -1
- package/dist/mimo-code-7R53QDHB.js.map +0 -1
- package/dist/mistral-vibe-LHJ55FSB.js.map +0 -1
- package/dist/mux-NYCNGL43.js.map +0 -1
- package/dist/mux-XM6AP35L.js.map +0 -1
- package/dist/nemoclaw-WSIPSE7U.js.map +0 -1
- package/dist/omp-562NK5BJ.js.map +0 -1
- package/dist/open-interpreter-I2CNOEXY.js.map +0 -1
- package/dist/openclaw-5EQFGOWL.js.map +0 -1
- package/dist/openclaw-7EYBQS4R.js +0 -17
- package/dist/opencode-QGP4ALQY.js.map +0 -1
- package/dist/opencode-YS4WX2E2.js.map +0 -1
- package/dist/openhands-QMYIKNOS.js.map +0 -1
- package/dist/package-G25GVTH2.js.map +0 -1
- package/dist/pi-644FIN3A.js.map +0 -1
- package/dist/pi-GGDQREVG.js.map +0 -1
- package/dist/qwen-code-GQILBJ5B.js.map +0 -1
- package/dist/qwen-code-STDMX7EM.js.map +0 -1
- package/dist/roo-code-DLPIHHQ6.js.map +0 -1
- package/dist/roo-code-SUWI4BBN.js.map +0 -1
- package/dist/serve-XTMIUHKK.js.map +0 -1
- package/dist/status-VJAGO4Z7.js.map +0 -1
- package/dist/statusline-EY2E2UGF.js.map +0 -1
- package/dist/synthetic-6FRA7P5Q.js.map +0 -1
- package/dist/telemetry-OLZQBADT.js.map +0 -1
- package/dist/trae-CPPYASR2.js.map +0 -1
- package/dist/trae-UOYD6JZZ.js.map +0 -1
- package/dist/uninstall-AZEUPAND.js.map +0 -1
- package/dist/upgrade-CAUUHSSC.js.map +0 -1
- package/dist/usage-3KHZ4RYZ.js.map +0 -1
- package/dist/usage-event-TZWOZPRJ.js.map +0 -1
- package/dist/vscode-copilot-NIMH2DGU.js.map +0 -1
- package/dist/warp-NRBBJQR2.js.map +0 -1
- package/dist/warp-QYJGKURM.js.map +0 -1
- package/dist/windsurf-75LLZ37C.js.map +0 -1
- package/dist/zed-HKAZXEJW.js.map +0 -1
- package/dist/zed-XJFOOKCO.js.map +0 -1
- /package/dist/{antigravity-VXLDLTO7.js.map → antigravity-PZXYAO3X.js.map} +0 -0
- /package/dist/{cursor-GSLUET3V.js.map → cursor-JRVK56QA.js.map} +0 -0
- /package/dist/{openclaw-7EYBQS4R.js.map → openclaw-AOKFJGRQ.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/telemetry/store.ts","../src/telemetry/types.ts","../src/telemetry/tokenizer.ts"],"sourcesContent":["/**\r\n * telemetry/store — the default NDJSON {@link TelemetryStore} implementation.\r\n *\r\n * Local-first, dependency-free persistence. One JSON object per line; appends\r\n * are atomic enough for concurrent multi-host writers (a single `appendFileSync`\r\n * of a `<line>\\n` chunk is written in one `write(2)` for small payloads, so\r\n * interleaving across processes does not corrupt individual records). A\r\n * SQLite/WAL backend is a drop-in upgrade behind the same interface.\r\n *\r\n * Telemetry stores AGGREGATE COUNTS ONLY — raw tool arguments/results are never\r\n * persisted (enforced by the {@link ToolEventRecord} shape, which carries no\r\n * content fields).\r\n *\r\n * Global kill switch: AGENT_CONNECTOR_TELEMETRY=0 makes `append` a no-op so a\r\n * disabled telemetry layer can never touch disk or break a host's tool call.\r\n */\r\n\r\nimport { appendFileSync, existsSync, readFileSync } from \"node:fs\";\r\nimport { dirname } from \"node:path\";\r\n\r\nimport { ensureDir, telemetryPath } from \"../core/paths.js\";\r\nimport { worstConfidence } from \"./types.js\";\r\nimport type {\r\n QueryFilter,\r\n RollupRow,\r\n TelemetryStore,\r\n ToolEventRecord,\r\n} from \"./types.js\";\r\n\r\n/** Options for {@link openStore}. */\r\nexport interface OpenStoreOptions {\r\n /** Override the NDJSON file path. Defaults to telemetryPath(\"ndjson\"). */\r\n path?: string;\r\n}\r\n\r\n// Confidence ranking + worst-of comparison live in ./types (the single source\r\n// of truth) so a new ConfidenceSource value orders correctly everywhere.\r\n\r\n/** Is `process.env.AGENT_CONNECTOR_TELEMETRY` an explicit off switch? */\r\nfunction telemetryDisabled(): boolean {\r\n return process.env.AGENT_CONNECTOR_TELEMETRY === \"0\";\r\n}\r\n\r\n/**\r\n * A unique-enough record id. Combines the wall clock with a caller-supplied\r\n * sequence so two records written in the same millisecond still differ.\r\n */\r\nexport function newRecordId(seq: number): string {\r\n return `${Date.now()}-${seq}`;\r\n}\r\n\r\nclass NdjsonStore implements TelemetryStore {\r\n private readonly path: string;\r\n\r\n constructor(path: string) {\r\n this.path = path;\r\n }\r\n\r\n append(record: ToolEventRecord): void {\r\n if (telemetryDisabled()) return;\r\n ensureDir(dirname(this.path));\r\n appendFileSync(this.path, `${JSON.stringify(record)}\\n`, \"utf8\");\r\n }\r\n\r\n query(filter: QueryFilter): ToolEventRecord[] {\r\n if (!existsSync(this.path)) return [];\r\n\r\n let text: string;\r\n try {\r\n text = readFileSync(this.path, \"utf8\");\r\n } catch {\r\n return [];\r\n }\r\n\r\n const out: ToolEventRecord[] = [];\r\n for (const line of text.split(\"\\n\")) {\r\n const trimmed = line.trim();\r\n if (trimmed === \"\") continue;\r\n\r\n let record: ToolEventRecord;\r\n try {\r\n record = JSON.parse(trimmed) as ToolEventRecord;\r\n } catch {\r\n continue; // skip malformed lines\r\n }\r\n\r\n if (matches(record, filter)) out.push(record);\r\n }\r\n return out;\r\n }\r\n\r\n rollup(by: \"tool\" | \"session\" | \"project\", filter: QueryFilter): RollupRow[] {\r\n const groups = new Map<string, RollupRow>();\r\n\r\n for (const record of this.query(filter)) {\r\n const key = groupKey(record, by);\r\n const existing = groups.get(key);\r\n if (existing === undefined) {\r\n groups.set(key, {\r\n key,\r\n calls: 1,\r\n inputTokens: record.inputTokens,\r\n outputTokens: record.outputTokens,\r\n totalTokens: record.inputTokens + record.outputTokens,\r\n confidence: record.confidenceSource,\r\n lastTs: record.ts,\r\n });\r\n } else {\r\n existing.calls += 1;\r\n existing.inputTokens += record.inputTokens;\r\n existing.outputTokens += record.outputTokens;\r\n existing.totalTokens += record.inputTokens + record.outputTokens;\r\n existing.confidence = worstConfidence(\r\n existing.confidence,\r\n record.confidenceSource,\r\n );\r\n if (record.ts > existing.lastTs) existing.lastTs = record.ts;\r\n }\r\n }\r\n\r\n return [...groups.values()];\r\n }\r\n\r\n close(): void {\r\n /* no-op for the NDJSON backend */\r\n }\r\n}\r\n\r\n/** Does a record satisfy every set field of the filter? */\r\nfunction matches(record: ToolEventRecord, filter: QueryFilter): boolean {\r\n if (\r\n filter.connectorId !== undefined &&\r\n record.connectorId !== filter.connectorId\r\n ) {\r\n return false;\r\n }\r\n if (\r\n filter.projectKey !== undefined &&\r\n record.projectKey !== filter.projectKey\r\n ) {\r\n return false;\r\n }\r\n if (filter.sessionId !== undefined && record.sessionId !== filter.sessionId) {\r\n return false;\r\n }\r\n if (filter.toolName !== undefined && record.toolName !== filter.toolName) {\r\n return false;\r\n }\r\n if (filter.sinceMs !== undefined && record.ts < filter.sinceMs) {\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/** Resolve the grouping key value for a record under the requested dimension. */\r\nfunction groupKey(\r\n record: ToolEventRecord,\r\n by: \"tool\" | \"session\" | \"project\",\r\n): string {\r\n switch (by) {\r\n case \"tool\":\r\n return record.toolName;\r\n case \"session\":\r\n return record.sessionId;\r\n case \"project\":\r\n return record.projectDir;\r\n }\r\n}\r\n\r\n/**\r\n * Open the default local telemetry store. NDJSON backend; no native deps. The\r\n * returned store is safe to use even when telemetry is disabled — `append`\r\n * becomes a no-op and reads of a missing file return empty results.\r\n */\r\nexport function openStore(opts?: OpenStoreOptions): TelemetryStore {\r\n const path = opts?.path ?? telemetryPath(\"ndjson\");\r\n return new NdjsonStore(path);\r\n}\r\n","/**\r\n * telemetry/types — runtime telemetry contracts.\r\n *\r\n * The framework measures the MCP server's OWN bytes (tool args in, tool result\r\n * out, tool-definition schemas) and tokenizes them locally — the only signal\r\n * identical across every host (no host reports per-tool usage to a server).\r\n * Records are aggregate counts only; raw arguments/results are NEVER stored.\r\n */\r\n\r\nimport type { PlatformId } from \"../core/types.js\";\r\n\r\n/** Provenance of a token count — surfaced so \"estimate\" is never read as \"exact\". */\r\nexport type ConfidenceSource =\r\n | \"tokenizer-exact\" // real BPE for a matching model family\r\n | \"tokenizer-calibrated\" // approx adjusted by a sampled Anthropic count_tokens factor\r\n | \"tokenizer-approx\" // real BPE used as a documented approximation (e.g. Anthropic)\r\n | \"heuristic\" // chars/4 fallback\r\n | \"host-native\"; // a host actually reported usage (e.g. Gemini AfterModel)\r\n\r\n/**\r\n * Confidence ranking, least-trustworthy (0) → most-trustworthy. The single\r\n * source of truth for ordering {@link ConfidenceSource} values; every\r\n * worst-of comparison across the telemetry subsystem (store rollup, both\r\n * leaderboards, report, measure) reads through {@link rankOf} /\r\n * {@link worstConfidence} so a new value orders correctly everywhere.\r\n *\r\n * heuristic < tokenizer-approx < tokenizer-calibrated < tokenizer-exact < host-native\r\n *\r\n * `tokenizer-calibrated` sits between the raw approximation and an exact\r\n * family-matched BPE count: it is an approximation nudged toward truth by a\r\n * sampled real count_tokens factor, so it is more trustworthy than bare approx\r\n * but still not the exact encoding for the target family.\r\n */\r\nexport const CONFIDENCE_RANK: Record<ConfidenceSource, number> = {\r\n heuristic: 0,\r\n \"tokenizer-approx\": 1,\r\n \"tokenizer-calibrated\": 2,\r\n \"tokenizer-exact\": 3,\r\n \"host-native\": 4,\r\n};\r\n\r\n/** Trust rank of a single {@link ConfidenceSource} (higher = more trustworthy). */\r\nexport function rankOf(c: ConfidenceSource): number {\r\n return CONFIDENCE_RANK[c];\r\n}\r\n\r\n/** Return whichever source is the worse (least-confident) of the two. */\r\nexport function worstConfidence(\r\n a: ConfidenceSource,\r\n b: ConfidenceSource,\r\n): ConfidenceSource {\r\n return CONFIDENCE_RANK[b] < CONFIDENCE_RANK[a] ? b : a;\r\n}\r\n\r\nexport type ModelFamily = \"openai\" | \"anthropic\" | \"generic\";\r\n\r\nexport interface TokenCount {\r\n tokens: number;\r\n source: ConfidenceSource;\r\n}\r\n\r\n/** Pluggable tokenizer. Default impl uses gpt-tokenizer; fallback is chars/4. */\r\nexport interface Tokenizer {\r\n /** Count tokens for a string under the given model family. */\r\n count(text: string, family: ModelFamily): TokenCount;\r\n /** Count tokens for an arbitrary JSON value (serialized canonically first). */\r\n countValue(value: unknown, family: ModelFamily): TokenCount;\r\n}\r\n\r\n/**\r\n * What a record measures. DISTINCT origins that must never be summed:\r\n * • `call` — one per-MCP `tools/call` round-trip (serve-proxy bytes).\r\n * • `tool_defs` — the one-time `tools/list` schema overhead (serve-proxy).\r\n * • `model_turn` — a WHOLE-CONVERSATION host-native turn reported by the host\r\n * (e.g. Gemini/Antigravity AfterModel `usageMetadata`). This is NOT per-MCP:\r\n * it covers the entire model turn, so the MCP leaderboard EXCLUDES it (just\r\n * as it treats `tool_defs` specially) and it is surfaced as its own labeled\r\n * section rather than added to the per-MCP `call` totals or to the\r\n * usage-reader host-scan numbers.\r\n * • `hook` — one RUNTIME hook dispatch through the home-bin `hook`\r\n * entrypoint (src/runtime/hook-entrypoint). The framework tokenizes the\r\n * inbound normalized event payload the handler reads (input) and what the\r\n * handler returns that becomes context/decision (output). The per-item\r\n * `toolName` is the hook EVENT name (e.g. \"SessionStart\"). This is the\r\n * developer-axis \"hook\" surface — measured live, like `call`.\r\n */\r\nexport type EventScope = \"call\" | \"tool_defs\" | \"model_turn\" | \"hook\";\r\n\r\n/**\r\n * Which of the FIVE developer-axis surfaces a record (or footprint) belongs to.\r\n * `server`/`hook` are RUNTIME-measured surfaces that produce {@link ToolEventRecord}\r\n * store rows; `command`/`skill`/`subagent` are STATIC footprints computed from the\r\n * registered connector (the host loads them as context — we never intercept them,\r\n * so they are NEVER written as usage rows). OPTIONAL on the record so rows written\r\n * before this field existed (every legacy serve-proxy row) read as `server`.\r\n */\r\nexport type SurfaceKind = \"server\" | \"hook\" | \"command\" | \"skill\" | \"subagent\";\r\n\r\n/**\r\n * The install scope a wrapped server was deployed under, narrowed to the two\r\n * dimensions that matter for slicing telemetry: a `user`-global install vs a\r\n * `project`-local one. The framework's broader {@link InstallScope}\r\n * (`system|user|project|profile|managed`) is mapped down to this at wrap time —\r\n * everything that is not project-local reads as `user`. Optional on the record\r\n * so rows written before this field existed are treated as \"unknown\".\r\n */\r\nexport type TelemetryInstallScope = \"user\" | \"project\";\r\n\r\n/**\r\n * How the real MCP server underneath the proxy was launched. `npx`/`bunx`/`uvx`\r\n * are ephemeral package runners; `node`/`bun`/`deno` are interpreters running a\r\n * local script; `binary` is a resolved executable on PATH; `http` marks a remote\r\n * server reached over the network (no local launch); `unknown` is the honest\r\n * fallback. Optional on the record so older rows read as \"unknown\".\r\n */\r\nexport type LaunchMethod =\r\n | \"npx\"\r\n | \"bunx\"\r\n | \"uvx\"\r\n | \"node\"\r\n | \"binary\"\r\n | \"http\"\r\n | \"unknown\";\r\n\r\n/**\r\n * One telemetry row. Aggregate counts only — no content. `projectKey` is the\r\n * hashed stable project identity (git remote || normalized abs path); `projectDir`\r\n * is kept human-readable for reports but is the same partition.\r\n */\r\nexport interface ToolEventRecord {\r\n /** Monotonic-ish unique id (e.g. `${ts}-${seq}`). */\r\n id: string;\r\n /** Epoch milliseconds. */\r\n ts: number;\r\n connectorId: string;\r\n toolName: string;\r\n scope: EventScope;\r\n hostPlatform: PlatformId;\r\n sessionId: string;\r\n projectKey: string;\r\n projectDir: string;\r\n inputTokens: number;\r\n outputTokens: number;\r\n confidenceSource: ConfidenceSource;\r\n isError: boolean;\r\n /**\r\n * The (narrowed) install scope the wrapped server was deployed under — a\r\n * slicing dimension for global(user) vs project usage. OPTIONAL: rows written\r\n * before this field existed lack it and must be read as \"unknown\".\r\n */\r\n installScope?: TelemetryInstallScope;\r\n /**\r\n * How the real server was launched (npx/bunx/uvx/node/binary/http) — the\r\n * \"launch-method\" slicing dimension. OPTIONAL: older rows lack it → \"unknown\".\r\n */\r\n launchMethod?: LaunchMethod;\r\n /**\r\n * Which developer-axis surface produced this row. OPTIONAL and\r\n * backward-compatible: rows written before this field existed (every legacy\r\n * serve-proxy `call`/`tool_defs` row) lack it and MUST be read as `server`.\r\n * Runtime rows stamp it explicitly (`server` for the proxy, `hook` for the\r\n * hook runtime); the static command/skill/subagent surfaces never produce\r\n * store rows (they are reported as footprints — see surface-footprint.ts).\r\n */\r\n surfaceKind?: SurfaceKind;\r\n}\r\n\r\nexport interface QueryFilter {\r\n connectorId?: string;\r\n projectKey?: string;\r\n sessionId?: string;\r\n toolName?: string;\r\n /** Lower bound epoch ms (inclusive). */\r\n sinceMs?: number;\r\n}\r\n\r\n/** A grouped rollup row for reports. */\r\nexport interface RollupRow {\r\n /** The grouping key value (tool name, session id, or project dir). */\r\n key: string;\r\n calls: number;\r\n inputTokens: number;\r\n outputTokens: number;\r\n totalTokens: number;\r\n /** Worst (least-confident) source seen in the group, for honest labeling. */\r\n confidence: ConfidenceSource;\r\n lastTs: number;\r\n}\r\n\r\n/**\r\n * Local-first telemetry store. The default NDJSON implementation appends one\r\n * line per record (append is atomic enough for concurrent multi-host writers);\r\n * a SQLite/WAL implementation is a drop-in upgrade behind this same interface.\r\n */\r\nexport interface TelemetryStore {\r\n append(record: ToolEventRecord): void;\r\n query(filter: QueryFilter): ToolEventRecord[];\r\n /** Group + aggregate by tool | session | project. */\r\n rollup(by: \"tool\" | \"session\" | \"project\", filter: QueryFilter): RollupRow[];\r\n close(): void;\r\n}\r\n","/**\r\n * telemetry/tokenizer — the default {@link Tokenizer} implementation.\r\n *\r\n * Token counts are the only signal that is identical across every host: no host\r\n * reports a server's per-tool usage back to the server, so the framework\r\n * tokenizes its OWN bytes locally. We use gpt-tokenizer's `o200k_base` encoding\r\n * (the GPT-4o / o1 BPE) for all families:\r\n * • openai → exact BPE for the target family → \"tokenizer-exact\"\r\n * • anthropic → o200k_base used as a documented stand-in → \"tokenizer-approx\"\r\n * • generic → o200k_base used as a generic approximation → \"tokenizer-approx\"\r\n *\r\n * gpt-tokenizer is loaded LAZILY on first use, inside a try/catch. If the module\r\n * (or its BPE data) fails to load we degrade to a chars/4 heuristic that never\r\n * throws, so telemetry can never break a host's tool call.\r\n *\r\n * Pure + side-effect-free apart from the one-time lazy encoder load. No IO.\r\n */\r\n\r\nimport { createRequire } from \"node:module\";\r\n\r\nimport type {\r\n ConfidenceSource,\r\n ModelFamily,\r\n TokenCount,\r\n Tokenizer,\r\n} from \"./types.js\";\r\n\r\n/**\r\n * A CommonJS `require` bound to this module's URL. gpt-tokenizer ships its\r\n * encoding entry points as CJS (the package `exports` `require` condition maps\r\n * `./encoding/*` to `./cjs/encoding/*.js`), so we resolve them synchronously via\r\n * createRequire — this keeps the {@link Tokenizer} surface synchronous and works\r\n * under ESM / NodeNext without baking an absolute path.\r\n */\r\nconst requireCjs = createRequire(import.meta.url);\r\n\r\n/** Minimal shape we use from a gpt-tokenizer encoding module. */\r\ninterface EncodingModule {\r\n encode(text: string): number[];\r\n}\r\n\r\n/**\r\n * Lazy-load state for the shared o200k_base encoder.\r\n * - undefined → not attempted yet\r\n * - null → load attempted and failed (stick to the heuristic)\r\n * - object → loaded encoder\r\n */\r\nlet encoderState: EncodingModule | null | undefined;\r\n\r\n/** Average characters-per-token for the chars/4 fallback heuristic. */\r\nconst HEURISTIC_CHARS_PER_TOKEN = 4;\r\n\r\n/**\r\n * Lazily import the o200k_base encoding. Returns the encoder, or null if the\r\n * module/data could not be loaded (in which case callers use the heuristic).\r\n *\r\n * The dynamic import resolves to `gpt-tokenizer/esm/encoding/o200k_base.js` via\r\n * the package `exports` map and exposes a named `encode(text) => number[]`.\r\n */\r\nfunction loadEncoder(): EncodingModule | null {\r\n if (encoderState !== undefined) return encoderState;\r\n try {\r\n // Synchronous require keeps count() a sync function (per the Tokenizer\r\n // interface). The package's `require` export condition resolves this to\r\n // gpt-tokenizer/cjs/encoding/o200k_base.js, which exports a named `encode`.\r\n const mod = requireCjs(\"gpt-tokenizer/encoding/o200k_base\") as {\r\n encode?: (text: string) => number[];\r\n };\r\n if (mod && typeof mod.encode === \"function\") {\r\n encoderState = { encode: mod.encode.bind(mod) };\r\n } else {\r\n encoderState = null;\r\n }\r\n } catch {\r\n encoderState = null;\r\n }\r\n return encoderState;\r\n}\r\n\r\n/** Heuristic chars/4 count — used when no encoder is available. Never throws. */\r\nfunction heuristicCount(text: string): TokenCount {\r\n return {\r\n tokens: Math.ceil(text.length / HEURISTIC_CHARS_PER_TOKEN),\r\n source: \"heuristic\",\r\n };\r\n}\r\n\r\n/**\r\n * Confidence label for a successful BPE count: exact only for the OpenAI family\r\n * (the encoding actually matches), approximate for everything else.\r\n */\r\nfunction bpeSource(family: ModelFamily): ConfidenceSource {\r\n return family === \"openai\" ? \"tokenizer-exact\" : \"tokenizer-approx\";\r\n}\r\n\r\n/**\r\n * The default tokenizer. A single shared instance is fine: the encoder is\r\n * stateless across calls and lazy-loaded once.\r\n */\r\nclass DefaultTokenizer implements Tokenizer {\r\n count(text: string, family: ModelFamily): TokenCount {\r\n const encoder = loadEncoder();\r\n if (!encoder) return heuristicCount(text);\r\n try {\r\n return { tokens: encoder.encode(text).length, source: bpeSource(family) };\r\n } catch {\r\n // A per-call encode failure (e.g. a pathological input) still degrades\r\n // gracefully rather than breaking the host's tool call.\r\n return heuristicCount(text);\r\n }\r\n }\r\n\r\n countValue(value: unknown, family: ModelFamily): TokenCount {\r\n return this.count(canonicalString(value), family);\r\n }\r\n}\r\n\r\n/**\r\n * Canonical string form of an arbitrary JSON value for counting.\r\n * `undefined` (and anything that JSON.stringify drops to undefined, e.g. a bare\r\n * function or symbol) serializes to the empty string.\r\n */\r\nfunction canonicalString(value: unknown): string {\r\n if (typeof value === \"string\") return value;\r\n const json = JSON.stringify(value);\r\n return json ?? \"\";\r\n}\r\n\r\nconst SHARED_TOKENIZER: Tokenizer = new DefaultTokenizer();\r\n\r\n/** Return the default {@link Tokenizer} (shared singleton). */\r\nexport function getTokenizer(): Tokenizer {\r\n return SHARED_TOKENIZER;\r\n}\r\n\r\n/**\r\n * Infer the {@link ModelFamily} for token counting.\r\n *\r\n * An explicit hint other than \"auto\" wins outright. Otherwise we sniff the\r\n * client/host name: Anthropic/Claude → anthropic, OpenAI/GPT/Codex → openai,\r\n * Gemini and everything unrecognized → generic.\r\n */\r\nexport function inferModelFamily(\r\n clientName: string,\r\n hint: \"auto\" | ModelFamily,\r\n): ModelFamily {\r\n if (hint !== \"auto\") return hint;\r\n const name = clientName.toLowerCase();\r\n if (name.includes(\"claude\") || name.includes(\"anthropic\")) return \"anthropic\";\r\n if (\r\n name.includes(\"codex\") ||\r\n name.includes(\"gpt\") ||\r\n name.includes(\"openai\")\r\n ) {\r\n return \"openai\";\r\n }\r\n // gemini and all others fall through to the generic approximation.\r\n return \"generic\";\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
assertNoSymlinkInPath,
|
|
4
4
|
ensureDir
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QYOUQCC6.js";
|
|
6
6
|
|
|
7
7
|
// src/core/config-patch-ledger.ts
|
|
8
8
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -176,4 +176,4 @@ export {
|
|
|
176
176
|
removeLedgerOwner,
|
|
177
177
|
dropLedgerEntry
|
|
178
178
|
};
|
|
179
|
-
//# sourceMappingURL=chunk-
|
|
179
|
+
//# sourceMappingURL=chunk-KFPSJRHR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/config-patch-ledger.ts"],"sourcesContent":["/**\r\n * core/config-patch-ledger — the persisted, refcounted ownership ledger behind\r\n * the declarative `configPatch` surface, plus the shared configPatch helpers\r\n * (leaf-path grammar, JSON-value checks, the agent-connector namespace guard,\r\n * canonical hashing, and the manual-edit hint every skip-warn prints).\r\n *\r\n * WHY A LEDGER (and not the hooks-style recompute ownership): hook entries\r\n * embed the connector id in their command string, so uninstall can identify\r\n * \"mine\" by inspection. configPatch writes bare host keys (`true` is `true`) —\r\n * not attributable by inspection — and the same key may be needed by SEVERAL\r\n * connectors (a shared host feature flag). Without a persisted refcount,\r\n * connector A uninstalling would delete a key connector B still relies on.\r\n *\r\n * Contract (docs/ARCHITECTURE.md §4 \"configPatch\"):\r\n * • One global file at `<dataRoot>/state/config-patches.json`, written\r\n * ATOMICALLY (temp + rename) — shared across connectors because\r\n * refcounting requires a global view; survives a connector's record purge.\r\n * • Primary key per entry: (platform, file, key). `prior` is ALWAYS\r\n * `{ present: false }` — ownership only ever attaches to keys\r\n * agent-connector itself created (set-if-absent), so the blind\r\n * \"restore prior value\" footgun is structurally impossible.\r\n * • Uninstall removes a key ONLY when the releasing connector is the LAST\r\n * owner AND the current value still deep-equals `writtenValue` AND prior\r\n * was absent; any mismatch → skip-warn and leave the key in place.\r\n * • The ledger is advisory FOR DELETION ONLY: the worst desync outcome is a\r\n * skip-warn and a leftover key, never data loss.\r\n */\r\n\r\nimport { createHash, randomBytes } from \"node:crypto\";\r\nimport {\r\n existsSync,\r\n readFileSync,\r\n renameSync,\r\n rmSync,\r\n writeFileSync,\r\n} from \"node:fs\";\r\nimport { dirname, join } from \"node:path\";\r\n\r\nimport type { ConfigPatchDef, JsonValue, PlatformId } from \"./types.js\";\r\nimport { assertNoSymlinkInPath, ensureDir } from \"./paths.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Shared configPatch helpers (grammar / values / namespace guard / hints)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Grammar for ONE dotted-path segment: no dots-in-key, no array indices. */\r\nexport const CONFIG_PATCH_SEGMENT_RE = /^[A-Za-z0-9_-]+$/;\r\n\r\n/**\r\n * True when `key` is a valid dotted LEAF path: 1+ segments joined by \".\",\r\n * every segment matching {@link CONFIG_PATCH_SEGMENT_RE}.\r\n */\r\nexport function isValidConfigPatchKey(key: unknown): key is string {\r\n if (typeof key !== \"string\" || key.length === 0) return false;\r\n return key.split(\".\").every((seg) => CONFIG_PATCH_SEGMENT_RE.test(seg));\r\n}\r\n\r\n/**\r\n * True when `value` is JSON-serializable data (string / finite number /\r\n * boolean / null / arrays / plain objects thereof). Rejects undefined,\r\n * functions, symbols, bigints, NaN/Infinity (JSON.stringify silently corrupts\r\n * those), and class instances other than plain objects/arrays.\r\n */\r\nexport function isJsonValue(value: unknown): value is JsonValue {\r\n if (value === null) return true;\r\n switch (typeof value) {\r\n case \"string\":\r\n case \"boolean\":\r\n return true;\r\n case \"number\":\r\n return Number.isFinite(value);\r\n case \"object\":\r\n break;\r\n default:\r\n return false;\r\n }\r\n if (Array.isArray(value)) return value.every((v) => isJsonValue(v));\r\n const proto = Object.getPrototypeOf(value);\r\n if (proto !== Object.prototype && proto !== null) return false;\r\n return Object.values(value as Record<string, unknown>).every((v) => isJsonValue(v));\r\n}\r\n\r\n/**\r\n * GUARDED NAMESPACE: keys agent-connector already models are NOT patchable —\r\n * the proper surface must be used instead (otherwise a connector could smuggle\r\n * hooks past the nativeHooks modeling/reporting, or fight the server install).\r\n * Returns a human-readable violation pointing at the proper surface, or null.\r\n * Checked at defineConnector (statically knowable) AND re-enforced in the\r\n * adapter (meta-loaded connectors must not bypass it).\r\n */\r\nexport function configPatchNamespaceViolation(key: string): string | null {\r\n const head = key.split(\".\")[0] ?? \"\";\r\n if (head === \"hooks\") {\r\n return `\"${key}\" targets the hooks config agent-connector already models; declare it via \\`hooks\\` (normalized) or \\`platforms.<id>.nativeHooks\\` instead`;\r\n }\r\n if (\r\n head === \"mcpServers\" ||\r\n head === \"enableAllProjectMcpServers\" ||\r\n head === \"enabledMcpjsonServers\" ||\r\n head === \"disabledMcpjsonServers\"\r\n ) {\r\n return `\"${key}\" targets MCP server registration agent-connector already models; declare it via \\`server\\` / \\`platforms.<id>.server\\` / \\`extra\\` instead`;\r\n }\r\n if (head === \"statusLine\") {\r\n return `\"${key}\" is modeled by the statusline surface; declare it via \\`statusline: { render }\\` instead`;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * The exact manual edit a user can perform when a patch is skipped (conflict,\r\n * drift, unsupported host, denylist…). Printed in every skip-warn so a single\r\n * declaration doubles as its own documented manual step.\r\n */\r\nexport function configPatchManualEdit(patch: ConfigPatchDef): string {\r\n const docs = patch.docsUrl ? ` — see ${patch.docsUrl}` : \"\";\r\n return (\r\n `manual edit if wanted: set ${patch.key} = ${describeJsonValue(patch.value)} ` +\r\n `(${patch.reason})${docs}`\r\n );\r\n}\r\n\r\n/** Compact single-line JSON rendering for diffs/warnings (\"<absent>\" for undefined). */\r\nexport function describeJsonValue(value: JsonValue | undefined): string {\r\n if (value === undefined) return \"<absent>\";\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// ─────────────────────────────────────────────────────────────────────────\r\n// Canonical JSON / deep equality\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Canonical (sorted-keys) JSON of a value — the hash/equality basis. */\r\nexport function canonicalJson(value: JsonValue | undefined): string {\r\n if (value === undefined) return \"undefined\";\r\n if (value === null || typeof value !== \"object\") return JSON.stringify(value);\r\n if (Array.isArray(value)) {\r\n return `[${value.map((v) => canonicalJson(v)).join(\",\")}]`;\r\n }\r\n const keys = Object.keys(value).sort();\r\n const parts = keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(value[k])}`);\r\n return `{${parts.join(\",\")}}`;\r\n}\r\n\r\n/** sha256 of the canonical JSON — the fast path; deep-equal is the authority. */\r\nexport function hashJsonValue(value: JsonValue): string {\r\n return createHash(\"sha256\").update(canonicalJson(value)).digest(\"hex\");\r\n}\r\n\r\n/** Order-insensitive (object keys) deep equality over JSON data. */\r\nexport function jsonDeepEquals(\r\n a: JsonValue | undefined,\r\n b: JsonValue | undefined,\r\n): boolean {\r\n return canonicalJson(a) === canonicalJson(b);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Ledger shape + persistence\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** One connector's registration on a ledger entry. */\r\nexport interface ConfigPatchOwner {\r\n connectorId: string;\r\n connectorVersion: string;\r\n installedAt: string;\r\n}\r\n\r\n/** Refcounted ownership record for one (platform, file, key). */\r\nexport interface ConfigPatchLedgerEntry {\r\n platform: PlatformId;\r\n /** Absolute path of the file actually written (scope-resolved at install time). */\r\n file: string;\r\n /** Dotted leaf path — (platform, file, key) is the primary key. */\r\n key: string;\r\n writtenValue: JsonValue;\r\n /** sha256 of canonical (sorted-keys) JSON of writtenValue (fast path only). */\r\n writtenValueHash: string;\r\n /** Always { present: false } — ownership ONLY attaches to keys we created. */\r\n prior: { present: false };\r\n owners: ConfigPatchOwner[];\r\n}\r\n\r\nexport interface ConfigPatchLedger {\r\n version: 1;\r\n entries: ConfigPatchLedgerEntry[];\r\n}\r\n\r\n/** Ledger file path under the framework data-root. */\r\nexport function configPatchLedgerPath(dataRoot: string): string {\r\n return join(dataRoot, \"state\", \"config-patches.json\");\r\n}\r\n\r\n/**\r\n * Load the ledger; a missing or corrupt file degrades to an empty ledger\r\n * (advisory-for-deletion-only: a lost ledger can never cause data loss, only\r\n * retained keys + skip-warns).\r\n */\r\nexport function loadConfigPatchLedger(dataRoot: string): ConfigPatchLedger {\r\n const path = configPatchLedgerPath(dataRoot);\r\n if (!existsSync(path)) return { version: 1, entries: [] };\r\n try {\r\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as ConfigPatchLedger;\r\n if (!parsed || !Array.isArray(parsed.entries)) return { version: 1, entries: [] };\r\n return { version: 1, entries: parsed.entries.filter(isPlausibleEntry) };\r\n } catch {\r\n return { version: 1, entries: [] };\r\n }\r\n}\r\n\r\n/** Minimal shape sanity for a persisted entry (corrupt rows are dropped). */\r\nfunction isPlausibleEntry(e: unknown): e is ConfigPatchLedgerEntry {\r\n if (e == null || typeof e !== \"object\") return false;\r\n const entry = e as Partial<ConfigPatchLedgerEntry>;\r\n return (\r\n typeof entry.platform === \"string\" &&\r\n typeof entry.file === \"string\" &&\r\n typeof entry.key === \"string\" &&\r\n Array.isArray(entry.owners)\r\n );\r\n}\r\n\r\n/**\r\n * Persist the ledger ATOMICALLY: write to a temp file in the same directory,\r\n * then rename over the target (rename is atomic on the same filesystem).\r\n */\r\nexport function saveConfigPatchLedger(dataRoot: string, ledger: ConfigPatchLedger): void {\r\n const path = configPatchLedgerPath(dataRoot);\r\n assertNoSymlinkInPath(path);\r\n ensureDir(dirname(path));\r\n const tmpFile = `${path}.${process.pid}-${randomBytes(4).toString(\"hex\")}.tmp`;\r\n try {\r\n writeFileSync(tmpFile, `${JSON.stringify(ledger, null, 2)}\\n`, \"utf8\");\r\n renameSync(tmpFile, path);\r\n } catch (err) {\r\n rmSync(tmpFile, { force: true });\r\n throw err;\r\n }\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Ledger operations (pure in-memory; callers load → mutate → save)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Find the entry for (platform, file, key), or undefined. */\r\nexport function findLedgerEntry(\r\n ledger: ConfigPatchLedger,\r\n platform: PlatformId,\r\n file: string,\r\n key: string,\r\n): ConfigPatchLedgerEntry | undefined {\r\n return ledger.entries.find(\r\n (e) => e.platform === platform && e.file === file && e.key === key,\r\n );\r\n}\r\n\r\n/** Every entry on `platform` owned (at least in part) by `connectorId`. */\r\nexport function ledgerEntriesOwnedBy(\r\n ledger: ConfigPatchLedger,\r\n platform: PlatformId,\r\n connectorId: string,\r\n): ConfigPatchLedgerEntry[] {\r\n return ledger.entries.filter(\r\n (e) => e.platform === platform && e.owners.some((o) => o.connectorId === connectorId),\r\n );\r\n}\r\n\r\n/** Create a fresh entry (prior is absent BY CONSTRUCTION) and append it. */\r\nexport function createLedgerEntry(\r\n ledger: ConfigPatchLedger,\r\n init: {\r\n platform: PlatformId;\r\n file: string;\r\n key: string;\r\n value: JsonValue;\r\n connectorId: string;\r\n connectorVersion: string;\r\n },\r\n): ConfigPatchLedgerEntry {\r\n const entry: ConfigPatchLedgerEntry = {\r\n platform: init.platform,\r\n file: init.file,\r\n key: init.key,\r\n writtenValue: init.value,\r\n writtenValueHash: hashJsonValue(init.value),\r\n prior: { present: false },\r\n owners: [\r\n {\r\n connectorId: init.connectorId,\r\n connectorVersion: init.connectorVersion,\r\n installedAt: new Date().toISOString(),\r\n },\r\n ],\r\n };\r\n ledger.entries.push(entry);\r\n return entry;\r\n}\r\n\r\n/**\r\n * Register `connectorId` as a (co-)owner. Returns true when added, false when\r\n * it was already an owner (idempotent re-install → no ledger mutation).\r\n */\r\nexport function addLedgerOwner(\r\n entry: ConfigPatchLedgerEntry,\r\n connectorId: string,\r\n connectorVersion: string,\r\n): boolean {\r\n if (entry.owners.some((o) => o.connectorId === connectorId)) return false;\r\n entry.owners.push({\r\n connectorId,\r\n connectorVersion,\r\n installedAt: new Date().toISOString(),\r\n });\r\n return true;\r\n}\r\n\r\n/**\r\n * Remove `connectorId` from the owners. Returns whether an owner was removed\r\n * and whether the entry is now ownerless (last owner out).\r\n */\r\nexport function removeLedgerOwner(\r\n entry: ConfigPatchLedgerEntry,\r\n connectorId: string,\r\n): { removed: boolean; lastOwner: boolean } {\r\n const before = entry.owners.length;\r\n entry.owners = entry.owners.filter((o) => o.connectorId !== connectorId);\r\n return { removed: entry.owners.length < before, lastOwner: entry.owners.length === 0 };\r\n}\r\n\r\n/** Drop an entry from the ledger (identity match). */\r\nexport function dropLedgerEntry(\r\n ledger: ConfigPatchLedger,\r\n entry: ConfigPatchLedgerEntry,\r\n): void {\r\n ledger.entries = ledger.entries.filter((e) => e !== entry);\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/usage/paths.ts"],"sourcesContent":["/**\r\n * usage/paths — per-platform HOST storage-root resolution + small fs walkers.\r\n *\r\n * This is the read-only complement to core/paths.ts: where that module resolves\r\n * the FRAMEWORK data-root (~/.agent-connector), this one resolves each agent\r\n * CLI's OWN native storage roots (~/.qwen, ~/.claude, …) so the usage readers\r\n * can parse them. It NEVER writes; it only enumerates files.\r\n *\r\n * Ported from tokscale paths.rs (the tokscale cache dir) and from each reader's\r\n * storage-path spec (docs/research/usage-readers.json). Resolution order is\r\n * uniform across platforms:\r\n * 1. an explicit AGENT_CONNECTOR_<PLATFORM>_DIR env override (verbatim, when\r\n * non-empty — an empty string is treated as unset so we never resolve to \"\");\r\n * 2. the platform-specific default for the current OS.\r\n *\r\n * The \"tokscale cache dir\" (~/.config/tokscale, or AGENT_CONNECTOR_TOKSCALE_DIR)\r\n * is where synced readers (cursor/antigravity/antigravity-cli/trae/warp) look for\r\n * a local cache that a separate tokscale run may have produced — we read it if\r\n * present, but we never create or sync it. (Antigravity's own native store is\r\n * protobuf .pb with no public schema, so it too is synced-cache-or-skip.)\r\n */\r\n\r\nimport {\r\n existsSync,\r\n readdirSync,\r\n statSync,\r\n} from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { isAbsolute, join, resolve } from \"node:path\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Home / env helpers\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Expand a leading \"~\" (and \"~/\") to the user's home directory. */\r\nexport function expandHome(p: string): string {\r\n if (p === \"~\") return homedir();\r\n if (p.startsWith(\"~/\") || p.startsWith(\"~\\\\\")) {\r\n return join(homedir(), p.slice(2));\r\n }\r\n return p;\r\n}\r\n\r\n/**\r\n * Read an env override, treating empty/blank as unset (mirrors tokscale's\r\n * is_config_dir_overridden contract: an empty override must NOT resolve to \"\").\r\n * Relative paths are resolved against the process CWD; \"~\" is expanded.\r\n */\r\nfunction envOverride(name: string): string | undefined {\r\n const raw = process.env[name];\r\n if (raw == null || raw.trim() === \"\") return undefined;\r\n const expanded = expandHome(raw.trim());\r\n return isAbsolute(expanded) ? expanded : resolve(expanded);\r\n}\r\n\r\n/** $XDG_DATA_HOME (when set & non-empty) else ~/.local/share. */\r\nfunction xdgDataHome(): string {\r\n const xdg = process.env.XDG_DATA_HOME;\r\n if (xdg && xdg.trim() !== \"\") return resolve(expandHome(xdg.trim()));\r\n return join(homedir(), \".local\", \"share\");\r\n}\r\n\r\n/** $XDG_CONFIG_HOME (when set & non-empty) else ~/.config. */\r\nfunction xdgConfigHome(): string {\r\n const xdg = process.env.XDG_CONFIG_HOME;\r\n if (xdg && xdg.trim() !== \"\") return resolve(expandHome(xdg.trim()));\r\n return join(homedir(), \".config\");\r\n}\r\n\r\n/** Windows %LOCALAPPDATA% else ~/AppData/Local. */\r\nfunction localAppData(): string {\r\n const v = process.env.LOCALAPPDATA;\r\n if (v && v.trim() !== \"\") return resolve(v.trim());\r\n return join(homedir(), \"AppData\", \"Local\");\r\n}\r\n\r\nconst isMac = process.platform === \"darwin\";\r\nconst isWin = process.platform === \"win32\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// tokscale cache dir (for synced readers)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Resolve the tokscale config dir (where synced caches live). Ported from\r\n * tokscale paths.rs get_config_dir():\r\n * 1. AGENT_CONNECTOR_TOKSCALE_DIR override (verbatim, non-empty);\r\n * 2. macOS: $HOME/.config/tokscale (NOT ~/Library/Application Support);\r\n * 3. Linux: $XDG_CONFIG_HOME/tokscale or ~/.config/tokscale;\r\n * 4. Windows: %APPDATA%/tokscale (config_dir equivalent) else ~/.config/tokscale.\r\n *\r\n * We use AGENT_CONNECTOR_TOKSCALE_DIR (not TOKSCALE_CONFIG_DIR) so the framework\r\n * never accidentally couples to a tokscale install's hermetic test env.\r\n */\r\nexport function tokscaleConfigDir(): string {\r\n const override = envOverride(\"AGENT_CONNECTOR_TOKSCALE_DIR\");\r\n if (override) return override;\r\n if (isMac) return join(homedir(), \".config\", \"tokscale\");\r\n if (isWin) {\r\n const appData = process.env.APPDATA;\r\n if (appData && appData.trim() !== \"\") return join(resolve(appData.trim()), \"tokscale\");\r\n return join(homedir(), \".config\", \"tokscale\");\r\n }\r\n return join(xdgConfigHome(), \"tokscale\");\r\n}\r\n\r\n/** The directory a synced platform's local cache lives under, e.g. `<tokscale>/cursor-cache`. */\r\nexport function tokscaleCacheDir(name: string): string {\r\n return join(tokscaleConfigDir(), name);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Antigravity native store roots (DETECTION ONLY — not parsed for usage)\r\n//\r\n// CONFIRMED-BY-INSTALL (2026-06-03, docs/research/antigravity-paths-confirmed.md):\r\n// the native Antigravity store is `~/.gemini/antigravity/conversations/<uuid>.pb`\r\n// — PROTOBUF with no public schema — and `brain/<uuid>/` holds only media +\r\n// `*.metadata.json`. There are NO `transcript*.jsonl` files. The `agy` CLI shares\r\n// this SAME `~/.gemini/antigravity/` dir (no separate config/storage dir). So the\r\n// native dir is used only for platform DETECTION (in the adapters); the usage\r\n// readers do NOT parse it (protobuf, unreadable) — they are SYNCED readers that\r\n// read the tokscale synced-cache instead (see hostRoots → antigravity-cache).\r\n//\r\n// These helpers are retained for any detection caller and honor the standard\r\n// AGENT_CONNECTOR_<PLATFORM>_DIR override (prepended, preferred when set).\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * The native Antigravity store root for DETECTION: `~/.gemini/antigravity/`\r\n * (CONFIRMED). Its `conversations/<uuid>.pb` payloads are protobuf with no public\r\n * schema, so this dir is NOT parsed for usage — only its presence is a signal.\r\n *\r\n * Honors AGENT_CONNECTOR_ANTIGRAVITY_DIR (verbatim, when set) as the override.\r\n */\r\nexport function antigravityNativeRoots(): string[] {\r\n const out: string[] = [];\r\n const override = envOverride(\"AGENT_CONNECTOR_ANTIGRAVITY_DIR\");\r\n if (override) out.push(override);\r\n out.push(join(homedir(), \".gemini\", \"antigravity\"));\r\n return out;\r\n}\r\n\r\n/**\r\n * The native store root for the Antigravity CLI (`agy`) for DETECTION. CONFIRMED:\r\n * `agy` has NO separate dir — it SHARES the IDE's `~/.gemini/antigravity/` (also\r\n * protobuf, not parsed for usage).\r\n *\r\n * Honors AGENT_CONNECTOR_ANTIGRAVITY_CLI_DIR (verbatim, when set) as the override.\r\n */\r\nexport function antigravityCliNativeRoots(): string[] {\r\n const out: string[] = [];\r\n const override = envOverride(\"AGENT_CONNECTOR_ANTIGRAVITY_CLI_DIR\");\r\n if (override) out.push(override);\r\n out.push(join(homedir(), \".gemini\", \"antigravity\"));\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Per-platform host roots\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Candidate host storage roots for a platform, most-preferred first. Readers\r\n * iterate the returned list and use the first that exists (each variant is the\r\n * OS-correct default; the env override, when present, is prepended).\r\n *\r\n * Only the platforms this subsystem currently ships a reader for are listed in\r\n * detail; the table is structured so a new platform is one new case. Returning\r\n * `[]` (no candidate root) makes a reader fail-open to zero records.\r\n */\r\nexport function hostRoots(platformId: string): string[] {\r\n const out: string[] = [];\r\n const override = envOverride(`AGENT_CONNECTOR_${platformId.toUpperCase().replace(/-/g, \"_\")}_DIR`);\r\n if (override) out.push(override);\r\n\r\n switch (platformId) {\r\n case \"qwen-code\":\r\n // ~/.qwen/projects/*/chats/*.jsonl\r\n out.push(join(homedir(), \".qwen\", \"projects\"));\r\n break;\r\n case \"claude-code\":\r\n out.push(join(homedir(), \".claude\", \"projects\"));\r\n break;\r\n case \"codex\":\r\n out.push(join(homedir(), \".codex\", \"sessions\"));\r\n break;\r\n case \"gemini-cli\":\r\n out.push(join(homedir(), \".gemini\", \"tmp\"));\r\n break;\r\n case \"pi\":\r\n out.push(join(homedir(), \".pi\", \"agent\", \"sessions\"));\r\n break;\r\n case \"kimi\":\r\n // TWO Moonshot products share the \"kimi\" id with DIFFERENT session trees:\r\n // - Kimi Code (newer, @moonshot-ai/kimi-code): ~/.kimi-code/sessions/...\r\n // (deeper tree, see readers/kimi.ts) — the product our adapter targets.\r\n // - Kimi CLI (older): ~/.kimi/sessions/<GROUP>/<UUID>/wire.jsonl\r\n // Both are scanned (Kimi Code preferred first). $KIMI_CODE_HOME relocates\r\n // the Kimi Code home and is honored ahead of these in readers/kimi.ts.\r\n out.push(join(homedir(), \".kimi-code\", \"sessions\"));\r\n out.push(join(homedir(), \".kimi\", \"sessions\"));\r\n break;\r\n case \"copilot-cli\":\r\n out.push(join(xdgDataHome(), \"Copilot\", \"telemetry\"));\r\n out.push(join(xdgConfigHome(), \"copilot\", \"telemetry\"));\r\n break;\r\n case \"amp\":\r\n out.push(join(xdgDataHome(), \"amp\", \"threads\"));\r\n break;\r\n case \"droid\":\r\n out.push(join(homedir(), \".factory\", \"sessions\"));\r\n break;\r\n case \"mux\":\r\n out.push(join(homedir(), \".mux\", \"sessions\"));\r\n break;\r\n case \"kiro\":\r\n out.push(join(homedir(), \".kiro\", \"sessions\", \"cli\"));\r\n break;\r\n case \"opencode\":\r\n out.push(join(xdgDataHome(), \"opencode\", \"opencode.db\"));\r\n break;\r\n case \"goose\":\r\n if (isMac) out.push(join(homedir(), \"Library\", \"Application Support\", \"goose\", \"sessions\", \"sessions.db\"));\r\n out.push(join(xdgDataHome(), \"goose\", \"sessions\", \"sessions.db\"));\r\n out.push(join(xdgDataHome(), \"Block\", \"goose\", \"sessions\", \"sessions.db\"));\r\n break;\r\n case \"hermes\":\r\n out.push(join(homedir(), \".hermes\", \"state.db\"));\r\n break;\r\n case \"kilo-cli\":\r\n out.push(join(xdgDataHome(), \"kilo\", \"kilo.db\"));\r\n break;\r\n case \"crush\":\r\n out.push(join(homedir(), \".cache\", \"crush\", \"crush.db\"));\r\n break;\r\n case \"zed\":\r\n if (isMac) out.push(join(homedir(), \"Library\", \"Application Support\", \"Zed\", \"threads\", \"threads.db\"));\r\n else if (isWin) out.push(join(localAppData(), \"Zed\", \"threads\", \"threads.db\"));\r\n else out.push(join(xdgDataHome(), \"zed\", \"threads\", \"threads.db\"));\r\n break;\r\n // Synced platforms: local cache under the tokscale config dir.\r\n case \"cursor\":\r\n out.push(tokscaleCacheDir(\"cursor-cache\"));\r\n break;\r\n case \"antigravity\":\r\n // SYNCED: the native store is protobuf (.pb, no public schema) and NOT\r\n // parseable, so the reader reads only the tokscale synced-cache mirror if a\r\n // separate tokscale run produced one (else [] → \"requires sync\"). The\r\n // native `~/.gemini/antigravity/` dir is used only for detection.\r\n out.push(tokscaleCacheDir(\"antigravity-cache\"));\r\n break;\r\n case \"antigravity-cli\":\r\n // SYNCED: `agy` shares the IDE's protobuf (.pb) store (no schema), so the\r\n // reader reads only the tokscale synced-cache mirror if present (else [] →\r\n // \"requires sync\"). Shares the IDE's antigravity-cache name (same data).\r\n out.push(tokscaleCacheDir(\"antigravity-cache\"));\r\n break;\r\n case \"trae\":\r\n out.push(tokscaleCacheDir(\"trae-cache\"));\r\n break;\r\n case \"warp\":\r\n out.push(tokscaleCacheDir(\"warp-cache\"));\r\n break;\r\n default:\r\n break;\r\n }\r\n return out;\r\n}\r\n\r\n/** First existing host root for a platform, or undefined when none is present. */\r\nexport function firstExistingRoot(platformId: string): string | undefined {\r\n for (const root of hostRoots(platformId)) {\r\n if (existsSync(root)) return root;\r\n }\r\n return undefined;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Directory / glob walkers (tolerant — never throw)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Is the path an existing directory? Tolerant (false on any stat error). */\r\nexport function isDir(p: string): boolean {\r\n try {\r\n return statSync(p).isDirectory();\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/** Is the path an existing regular file? Tolerant (false on any stat error). */\r\nexport function isFile(p: string): boolean {\r\n try {\r\n return statSync(p).isFile();\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Recursively list every file under `root` whose name matches `predicate`.\r\n * Tolerant: an unreadable directory is skipped, never thrown. Returns absolute\r\n * paths in directory-walk order. A non-existent root yields [].\r\n */\r\nexport function walkFiles(\r\n root: string,\r\n predicate: (name: string, absPath: string) => boolean,\r\n maxDepth = 12,\r\n): string[] {\r\n const out: string[] = [];\r\n if (!isDir(root)) return out;\r\n\r\n const stack: Array<{ dir: string; depth: number }> = [{ dir: root, depth: 0 }];\r\n while (stack.length > 0) {\r\n const { dir, depth } = stack.pop() as { dir: string; depth: number };\r\n let entries: import(\"node:fs\").Dirent[];\r\n try {\r\n entries = readdirSync(dir, { withFileTypes: true });\r\n } catch {\r\n continue; // unreadable dir → skip\r\n }\r\n for (const entry of entries) {\r\n const abs = join(dir, entry.name);\r\n if (entry.isDirectory()) {\r\n if (depth < maxDepth) stack.push({ dir: abs, depth: depth + 1 });\r\n } else if (entry.isFile() && predicate(entry.name, abs)) {\r\n out.push(abs);\r\n }\r\n }\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * List immediate subdirectory names of `dir` (not recursive). Tolerant: returns\r\n * [] for a missing/unreadable directory.\r\n */\r\nexport function listSubdirs(dir: string): string[] {\r\n if (!isDir(dir)) return [];\r\n try {\r\n return readdirSync(dir, { withFileTypes: true })\r\n .filter((e) => e.isDirectory())\r\n .map((e) => join(dir, e.name));\r\n } catch {\r\n return [];\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
allAdapters,
|
|
4
4
|
loadAdapter
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-TOSNS2BY.js";
|
|
6
6
|
|
|
7
7
|
// src/sdk/introspect.ts
|
|
8
8
|
function hostCanFireEvent(c, event) {
|
|
@@ -58,10 +58,10 @@ var SURFACE_PREDICATES = {
|
|
|
58
58
|
subagents: (c) => c.supportsSubagents ?? false,
|
|
59
59
|
memory: (c) => c.supportsMemory ?? false,
|
|
60
60
|
statusline: (c) => c.supportsStatusline ?? false,
|
|
61
|
-
// Emitters ship on
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
61
|
+
// Emitters ship only on hosts with a verified native trigger target: droid,
|
|
62
|
+
// hermes, kiro, omp, openclaw, pi, warp, zed, plus the nemoclaw fork. Every
|
|
63
|
+
// other host leaves supportsActions unset, so explain() marks actions
|
|
64
|
+
// skip-warn there — the honest state for a host with no emission target.
|
|
65
65
|
actions: (c) => c.supportsActions ?? false,
|
|
66
66
|
configPatch: (c) => c.supportsConfigPatch ?? false,
|
|
67
67
|
nativeHooks: (c) => c.supportsNativeHooks ?? false
|
|
@@ -87,4 +87,4 @@ export {
|
|
|
87
87
|
hostsSupporting,
|
|
88
88
|
surfaceSupport
|
|
89
89
|
};
|
|
90
|
-
//# sourceMappingURL=chunk-
|
|
90
|
+
//# sourceMappingURL=chunk-KTBAB556.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sdk/introspect.ts"],"sourcesContent":["/**\r\n * sdk/introspect — host-capability introspection over the adapter registry.\r\n *\r\n * A thin, READ-ONLY query layer above {@link loadAdapter} / {@link allAdapters}:\r\n * \"which hosts can honor surface X?\" and \"what can host Y do?\". It exists so a\r\n * connector author (or a docs/CLI surface) can answer those questions WITHOUT\r\n * reaching into adapter internals or re-deriving the per-surface capability\r\n * rules — the predicates below are the single source of truth for mapping the\r\n * raw {@link PlatformCapabilities} flags onto the developer-facing surface names.\r\n *\r\n * Everything is async because adapters load lazily (one entry per platform in\r\n * the registry, imported only when queried).\r\n */\r\n\r\nimport type {\r\n HookEventName,\r\n PlatformCapabilities,\r\n PlatformId,\r\n} from \"../core/types.js\";\r\nimport { allAdapters, loadAdapter } from \"../adapters/registry.js\";\r\n\r\n/**\r\n * The single source of truth mapping each normalized {@link HookEventName} onto\r\n * the {@link PlatformCapabilities} flag that says \"this host can natively FIRE\r\n * this event\". The optional flags (the newer E1 events + PostCompact) are read\r\n * as `?? false`, mirroring the supportsCommands precedent — a host that leaves a\r\n * flag unset cannot fire that event, so a declared hook for it skip-warns at\r\n * install and `explain` reports it as not honored.\r\n *\r\n * This is the per-event signal {@link explain}'s hooks row evaluates against the\r\n * connector's DECLARED events (so a Stop-only connector on a PreToolUse-only\r\n * host no longer falsely shows `native`), and the same signal `simulate`'s real\r\n * parse→handler→format chain expresses at runtime.\r\n */\r\nexport function hostCanFireEvent(\r\n c: PlatformCapabilities,\r\n event: HookEventName,\r\n): boolean {\r\n switch (event) {\r\n case \"SessionStart\":\r\n return c.sessionStart;\r\n case \"SessionEnd\":\r\n return c.sessionEnd;\r\n case \"UserPromptSubmit\":\r\n return c.userPromptSubmit;\r\n case \"PreToolUse\":\r\n return c.preToolUse;\r\n case \"PostToolUse\":\r\n return c.postToolUse;\r\n case \"PreCompact\":\r\n return c.preCompact;\r\n case \"Stop\":\r\n return c.stop;\r\n case \"Notification\":\r\n return c.notification;\r\n case \"PermissionRequest\":\r\n return c.permissionRequest ?? false;\r\n case \"PostToolUseFailure\":\r\n return c.postToolUseFailure ?? false;\r\n case \"SubagentStart\":\r\n return c.subagentStart ?? false;\r\n case \"SubagentStop\":\r\n return c.subagentStop ?? false;\r\n case \"PostCompact\":\r\n return c.postCompact ?? false;\r\n }\r\n}\r\n\r\n/** The full normalized hook-event union, in canonical order. */\r\nconst ALL_HOOK_EVENTS: HookEventName[] = [\r\n \"SessionStart\",\r\n \"SessionEnd\",\r\n \"UserPromptSubmit\",\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"Stop\",\r\n \"Notification\",\r\n \"PermissionRequest\",\r\n \"PostToolUseFailure\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n \"PostCompact\",\r\n];\r\n\r\n/**\r\n * The developer-facing surface names a connector can declare. These mirror the\r\n * top-level {@link import(\"../core/types.js\").ConnectorConfig} keys (server,\r\n * hooks, commands, …) plus the platform-scoped `configPatch` / `nativeHooks`\r\n * escape hatches — the same vocabulary the install diff and `explain` use.\r\n */\r\nexport type SurfaceName =\r\n | \"server\"\r\n | \"hooks\"\r\n | \"commands\"\r\n | \"skills\"\r\n | \"subagents\"\r\n | \"memory\"\r\n | \"statusline\"\r\n | \"actions\"\r\n | \"configPatch\"\r\n | \"nativeHooks\";\r\n\r\n/**\r\n * Pure capability predicate per surface — `true` when the host can NATIVELY\r\n * honor that surface. The optional capability flags are read as `?? false`\r\n * (the supportsCommands precedent in core/types), so a host that simply leaves\r\n * a flag unset reports the surface as unsupported (the installer skip-warns it).\r\n *\r\n * `hooks` here is the COARSE host-capability predicate: `true` when the host can\r\n * fire AT LEAST ONE normalized event (it derives from {@link hostCanFireEvent},\r\n * the per-event source of truth, so the two never drift). It is the right answer\r\n * for the connector-less queries ({@link hostsSupporting} / {@link surfaceSupport}:\r\n * \"which hosts have a hook runtime at all?\"). It is deliberately NOT used by\r\n * {@link explain}, which must judge the hooks surface against the connector's\r\n * SPECIFIC declared events — a Stop-only connector on a PreToolUse-only host is\r\n * NOT honored even though the host has a hook runtime (see {@link explain}).\r\n */\r\nexport const SURFACE_PREDICATES: Record<\r\n SurfaceName,\r\n (c: PlatformCapabilities) => boolean\r\n> = {\r\n server: (c) => c.transports.length > 0,\r\n hooks: (c) => ALL_HOOK_EVENTS.some((e) => hostCanFireEvent(c, e)),\r\n commands: (c) => c.supportsCommands ?? false,\r\n skills: (c) => c.supportsSkills ?? false,\r\n subagents: (c) => c.supportsSubagents ?? false,\r\n memory: (c) => c.supportsMemory ?? false,\r\n statusline: (c) => c.supportsStatusline ?? false,\r\n // Emitters ship only on hosts with a verified native trigger target: droid,\n // hermes, kiro, omp, openclaw, pi, warp, zed, plus the nemoclaw fork. Every\n // other host leaves supportsActions unset, so explain() marks actions\n // skip-warn there — the honest state for a host with no emission target.\n actions: (c) => c.supportsActions ?? false,\r\n configPatch: (c) => c.supportsConfigPatch ?? false,\r\n nativeHooks: (c) => c.supportsNativeHooks ?? false,\r\n};\r\n\r\n/**\r\n * The {@link PlatformCapabilities} a host advertises, or `undefined` for an id\r\n * that is not in the registry (`\"unknown\"`, a usage-only id like `\"synthetic\"`,\r\n * or a typo) — callers branch on undefined rather than crash.\r\n */\r\nexport async function capabilitiesOf(\r\n host: PlatformId | string,\r\n): Promise<PlatformCapabilities | undefined> {\r\n const adapter = await loadAdapter(host);\r\n return adapter?.capabilities;\r\n}\r\n\r\n/**\r\n * Every registered host that can NATIVELY honor `surface`, as a sorted id list\r\n * (stable output for snapshots/docs). Loads all adapters in parallel and keeps\r\n * only those whose capabilities pass {@link SURFACE_PREDICATES}.\r\n */\r\nexport async function hostsSupporting(surface: SurfaceName): Promise<PlatformId[]> {\r\n const predicate = SURFACE_PREDICATES[surface];\r\n const adapters = await allAdapters();\r\n return adapters\r\n .filter((adapter) => predicate(adapter.capabilities))\r\n .map((adapter) => adapter.id)\r\n .sort();\r\n}\r\n\r\n/**\r\n * Convenience: does `host` natively support `surface`? `false` for an unknown\r\n * id (no capabilities → cannot support anything).\r\n */\r\nexport async function surfaceSupport(\r\n host: PlatformId | string,\r\n surface: SurfaceName,\r\n): Promise<boolean> {\r\n const capabilities = await capabilitiesOf(host);\r\n return capabilities ? SURFACE_PREDICATES[surface](capabilities) : false;\r\n}\r\n"],"mappings":";;;;;;;AAkCO,SAAS,iBACd,GACA,OACS;AACT,UAAQ,OAAO;AAAA,IACb,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE;AAAA,IACX,KAAK;AACH,aAAO,EAAE,qBAAqB;AAAA,IAChC,KAAK;AACH,aAAO,EAAE,sBAAsB;AAAA,IACjC,KAAK;AACH,aAAO,EAAE,iBAAiB;AAAA,IAC5B,KAAK;AACH,aAAO,EAAE,gBAAgB;AAAA,IAC3B,KAAK;AACH,aAAO,EAAE,eAAe;AAAA,EAC5B;AACF;AAGA,IAAM,kBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAmCO,IAAM,qBAGT;AAAA,EACF,QAAQ,CAAC,MAAM,EAAE,WAAW,SAAS;AAAA,EACrC,OAAO,CAAC,MAAM,gBAAgB,KAAK,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAAA,EAChE,UAAU,CAAC,MAAM,EAAE,oBAAoB;AAAA,EACvC,QAAQ,CAAC,MAAM,EAAE,kBAAkB;AAAA,EACnC,WAAW,CAAC,MAAM,EAAE,qBAAqB;AAAA,EACzC,QAAQ,CAAC,MAAM,EAAE,kBAAkB;AAAA,EACnC,YAAY,CAAC,MAAM,EAAE,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA,EAK3C,SAAS,CAAC,MAAM,EAAE,mBAAmB;AAAA,EACrC,aAAa,CAAC,MAAM,EAAE,uBAAuB;AAAA,EAC7C,aAAa,CAAC,MAAM,EAAE,uBAAuB;AAC/C;AAOA,eAAsB,eACpB,MAC2C;AAC3C,QAAM,UAAU,MAAM,YAAY,IAAI;AACtC,SAAO,SAAS;AAClB;AAOA,eAAsB,gBAAgB,SAA6C;AACjF,QAAM,YAAY,mBAAmB,OAAO;AAC5C,QAAM,WAAW,MAAM,YAAY;AACnC,SAAO,SACJ,OAAO,CAAC,YAAY,UAAU,QAAQ,YAAY,CAAC,EACnD,IAAI,CAAC,YAAY,QAAQ,EAAE,EAC3B,KAAK;AACV;AAMA,eAAsB,eACpB,MACA,SACkB;AAClB,QAAM,eAAe,MAAM,eAAe,IAAI;AAC9C,SAAO,eAAe,mBAAmB,OAAO,EAAE,YAAY,IAAI;AACpE;","names":[]}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
REGISTERED_PLATFORM_IDS
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-TOSNS2BY.js";
|
|
5
5
|
import {
|
|
6
6
|
CONFIG_PATCH_SEGMENT_RE,
|
|
7
7
|
configPatchNamespaceViolation,
|
|
8
8
|
isJsonValue,
|
|
9
9
|
isValidConfigPatchKey
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KFPSJRHR.js";
|
|
11
11
|
import {
|
|
12
12
|
MANAGED_BLOCK_BEGIN_TOKEN,
|
|
13
13
|
MANAGED_BLOCK_END_TOKEN,
|
|
14
14
|
MEMORY_CONTENT_HARD_CAP_BYTES
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ILWHLGIC.js";
|
|
16
16
|
import {
|
|
17
17
|
CONNECTOR_ID_RE,
|
|
18
18
|
isValidConnectorId
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-QYOUQCC6.js";
|
|
20
20
|
|
|
21
21
|
// src/core/package-metadata.ts
|
|
22
22
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -643,6 +643,8 @@ function normalizeServer(server) {
|
|
|
643
643
|
|
|
644
644
|
export {
|
|
645
645
|
withConnectorPackageMetadata,
|
|
646
|
+
findNearestPackageJson,
|
|
647
|
+
readConnectorPackageMetadataFromPackageJson,
|
|
646
648
|
readConnectorPackageMetadataNearFile,
|
|
647
649
|
deriveHostAliasFromPackageName,
|
|
648
650
|
deriveHostAliasFromMcpName,
|
|
@@ -668,4 +670,4 @@ export {
|
|
|
668
670
|
defineConfigPatch,
|
|
669
671
|
defineNativeHook
|
|
670
672
|
};
|
|
671
|
-
//# sourceMappingURL=chunk-
|
|
673
|
+
//# sourceMappingURL=chunk-KWC5DQ5Z.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/package-metadata.ts","../src/core/define-connector.ts","../src/core/mcp-standard.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\r\nimport { existsSync, readFileSync } from \"node:fs\";\r\nimport { dirname, join, resolve } from \"node:path\";\r\n\r\nimport type {\r\n McpPackageIdentity,\r\n ResolvedMcpPackageIdentity,\r\n ServerDef,\r\n} from \"./types.js\";\r\n\r\nconst GENERIC_PACKAGE_BASENAMES = new Set([\r\n \"mcp\",\r\n \"server\",\r\n \"mcp-server\",\r\n \"connector\",\r\n \"tool\",\r\n \"tools\",\r\n \"cli\",\r\n]);\r\n\r\nexport interface ConnectorPackageMetadata {\r\n /** Package-derived MCP identity used to derive host aliases and install ids. */\r\n mcp?: McpPackageIdentity;\r\n /** package.json version used as the connector version default. */\r\n version?: string;\r\n}\r\n\r\nconst PACKAGE_METADATA_CONTEXT = new AsyncLocalStorage<ConnectorPackageMetadata>();\r\n\r\nfunction kebab(raw: string): string {\r\n return raw\r\n .trim()\r\n .replace(/^@/, \"\")\r\n .replace(/[\\\\/_.\\s]+/g, \"-\")\r\n .replace(/[^a-zA-Z0-9-]+/g, \"-\")\r\n .replace(/-{2,}/g, \"-\")\r\n .replace(/^-+|-+$/g, \"\")\r\n .toLowerCase();\r\n}\r\n\r\nfunction scopedPackageParts(packageName: string): {\r\n scope?: string;\r\n basename: string;\r\n} {\r\n const raw = packageName.trim();\r\n if (raw.startsWith(\"@\")) {\r\n const [scope, basename] = raw.slice(1).split(\"/\");\r\n return { scope: scope ? kebab(scope) : undefined, basename: basename ?? \"\" };\r\n }\r\n return { basename: raw };\r\n}\r\n\r\nfunction cleanMcpBasename(raw: string): string {\r\n let name = kebab(raw);\r\n name = name.replace(/^mcp-server-/, \"\");\r\n name = name.replace(/^server-/, \"\");\r\n name = name.replace(/-mcp-server$/, \"\");\r\n name = name.replace(/-mcp$/, \"\");\r\n name = name.replace(/-server$/, \"\");\r\n return kebab(name);\r\n}\r\n\r\nfunction isGeneric(name: string | undefined): boolean {\r\n return !name || GENERIC_PACKAGE_BASENAMES.has(name);\r\n}\r\n\r\nfunction cleanString(value: unknown): string | undefined {\r\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\r\n}\r\n\r\nfunction objectKeys(value: unknown): string[] {\r\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\r\n return Object.keys(value).filter((key) => key.trim());\r\n}\r\n\r\nfunction packageBinName(bin: unknown, packageName: string | undefined): string | undefined {\r\n if (typeof bin === \"string\") {\r\n return packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\r\n }\r\n\r\n const keys = objectKeys(bin);\r\n if (keys.length === 0) return undefined;\r\n if (keys.length === 1) return keys[0];\r\n\r\n const packageAlias = packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\r\n if (packageAlias && keys.includes(packageAlias)) return packageAlias;\r\n\r\n const unscoped = packageName?.startsWith(\"@\") ? packageName.split(\"/\")[1] : packageName;\r\n const cleanUnscoped = unscoped ? cleanMcpBasename(unscoped) : undefined;\r\n if (cleanUnscoped && keys.includes(cleanUnscoped)) return cleanUnscoped;\r\n\r\n return undefined;\r\n}\r\n\r\nexport function currentMcpPackageIdentity(): McpPackageIdentity | undefined {\r\n return currentConnectorPackageMetadata()?.mcp;\r\n}\r\n\r\nexport function currentConnectorPackageMetadata():\r\n | ConnectorPackageMetadata\r\n | undefined {\r\n return PACKAGE_METADATA_CONTEXT.getStore();\r\n}\r\n\r\nexport async function withConnectorPackageMetadata<T>(\r\n metadata: ConnectorPackageMetadata | undefined,\r\n run: () => Promise<T>,\r\n): Promise<T> {\r\n if (!metadata || Object.keys(metadata).length === 0) return run();\r\n return PACKAGE_METADATA_CONTEXT.run(metadata, run);\r\n}\r\n\r\nexport async function withMcpPackageIdentity<T>(\r\n identity: McpPackageIdentity | undefined,\r\n run: () => Promise<T>,\r\n): Promise<T> {\r\n if (!identity || Object.keys(identity).length === 0) return run();\r\n return withConnectorPackageMetadata({ mcp: identity }, run);\r\n}\r\n\r\nexport function findNearestPackageJson(startDir: string): string | undefined {\r\n let dir = resolve(startDir);\r\n for (;;) {\r\n const candidate = join(dir, \"package.json\");\r\n if (existsSync(candidate)) return candidate;\r\n\r\n const parent = dirname(dir);\r\n if (parent === dir) return undefined;\r\n dir = parent;\r\n }\r\n}\r\n\r\nexport function readMcpPackageIdentityFromPackageJson(\r\n packageJsonPath: string,\r\n): McpPackageIdentity {\r\n return readConnectorPackageMetadataFromPackageJson(packageJsonPath).mcp ?? {};\r\n}\r\n\r\nexport function readConnectorPackageMetadataFromPackageJson(\r\n packageJsonPath: string,\r\n): ConnectorPackageMetadata {\r\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\r\n name?: unknown;\r\n version?: unknown;\r\n mcpName?: unknown;\r\n mcp?: unknown;\r\n bin?: unknown;\r\n };\r\n const packageName = cleanString(parsed.name);\r\n const version = cleanString(parsed.version);\r\n const mcp =\r\n parsed.mcp && typeof parsed.mcp === \"object\" && !Array.isArray(parsed.mcp)\r\n ? (parsed.mcp as { name?: unknown; mcpName?: unknown })\r\n : undefined;\r\n const mcpName =\r\n cleanString(parsed.mcpName) ??\r\n cleanString(mcp?.mcpName) ??\r\n cleanString(mcp?.name);\r\n const bin = packageBinName(parsed.bin, packageName);\r\n\r\n const identity: McpPackageIdentity = {\r\n ...(packageName ? { packageName } : {}),\r\n ...(mcpName ? { mcpName } : {}),\r\n ...(bin ? { bin } : {}),\r\n };\r\n\r\n return {\r\n ...(Object.keys(identity).length > 0 ? { mcp: identity } : {}),\r\n ...(version ? { version } : {}),\r\n };\r\n}\r\n\r\nexport function readMcpPackageIdentityNearFile(\r\n filePath: string,\r\n): McpPackageIdentity | undefined {\r\n return readConnectorPackageMetadataNearFile(filePath)?.mcp;\r\n}\r\n\r\nexport function readConnectorPackageMetadataNearFile(\r\n filePath: string,\r\n): ConnectorPackageMetadata | undefined {\r\n const packageJsonPath = findNearestPackageJson(dirname(filePath));\r\n if (!packageJsonPath) return undefined;\r\n try {\r\n const metadata = readConnectorPackageMetadataFromPackageJson(packageJsonPath);\r\n return Object.keys(metadata).length > 0 ? metadata : undefined;\r\n } catch {\r\n return undefined;\r\n }\r\n}\r\n\r\n/** Derive the host-facing MCP server key from a package name. */\r\nexport function deriveHostAliasFromPackageName(\r\n packageName: string,\r\n): string | undefined {\r\n const { scope, basename } = scopedPackageParts(packageName);\r\n const fromBasename = cleanMcpBasename(basename);\r\n if (!isGeneric(fromBasename)) return fromBasename;\r\n const fromScope = scope ? cleanMcpBasename(scope) : undefined;\r\n return isGeneric(fromScope) ? undefined : fromScope;\r\n}\r\n\r\n/** Derive the host-facing MCP server key from an MCP registry name. */\r\nexport function deriveHostAliasFromMcpName(\r\n mcpName: string,\r\n): string | undefined {\r\n const [namespace, name] = mcpName.trim().split(\"/\");\r\n const fromName = cleanMcpBasename(name ?? namespace ?? \"\");\r\n if (!isGeneric(fromName)) return fromName;\r\n\r\n const namespaceParts = (namespace ?? \"\").split(\".\").filter(Boolean);\r\n const fromNamespace = cleanMcpBasename(namespaceParts.at(-1) ?? \"\");\r\n return isGeneric(fromNamespace) ? undefined : fromNamespace;\r\n}\r\n\r\n/** Infer an npm package from common npx-style stdio server definitions. */\r\nexport function inferNpmPackageFromServer(\r\n server: ServerDef | undefined,\r\n): string | undefined {\r\n if (!server || server.transport !== \"stdio\") return undefined;\r\n if (typeof server.command !== \"string\" || server.command.trim() === \"\") {\r\n return undefined;\r\n }\r\n const runner = kebab(server.command.split(/[\\\\/]/).pop() ?? server.command);\r\n if (![\"npx\", \"npm\", \"pnpm\", \"yarn\", \"bun\"].includes(runner)) return undefined;\r\n\r\n const args = server.args ?? [];\r\n for (let i = 0; i < args.length; i += 1) {\r\n const arg = args[i]!;\r\n if (arg === \"--\") continue;\r\n if (arg === \"exec\" || arg === \"dlx\" || arg === \"x\") continue;\r\n if (arg === \"-y\" || arg === \"--yes\" || arg === \"--no-install\") continue;\r\n if (arg === \"--package\" || arg === \"-p\") {\r\n i += 1;\r\n continue;\r\n }\r\n if (arg.startsWith(\"-\")) continue;\r\n return arg;\r\n }\r\n return undefined;\r\n}\r\n\r\nexport function resolveMcpPackageIdentity(input: {\r\n id?: string;\r\n mcp?: McpPackageIdentity;\r\n server?: ServerDef;\r\n}): ResolvedMcpPackageIdentity {\r\n const packageName =\r\n input.mcp?.packageName ?? inferNpmPackageFromServer(input.server);\r\n const hostAlias =\r\n input.mcp?.hostAlias ??\r\n (input.mcp?.mcpName\r\n ? deriveHostAliasFromMcpName(input.mcp.mcpName)\r\n : undefined) ??\r\n (packageName ? deriveHostAliasFromPackageName(packageName) : undefined) ??\r\n (input.mcp?.bin ? cleanMcpBasename(input.mcp.bin) : undefined);\r\n\r\n return {\r\n ...(packageName ? { packageName } : {}),\r\n ...(input.mcp?.mcpName ? { mcpName: input.mcp.mcpName } : {}),\r\n ...(input.mcp?.bin ? { bin: input.mcp.bin } : {}),\r\n ...(hostAlias ? { hostAlias } : {}),\r\n };\r\n}\r\n","/**\r\n * core/define-connector — the public write-once entry point.\r\n *\r\n * Validates a ConnectorConfig and normalizes it into a ResolvedConnector with\r\n * every optional field resolved to a default. Validation is intentionally\r\n * dependency-free (no zod) to keep the single-binary install lean.\r\n */\r\n\r\nimport { isAbsolute, normalize } from \"node:path\";\r\n\r\nimport type {\r\n ActionDef,\r\n CommandDef,\r\n ConfigPatchDef,\r\n ConnectorConfig,\r\n HookDefinition,\r\n HookEventName,\r\n HooksConfig,\r\n MemoryDef,\r\n NativeHookDef,\r\n PlatformId,\r\n PublishConfig,\r\n ResolvedConnector,\r\n SkillDef,\r\n StatuslineDef,\r\n SubagentDef,\r\n} from \"./types.js\";\r\nimport { REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\r\nimport { REGISTRY_NAMESPACE_RE } from \"./mcp-standard.js\";\r\nimport { CONNECTOR_ID_RE, isValidConnectorId } from \"./ids.js\";\r\nimport {\r\n currentConnectorPackageMetadata,\r\n resolveMcpPackageIdentity,\r\n} from \"./package-metadata.js\";\r\nimport {\r\n MANAGED_BLOCK_BEGIN_TOKEN,\r\n MANAGED_BLOCK_END_TOKEN,\r\n MEMORY_CONTENT_HARD_CAP_BYTES,\r\n} from \"./managed-block.js\";\r\nimport {\r\n CONFIG_PATCH_SEGMENT_RE,\r\n configPatchNamespaceViolation,\r\n isJsonValue,\r\n isValidConfigPatchKey,\r\n} from \"./config-patch-ledger.js\";\r\n\r\n/** kebab-case name regex shared by command/skill/subagent names. */\r\nconst SURFACE_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\r\n\r\n/** Max length of a skill description (Agent Skills open standard). */\r\nconst SKILL_DESCRIPTION_MAX = 1024;\r\n\r\n// NOTE: canonical ordering — append new events at the END (hookEvents ordering\r\n// is pinned by tests and feeds install-file ordering). Exported so the\r\n// hook-dispatch gate + Claude-bundle event sets can be drift-tested against it.\r\nexport const ALL_EVENTS: HookEventName[] = [\r\n \"SessionStart\",\r\n \"SessionEnd\",\r\n \"UserPromptSubmit\",\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"Stop\",\r\n \"Notification\",\r\n \"PermissionRequest\",\r\n \"PostToolUseFailure\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n \"PostCompact\",\r\n];\r\n\r\n/** Thrown on an invalid connector configuration. */\r\nexport class ConnectorConfigError extends Error {\r\n constructor(message: string) {\r\n super(`Invalid connector config: ${message}`);\r\n this.name = \"ConnectorConfigError\";\r\n }\r\n}\r\n\r\nfunction declaredEvents(hooks: HooksConfig | undefined): HookEventName[] {\r\n if (!hooks) return [];\r\n return ALL_EVENTS.filter((e) => typeof hooks[e]?.handler === \"function\");\r\n}\r\n\r\n/**\r\n * Validate + normalize a connector definition.\r\n * Returns a ResolvedConnector that adapters and the CLI consume directly.\r\n */\r\nexport function defineConnector(config: ConnectorConfig): ResolvedConnector {\r\n if (!config || typeof config !== \"object\") {\r\n throw new ConnectorConfigError(\"config must be an object\");\r\n }\r\n\r\n const packageMetadata = currentConnectorPackageMetadata();\r\n const packageIdentity = packageMetadata?.mcp;\r\n if (packageIdentity && Object.keys(packageIdentity).length > 0) {\r\n config = {\r\n ...config,\r\n mcp: {\r\n ...packageIdentity,\r\n ...config.mcp,\r\n },\r\n };\r\n }\r\n\r\n const mcpIdentity = resolveMcpPackageIdentity(config);\r\n const connectorId = config.id ?? mcpIdentity.hostAlias;\r\n if (!isValidConnectorId(connectorId)) {\r\n throw new ConnectorConfigError(\r\n `id must be kebab-case matching ${CONNECTOR_ID_RE} or derivable from mcp/package metadata (got ${JSON.stringify(config.id)})`,\r\n );\r\n }\r\n const hasCommands = Array.isArray(config.commands) && config.commands.length > 0;\r\n const hasSkills = Array.isArray(config.skills) && config.skills.length > 0;\r\n const hasSubagents = Array.isArray(config.subagents) && config.subagents.length > 0;\r\n const hasMemory = Array.isArray(config.memory) && config.memory.length > 0;\r\n // A statusline (a HUD) is a legitimate sole payload — a connector whose whole\r\n // job is rendering a status line. SINGULAR (one per connector), so a plain\r\n // presence check (object with a render handler — validated in normalizeStatusline).\r\n const hasStatusline = config.statusline != null;\r\n // Actions (each a user-invokable run handler) are a legitimate sole payload —\r\n // a connector whose whole job is shipping dispatchable actions.\r\n const hasActions = Array.isArray(config.actions) && config.actions.length > 0;\r\n // A platform-scoped nativeHooks declaration is a legitimate sole payload\r\n // (a hooks-only connector wired entirely through native passthrough events).\r\n const hasNativeHooks = Object.values(config.platforms ?? {}).some(\r\n (override) =>\r\n override?.nativeHooks != null && Object.keys(override.nativeHooks).length > 0,\r\n );\r\n // Likewise a platform-scoped configPatch declaration (a connector whose whole\r\n // job is asserting a host config key, e.g. an experimental feature flag).\r\n const hasConfigPatch = Object.values(config.platforms ?? {}).some(\r\n (override) => Array.isArray(override?.configPatch) && override.configPatch.length > 0,\r\n );\r\n if (\r\n !config.server &&\r\n !config.hooks &&\r\n !hasCommands &&\r\n !hasSkills &&\r\n !hasSubagents &&\r\n !hasMemory &&\r\n !hasStatusline &&\r\n !hasActions &&\r\n !hasNativeHooks &&\r\n !hasConfigPatch\r\n ) {\r\n throw new ConnectorConfigError(\r\n \"a connector must declare at least one of `server`, `hooks`, `commands`, `skills`, `subagents`, `memory`, `statusline`, `actions`, \" +\r\n \"or a per-platform `nativeHooks` / `configPatch` declaration\",\r\n );\r\n }\r\n\r\n if (config.server) {\r\n const s = config.server;\r\n if (s.transport === \"stdio\") {\r\n if (!s.command || typeof s.command !== \"string\") {\r\n throw new ConnectorConfigError(\r\n \"server.command is required for stdio transport\",\r\n );\r\n }\r\n } else {\r\n if (!s.url || typeof s.url !== \"string\") {\r\n throw new ConnectorConfigError(\r\n `server.url is required for ${s.transport} transport`,\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Validate hook handlers are functions, plus any per-host override map.\r\n if (config.hooks) {\r\n for (const ev of ALL_EVENTS) {\r\n const def = config.hooks[ev];\r\n if (def != null && typeof def.handler !== \"function\") {\r\n throw new ConnectorConfigError(`hooks.${ev}.handler must be a function`);\r\n }\r\n // Per-host override map: every key must be a registered platform id and\r\n // every entry's handler a function (author-time hard error, not skip-warn).\r\n validateHostsMap(def?.hosts, `hooks.${ev}.hosts`, \"handler\");\r\n }\r\n }\r\n\r\n // Validate per-platform native passthrough hooks (handlers live in this same\r\n // config module, exactly like normalized hooks — the resolved connector keeps\r\n // `platforms` verbatim, so live handlers survive resolution and are recovered\r\n // at runtime by re-importing the module via the registry's modulePath).\r\n validateNativeHooks(config.platforms);\r\n\r\n // Validate per-platform declarative config patches (pure JSON — persisted\r\n // whole; semantics are FIXED set-if-absent/skip-warn, so only the shape is\r\n // validated here; the host adapter enforces its sensitive-key denylist).\r\n validateConfigPatches(config.platforms);\r\n\r\n const commands = normalizeCommands(config.commands);\r\n const skills = normalizeSkills(config.skills);\r\n const subagents = normalizeSubagents(config.subagents);\r\n const memory = normalizeMemory(config.memory);\r\n const statusline = normalizeStatusline(config.statusline);\r\n const actions = normalizeActions(config.actions);\r\n\r\n const t = config.telemetry ?? {};\r\n\r\n const resolved: ResolvedConnector = {\r\n id: connectorId,\r\n ...(Object.keys(mcpIdentity).length > 0 ? { mcp: mcpIdentity } : {}),\r\n displayName: config.displayName ?? connectorId,\r\n version: config.version ?? packageMetadata?.version ?? \"0.0.0\",\r\n ...(config.server ? { server: normalizeServer(config.server) } : {}),\r\n hooks: config.hooks ?? {},\r\n hookEvents: declaredEvents(config.hooks),\r\n telemetry: {\r\n enabled: t.enabled ?? true,\r\n modelFamilyHint: t.modelFamilyHint ?? \"auto\",\r\n measureToolDefs: t.measureToolDefs ?? true,\r\n // OPT-IN: host-native turn-usage capture is OFF unless explicitly enabled\r\n // in config (or forced on at install via AGENT_CONNECTOR_HOST_NATIVE=1).\r\n hostNativeUsage: t.hostNativeUsage ?? false,\r\n store: t.store ?? \"ndjson\",\r\n calibration: {\r\n anthropicCountTokens: t.calibration?.anthropicCountTokens ?? false,\r\n },\r\n },\r\n commands,\r\n skills,\r\n subagents,\r\n memory,\r\n ...(statusline ? { statusline } : {}),\r\n actions,\r\n platforms: config.platforms ?? {},\r\n targets: config.targets ?? \"auto\",\r\n ...(config.publish ? { publish: normalizePublish(config.publish) } : {}),\r\n };\r\n\r\n return resolved;\r\n}\r\n\r\n/** The 13 normalized event names, for the nativeHooks collision check. */\r\nconst NORMALIZED_EVENT_SET: ReadonlySet<string> = new Set(ALL_EVENTS);\r\n\r\n/**\r\n * Validate a per-host override map (`hosts?:`) declared on a hook definition or\r\n * on the statusline. Shared by the hook-validation loop and normalizeStatusline:\r\n * - the value must be a plain object keyed by platform id;\r\n * - every key MUST be a REGISTERED platform id (REGISTERED_PLATFORM_IDS) —\r\n * an unknown id is an author-time ConnectorConfigError (NOT a skip-warn:\r\n * a typo'd host would otherwise silently never fire);\r\n * - every entry's implementation field (`handler` for hooks, `render` for\r\n * statusline, `run` for actions) MUST be a function (it is re-imported from\r\n * the connector module at runtime, like the top-level handler/render/run).\r\n * `undefined` (no map) is valid and skipped.\r\n */\r\nfunction validateHostsMap(\r\n map: unknown,\r\n surfaceLabel: string,\r\n implField: \"handler\" | \"render\" | \"run\",\r\n): void {\r\n if (map == null) return;\r\n if (typeof map !== \"object\" || Array.isArray(map)) {\r\n throw new ConnectorConfigError(\r\n `${surfaceLabel} must be an object keyed by platform id`,\r\n );\r\n }\r\n for (const [platformId, entry] of Object.entries(map as Record<string, unknown>)) {\r\n if (!REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)) {\r\n const valid = [...REGISTERED_PLATFORM_IDS].sort().join(\", \");\r\n throw new ConnectorConfigError(\r\n `unknown platform id \"${platformId}\" in hosts map for ${surfaceLabel}; valid ids: ${valid}`,\r\n );\r\n }\r\n if (\r\n entry == null ||\r\n typeof entry !== \"object\" ||\r\n typeof (entry as Record<string, unknown>)[implField] !== \"function\"\r\n ) {\r\n throw new ConnectorConfigError(\r\n `${surfaceLabel}.${platformId}.${implField} must be a function`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Validate every `platforms[<id>].nativeHooks` declaration:\r\n * - the value must be an object keyed by HOST-NATIVE event name;\r\n * - an event name must NOT collide with the normalized {@link HookEventName}\r\n * union (those belong in the cross-platform `hooks` API, which gets\r\n * normalization, matcher evaluation, and HookResponse mapping);\r\n * - each handler must be a function (it is re-imported from the config module\r\n * at runtime, like normalized hook handlers);\r\n * - `matcher`, when present, must be a string (written verbatim into the\r\n * host's hook config — the host evaluates it).\r\n */\r\nfunction validateNativeHooks(platforms: ConnectorConfig[\"platforms\"]): void {\r\n if (platforms == null) return;\r\n for (const [platformId, override] of Object.entries(platforms)) {\r\n const native = override?.nativeHooks;\r\n if (native == null) continue;\r\n const where = `platforms.${platformId}.nativeHooks`;\r\n if (typeof native !== \"object\" || Array.isArray(native)) {\r\n throw new ConnectorConfigError(\r\n `${where} must be an object keyed by host-native event name`,\r\n );\r\n }\r\n for (const [event, def] of Object.entries(native)) {\r\n if (NORMALIZED_EVENT_SET.has(event)) {\r\n throw new ConnectorConfigError(\r\n `${where}.${event} collides with the normalized hook event \"${event}\"; ` +\r\n `declare it under \\`hooks.${event}\\` (the normalized, cross-platform hooks API) instead`,\r\n );\r\n }\r\n if (def == null || typeof def !== \"object\" || typeof def.handler !== \"function\") {\r\n throw new ConnectorConfigError(`${where}.${event}.handler must be a function`);\r\n }\r\n if (def.matcher !== undefined && typeof def.matcher !== \"string\") {\r\n throw new ConnectorConfigError(`${where}.${event}.matcher must be a string`);\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Validate every `platforms[<id>].configPatch` declaration:\r\n * - the value must be an array of patch objects;\r\n * - `key` must be a dotted LEAF path whose segments match\r\n * {@link CONFIG_PATCH_SEGMENT_RE} — no dots-in-key, no array indices;\r\n * - `key` must not collide with the agent-connector-modeled namespace\r\n * (`hooks*` → hooks/nativeHooks; `mcpServers*` & friends → server/extra);\r\n * - duplicate keys within one platform's list are rejected (a duplicate\r\n * would double-apply / fight itself on refcounts);\r\n * - `value` must be JSON-serializable data (it is persisted whole in the\r\n * connector record and in the ownership ledger);\r\n * - `reason` is REQUIRED (printed in the install diff and every skip-warn);\r\n * - `docsUrl`, when present, must be a string.\r\n * The HOST-side sensitive-key denylist is deliberately NOT validated here —\r\n * it lives in (and is documented by) each supporting adapter.\r\n */\r\nfunction validateConfigPatches(platforms: ConnectorConfig[\"platforms\"]): void {\r\n if (platforms == null) return;\r\n for (const [platformId, override] of Object.entries(platforms)) {\r\n const patches = override?.configPatch;\r\n if (patches == null) continue;\r\n const where = `platforms.${platformId}.configPatch`;\r\n if (!Array.isArray(patches)) {\r\n throw new ConnectorConfigError(`${where} must be an array of patch objects`);\r\n }\r\n const seen = new Set<string>();\r\n patches.forEach((patch, i) => {\r\n if (patch == null || typeof patch !== \"object\" || Array.isArray(patch)) {\r\n throw new ConnectorConfigError(`${where}[${i}] must be an object`);\r\n }\r\n if (!isValidConfigPatchKey(patch.key)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].key must be a dotted LEAF path whose segments match ` +\r\n `${CONFIG_PATCH_SEGMENT_RE} (no dots-in-key, no array indices); ` +\r\n `got ${JSON.stringify(patch.key)}`,\r\n );\r\n }\r\n const violation = configPatchNamespaceViolation(patch.key);\r\n if (violation) {\r\n throw new ConnectorConfigError(`${where}[${i}].key ${violation}`);\r\n }\r\n if (seen.has(patch.key)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}] duplicate key \"${patch.key}\"`,\r\n );\r\n }\r\n seen.add(patch.key);\r\n if (!isJsonValue(patch.value)) {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].value must be JSON-serializable data ` +\r\n `(string/finite number/boolean/null/array/plain object)`,\r\n );\r\n }\r\n if (typeof patch.reason !== \"string\" || patch.reason.trim() === \"\") {\r\n throw new ConnectorConfigError(\r\n `${where}[${i}].reason is required (a human-readable why, printed in ` +\r\n `the install diff and every skip-warn)`,\r\n );\r\n }\r\n if (patch.docsUrl !== undefined && typeof patch.docsUrl !== \"string\") {\r\n throw new ConnectorConfigError(`${where}[${i}].docsUrl must be a string`);\r\n }\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Validate the optional `publish` block (registry server.json + MCPB bundle\r\n * distribution metadata). Light, dependency-free: we only reject shapes that\r\n * would emit a clearly INVALID standard artifact. The per-format required-field\r\n * checks (e.g. server.json needs registryNamespace, mcpb needs author.name)\r\n * live in the emitters so a connector that never publishes pays nothing.\r\n */\r\nfunction normalizePublish(publish: PublishConfig): PublishConfig {\r\n if (typeof publish !== \"object\" || Array.isArray(publish)) {\r\n throw new ConnectorConfigError(\"publish must be an object\");\r\n }\r\n if (publish.registryNamespace !== undefined) {\r\n const ns = publish.registryNamespace;\r\n if (typeof ns !== \"string\" || !REGISTRY_NAMESPACE_RE.test(ns)) {\r\n throw new ConnectorConfigError(\r\n `publish.registryNamespace must be a reverse-DNS namespace matching ${REGISTRY_NAMESPACE_RE} ` +\r\n `(e.g. \"io.github.acme\" or \"com.acme\"); got ${JSON.stringify(ns)}`,\r\n );\r\n }\r\n }\r\n if (publish.packageName !== undefined && typeof publish.packageName !== \"string\") {\r\n throw new ConnectorConfigError(\"publish.packageName must be a string\");\r\n }\r\n if (publish.author !== undefined) {\r\n const a = publish.author;\r\n if (typeof a !== \"object\" || a == null || typeof a.name !== \"string\" || a.name === \"\") {\r\n throw new ConnectorConfigError(\"publish.author.name must be a non-empty string\");\r\n }\r\n }\r\n return { ...publish };\r\n}\r\n\r\n/** Validate a surface name (kebab-case) or throw a ConnectorConfigError. */\r\nfunction assertSurfaceName(\r\n surface: string,\r\n name: unknown,\r\n index: number,\r\n field = \"name\",\r\n): string {\r\n if (typeof name !== \"string\" || !SURFACE_NAME_RE.test(name)) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].${field} must be kebab-case matching ${SURFACE_NAME_RE} (got ${JSON.stringify(name)})`,\r\n );\r\n }\r\n return name;\r\n}\r\n\r\n/** Require a non-empty string field on a surface entry. */\r\nfunction assertNonEmptyString(\r\n surface: string,\r\n index: number,\r\n field: string,\r\n value: unknown,\r\n): string {\r\n if (typeof value !== \"string\" || value.length === 0) {\r\n throw new ConnectorConfigError(`${surface}[${index}].${field} must be a non-empty string`);\r\n }\r\n return value;\r\n}\r\n\r\n/** Detect a duplicate surface name within one array, throwing on collision. */\r\nfunction assertNoDuplicate(\r\n surface: string,\r\n seen: Set<string>,\r\n name: string,\r\n index: number,\r\n field = \"name\",\r\n): void {\r\n if (seen.has(name)) {\r\n throw new ConnectorConfigError(`${surface}[${index}] duplicate ${field} \"${name}\"`);\r\n }\r\n seen.add(name);\r\n}\r\n\r\nfunction normalizeCommands(input: CommandDef[] | undefined): CommandDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"commands must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((cmd, i) => {\r\n if (!cmd || typeof cmd !== \"object\") {\r\n throw new ConnectorConfigError(`commands[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"commands\", cmd.name, i);\r\n assertNoDuplicate(\"commands\", seen, name, i);\r\n assertNonEmptyString(\"commands\", i, \"prompt\", cmd.prompt);\r\n // Pass through verbatim (content); arrays are content, not handlers.\r\n return { ...cmd, name };\r\n });\r\n}\r\n\r\nfunction normalizeSkills(input: SkillDef[] | undefined): SkillDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"skills must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((skill, i) => {\r\n if (!skill || typeof skill !== \"object\") {\r\n throw new ConnectorConfigError(`skills[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"skills\", skill.name, i);\r\n assertNoDuplicate(\"skills\", seen, name, i);\r\n const description = assertNonEmptyString(\"skills\", i, \"description\", skill.description);\r\n if (description.length > SKILL_DESCRIPTION_MAX) {\r\n throw new ConnectorConfigError(\r\n `skills[${i}].description exceeds ${SKILL_DESCRIPTION_MAX} chars (got ${description.length})`,\r\n );\r\n }\r\n assertNonEmptyString(\"skills\", i, \"body\", skill.body);\r\n assertSafeResourceKeys(\"skills\", i, skill.resources);\r\n return { ...skill, name };\r\n });\r\n}\r\n\r\n/**\r\n * Validate every `skill.resources` key as a SAFE relative path that stays inside\r\n * the skill dir. Each resource is later written/removed via join(skillDir, rel)\r\n * by every adapter, so an unvalidated key like \"../../settings.json\" would\r\n * escape the skill dir → arbitrary file write/delete. Reject (throw) when a key\r\n * is empty/\".\", absolute, or normalizes to a path that begins with \"..\" or\r\n * contains a \"/..\" (or platform-sep) traversal segment.\r\n */\r\nfunction assertSafeResourceKeys(\r\n surface: string,\r\n index: number,\r\n resources: Record<string, string> | undefined,\r\n): void {\r\n if (resources == null) return;\r\n if (typeof resources !== \"object\" || Array.isArray(resources)) {\r\n throw new ConnectorConfigError(`${surface}[${index}].resources must be an object`);\r\n }\r\n for (const rel of Object.keys(resources)) {\r\n if (rel === \"\" || rel === \".\" || rel.trim() === \"\") {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must be a non-empty relative path (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n if (isAbsolute(rel)) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must be a relative path inside the skill dir, not absolute (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n // Normalize with BOTH posix and native separators flattened so a Windows\r\n // \"..\\\\x\" or a posix \"../x\" is caught regardless of the host OS.\r\n const norm = normalize(rel.replace(/\\\\/g, \"/\"));\r\n const segs = norm.split(/[/\\\\]/);\r\n if (norm === \"..\" || norm.startsWith(\"../\") || norm.startsWith(\"..\\\\\") || segs.includes(\"..\")) {\r\n throw new ConnectorConfigError(\r\n `${surface}[${index}].resources key must not escape the skill dir via \"..\" (got ${JSON.stringify(rel)})`,\r\n );\r\n }\r\n }\r\n}\r\n\r\n/** Default name for a single-entry memory declaration. */\r\nconst MEMORY_DEFAULT_NAME = \"memory\";\r\n\r\n/**\r\n * Validate + normalize `memory` entries (the managed-block content surface).\r\n * - `name` defaults to \"memory\", then must be kebab-case and unique — it is\r\n * half of the block marker id (`<connectorId>/<name>`) and must stay stable;\r\n * - `content` must be a non-empty string, ≤ 16 KiB (hard cap — memory files\r\n * are injected into every prompt of every session on the host), and must\r\n * NOT contain the literal marker tokens `agent-connector:begin` /\r\n * `agent-connector:end` (they would corrupt marker scanning in the shared\r\n * file — rephrase the guidance instead). The 4 KiB SOFT budget is reported\r\n * at install time as a `warn` ChangeRecord, not a config error\r\n * (defineConnector has no warning channel).\r\n */\r\nfunction normalizeMemory(input: MemoryDef[] | undefined): MemoryDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"memory must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((entry, i) => {\r\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\r\n throw new ConnectorConfigError(`memory[${i}] must be an object`);\r\n }\r\n const name =\r\n entry.name === undefined\r\n ? MEMORY_DEFAULT_NAME\r\n : assertSurfaceName(\"memory\", entry.name, i);\r\n assertNoDuplicate(\"memory\", seen, name, i);\r\n const content = assertNonEmptyString(\"memory\", i, \"content\", entry.content);\r\n const bytes = Buffer.byteLength(content, \"utf8\");\r\n if (bytes > MEMORY_CONTENT_HARD_CAP_BYTES) {\r\n throw new ConnectorConfigError(\r\n `memory[${i}].content exceeds the ${MEMORY_CONTENT_HARD_CAP_BYTES}-byte hard cap ` +\r\n `(got ${bytes} bytes); memory is inlined into every prompt of every targeted host — keep it terse`,\r\n );\r\n }\r\n for (const token of [MANAGED_BLOCK_BEGIN_TOKEN, MANAGED_BLOCK_END_TOKEN]) {\r\n if (content.includes(token)) {\r\n throw new ConnectorConfigError(\r\n `memory[${i}].content must not contain the literal marker token \"${token}\" ` +\r\n `(it would corrupt managed-block scanning in the shared memory file); rephrase the guidance`,\r\n );\r\n }\r\n }\r\n if (entry.description !== undefined && typeof entry.description !== \"string\") {\r\n throw new ConnectorConfigError(`memory[${i}].description must be a string`);\r\n }\r\n return { ...entry, name };\r\n });\r\n}\r\n\r\n/** Default name for the (singular) statusline declaration. */\r\nconst STATUSLINE_DEFAULT_NAME = \"statusline\";\r\n\r\n/**\r\n * Validate + normalize the SINGULAR `statusline` (a HUD handler surface):\r\n * - `render` MUST be a function (it is the renderer, re-imported at runtime\r\n * like a hook handler);\r\n * - `name` defaults to \"statusline\", then must be kebab-case (the shared\r\n * surface-name validator);\r\n * - `description`, when present, must be a string.\r\n * Returns undefined when no statusline is declared (it is optional and singular,\r\n * unlike the memory[] array).\r\n */\r\nfunction normalizeStatusline(\r\n input: StatuslineDef | undefined,\r\n): StatuslineDef | undefined {\r\n if (input == null) return undefined;\r\n if (typeof input !== \"object\" || Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"statusline must be an object\");\r\n }\r\n if (typeof input.render !== \"function\") {\r\n throw new ConnectorConfigError(\"statusline.render must be a function\");\r\n }\r\n const name =\r\n input.name === undefined\r\n ? STATUSLINE_DEFAULT_NAME\r\n : assertSurfaceName(\"statusline\", input.name, 0);\r\n if (input.description !== undefined && typeof input.description !== \"string\") {\r\n throw new ConnectorConfigError(\"statusline.description must be a string\");\r\n }\r\n // Per-host render override map: registered platform ids only, each render a\r\n // function (author-time hard error, mirroring the hook hosts-map validation).\r\n validateHostsMap(input.hosts, \"statusline.hosts\", \"render\");\r\n return { ...input, name };\r\n}\r\n\r\n/**\r\n * Validate + normalize `actions` (the user-invokable action handler surface):\r\n * - the value must be an array;\r\n * - each entry's `id` must be kebab-case (the shared surface-name validator)\r\n * and UNIQUE within the connector (ConnectorConfigError on dup — the id is\r\n * the verb's positional arg, so a duplicate would be ambiguous);\r\n * - `run` MUST be a function (it is the handler, re-imported at runtime like a\r\n * hook handler / statusline render);\r\n * - `description`, when present, must be a string;\r\n * - the per-host `hosts:` override map is validated via the shared\r\n * validateHostsMap (registered platform ids only, each `run` a function).\r\n * Returns [] when no actions are declared (defaults applied, like the other\r\n * array surfaces).\r\n */\r\nfunction normalizeActions(input: ActionDef[] | undefined): ActionDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"actions must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((action, i) => {\r\n if (!action || typeof action !== \"object\" || Array.isArray(action)) {\r\n throw new ConnectorConfigError(`actions[${i}] must be an object`);\r\n }\r\n const id = assertSurfaceName(\"actions\", action.id, i, \"id\");\r\n assertNoDuplicate(\"actions\", seen, id, i, \"id\");\r\n if (typeof action.run !== \"function\") {\r\n throw new ConnectorConfigError(`actions[${i}].run must be a function`);\r\n }\r\n if (action.description !== undefined && typeof action.description !== \"string\") {\r\n throw new ConnectorConfigError(`actions[${i}].description must be a string`);\r\n }\r\n // Per-host run override map: registered platform ids only, each run a\r\n // function (author-time hard error, mirroring the statusline/hook hosts-map).\r\n validateHostsMap(action.hosts, `actions.${id}.hosts`, \"run\");\r\n return { ...action, id };\r\n });\r\n}\r\n\r\n/**\r\n * Typed identity helper for authoring a status line in its own module:\r\n * export const myStatusline = defineStatusline({ render: (ctx) => \"…\" });\r\n * Mirrors the (informal) defineX helpers; gives the developer full type\r\n * inference on {@link StatuslineContext} without importing the type by hand.\r\n */\r\nexport const defineStatusline = (def: StatuslineDef): StatuslineDef => def;\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Typed identity helpers (the `define*` authoring family)\r\n//\r\n// Each is a one-line identity function: it returns its argument UNCHANGED and\r\n// does NOT validate or mutate (validation still happens centrally in\r\n// defineConnector). Their only job is ergonomics — authoring a surface in its\r\n// own module with full type inference + autocomplete on the *Def shape, and a\r\n// single import site — mirroring the existing {@link defineStatusline}.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Typed identity helper for authoring ONE normalized lifecycle hook in its own\r\n * module, EVENT-PARAMETERIZED so the handler's payload narrows to that event:\r\n *\r\n * export const onPre = defineHook(\"PreToolUse\", {\r\n * handler(evt) { evt.toolName // ← typed as a PreToolUseEvent, not the union\r\n * return { decision: \"deny\", reason: \"no\" };\r\n * },\r\n * });\r\n *\r\n * The leading `event` argument exists ONLY to infer `E`; the def is returned\r\n * unchanged (identity — validation still happens in defineConnector). Passing\r\n * `HookDefinition` without an event would widen the handler param to the full\r\n * {@link HookEventName} union and lose per-event narrowing, so the event tag is\r\n * required.\r\n */\r\nexport const defineHook = <E extends HookEventName>(\r\n event: E,\r\n def: HookDefinition<E>,\r\n): HookDefinition<E> => {\r\n void event; // tag-only: used solely to infer E (the def carries no event field)\r\n return def;\r\n};\r\n\r\n/**\r\n * Typed identity helper for authoring a slash {@link CommandDef} in its own\r\n * module. Returns the def unchanged (kebab-case name + prompt are validated by\r\n * defineConnector when the connector is assembled).\r\n */\r\nexport const defineCommand = (def: CommandDef): CommandDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring an Agent {@link SkillDef} in its own\r\n * module. Returns the def unchanged (name/description/body + safe resource keys\r\n * are validated by defineConnector).\r\n */\r\nexport const defineSkill = (def: SkillDef): SkillDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link SubagentDef} in its own module.\r\n * Returns the def unchanged (name/description/prompt validated by defineConnector).\r\n */\r\nexport const defineSubagent = (def: SubagentDef): SubagentDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link MemoryDef} (standing-guidance\r\n * managed block) in its own module. Returns the def unchanged (name/content +\r\n * byte budget + marker-token guard validated by defineConnector).\r\n */\r\nexport const defineMemory = (def: MemoryDef): MemoryDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a user-invokable {@link ActionDef} in its\r\n * own module. Returns the def unchanged (kebab-case unique id + run-is-function\r\n * + the per-host hosts map validated by defineConnector when the connector is\r\n * assembled).\r\n */\r\nexport const defineAction = (def: ActionDef): ActionDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a declarative {@link ConfigPatchDef}\r\n * (set-if-absent host-config key patch) in its own module. Returns the def\r\n * unchanged (leaf-path grammar + namespace guard + required reason validated by\r\n * defineConnector when it appears under `platforms[<id>].configPatch`).\r\n */\r\nexport const defineConfigPatch = (def: ConfigPatchDef): ConfigPatchDef => def;\r\n\r\n/**\r\n * Typed identity helper for authoring a {@link NativeHookDef} (host-native\r\n * passthrough hook) in its own module. Returns the def unchanged (event-name\r\n * collision + handler-is-function validated by defineConnector when it appears\r\n * under `platforms[<id>].nativeHooks`).\r\n */\r\nexport const defineNativeHook = (def: NativeHookDef): NativeHookDef => def;\r\n\r\nfunction normalizeSubagents(input: SubagentDef[] | undefined): SubagentDef[] {\r\n if (input == null) return [];\r\n if (!Array.isArray(input)) {\r\n throw new ConnectorConfigError(\"subagents must be an array\");\r\n }\r\n const seen = new Set<string>();\r\n return input.map((agent, i) => {\r\n if (!agent || typeof agent !== \"object\") {\r\n throw new ConnectorConfigError(`subagents[${i}] must be an object`);\r\n }\r\n const name = assertSurfaceName(\"subagents\", agent.name, i);\r\n assertNoDuplicate(\"subagents\", seen, name, i);\r\n assertNonEmptyString(\"subagents\", i, \"description\", agent.description);\r\n assertNonEmptyString(\"subagents\", i, \"prompt\", agent.prompt);\r\n return { ...agent, name };\r\n });\r\n}\r\n\r\nfunction normalizeServer(server: ConnectorConfig[\"server\"]): ResolvedConnector[\"server\"] {\r\n if (!server) return undefined;\r\n const wrapDefault = server.transport === \"stdio\";\r\n return {\r\n ...server,\r\n enabled: server.enabled ?? true,\r\n tools: server.tools ?? { include: [\"*\"] },\r\n wrapForTelemetry: server.wrapForTelemetry ?? wrapDefault,\r\n };\r\n}\r\n","/**\r\n * core/mcp-standard — pinned literals + guards for the official MCP standards\r\n * agent-connector EMITS (registry server.json, MCPB bundle) or SPEAKS (the\r\n * connection-lifecycle wire used by `doctor --probe`).\r\n *\r\n * Each pinned constant is the CURRENT released value verified 2026-06-05 against\r\n * the upstream spec/schema. They are deliberately centralized + annotated\r\n * MUST-VERIFY-AT-IMPLEMENTATION: a newer spec revision can supersede any of them\r\n * without breaking us, so the bump is a one-line change here, never scattered.\r\n *\r\n * Sources:\r\n * • server.schema.json 2025-12-11 — https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\r\n * • MCPB manifest 0.3 — github.com/anthropics/mcpb (MANIFEST.md)\r\n * • MCP protocol 2025-11-25 — modelcontextprotocol.io/specification/2025-11-25\r\n * (latest RELEASED revision. 2026-07-28 is a release-candidate only — do NOT\r\n * advance to it until it publishes as a stable dated revision. The probe\r\n * offers this version but ACCEPTS whatever a server negotiates, so the\r\n * offered literal being stale never breaks interop — only this constant.)\r\n */\r\n\r\nimport type { Transport } from \"./types.js\";\r\n\r\n/** Registry server.json JSON Schema URL (released 2025-12-11). MUST-VERIFY on bump. */\r\nexport const MCP_SERVER_SCHEMA_URL =\r\n \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\";\r\n\r\n/** Current MCPB bundle manifest_version (anthropics/mcpb). MUST-VERIFY on bump. */\r\nexport const MCPB_MANIFEST_VERSION = \"0.3\";\r\n\r\n/**\r\n * Latest RELEASED MCP protocol revision `doctor --probe` offers in `initialize`.\r\n * Current = 2025-11-25. MUST-VERIFY on bump; stay on the latest *released*\r\n * revision (2026-07-28 is RC-only as of 2026-06). Negotiation accepts whatever\r\n * the server returns, so this is the offered value, not a hard requirement.\r\n */\r\nexport const MCP_PROTOCOL_VERSION = \"2025-11-25\";\r\n\r\n/** Default npm registry base URL stamped into server.json npm packages. */\r\nexport const NPM_REGISTRY_BASE_URL = \"https://registry.npmjs.org\";\r\n\r\n/**\r\n * server.json transport.type enum — the EXACT values the 2025-12-11 schema\r\n * accepts (packages[].transport.type and remotes[].type). Our `http` Transport\r\n * maps to the spec slug \"streamable-http\"; \"ws\" is non-spec (see below).\r\n */\r\nexport type RegistryTransportType = \"stdio\" | \"streamable-http\" | \"sse\";\r\n\r\n/**\r\n * Map our {@link Transport} union to the registry/server.json transport slug.\r\n * Returns null for \"ws\" — WebSocket is NOT a spec transport (it can only exist\r\n * as a vendor custom transport, e.g. Claude Code's non-spec type:\"ws\"), so a\r\n * conformant artifact must REJECT it rather than emit an invalid type. The spec\r\n * defines exactly stdio + streamable-http, with sse the deprecated HTTP+SSE.\r\n */\r\nexport function registryTransportType(transport: Transport): RegistryTransportType | null {\r\n switch (transport) {\r\n case \"stdio\":\r\n return \"stdio\";\r\n case \"http\":\r\n return \"streamable-http\";\r\n case \"sse\":\r\n return \"sse\";\r\n case \"ws\":\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Is `v` a CONCRETE version the MCP Registry accepts? The registry rejects\r\n * ranges (\"^1.2.3\", \"~1.2.3\", \">=1.2.3\", \"1.x\", \"1.*\"); only a pinned SemVer\r\n * (optionally with a -prerelease / +build suffix) is valid. \"0.0.0\" is concrete\r\n * (so it passes this guard) but is the unset placeholder — callers warn on it\r\n * separately via {@link isPlaceholderVersion}.\r\n */\r\nexport function isConcreteSemver(v: string): boolean {\r\n return /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(v);\r\n}\r\n\r\n/** The unset default version a connector ships with until the dev sets a real one. */\r\nexport function isPlaceholderVersion(v: string): boolean {\r\n return v === \"0.0.0\";\r\n}\r\n\r\n/**\r\n * Reverse-DNS registry namespace pattern (the part BEFORE the \"/\" in a\r\n * server.json `name`). The full name regex is\r\n * `^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$`; the namespace side allows letters, digits,\r\n * dots and hyphens (NO underscore) — e.g. \"io.github.acme\" or \"com.acme\".\r\n */\r\nexport const REGISTRY_NAMESPACE_RE = /^[a-zA-Z0-9.-]+$/;\r\n\r\n/** The full server.json `name` regex (namespace \"/\" server-name), per the schema. */\r\nexport const REGISTRY_NAME_RE = /^[a-zA-Z0-9.-]+\\/[a-zA-Z0-9._-]+$/;\r\n"],"mappings":"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","names":[]}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
resolveEnvRefsDeep
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-XXLCMSD3.js";
|
|
5
5
|
import {
|
|
6
6
|
BaseAdapter,
|
|
7
7
|
parseJsonc,
|
|
8
8
|
renderSkillMd
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-UNU2KPYJ.js";
|
|
10
10
|
import {
|
|
11
11
|
buildWrappedStdio
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-W7AGWAMH.js";
|
|
13
13
|
|
|
14
14
|
// src/adapters/openclaw/index.ts
|
|
15
15
|
import { existsSync, readFileSync } from "fs";
|
|
@@ -1008,4 +1008,4 @@ export {
|
|
|
1008
1008
|
adapter,
|
|
1009
1009
|
openclaw_default
|
|
1010
1010
|
};
|
|
1011
|
-
//# sourceMappingURL=chunk-
|
|
1011
|
+
//# sourceMappingURL=chunk-LD5HAN6O.js.map
|