@ken-jo/agent-connector 0.4.97 → 0.4.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -202
- package/NOTICE +6 -6
- package/README.md +604 -596
- package/dist/{action-IPFDPOZU.js → action-5OEM3QC4.js} +17 -16
- package/dist/action-5OEM3QC4.js.map +1 -0
- package/dist/{amazon-q-IT44LEWV.js → amazon-q-7DPVJXJN.js} +6 -6
- package/dist/amazon-q-7DPVJXJN.js.map +1 -0
- package/dist/{amp-CEWOSWQO.js → amp-BQZOL5GR.js} +4 -4
- package/dist/amp-BQZOL5GR.js.map +1 -0
- package/dist/{amp-P35FRU2Z.js → amp-VYXZWHXW.js} +7 -7
- package/dist/amp-VYXZWHXW.js.map +1 -0
- package/dist/{antigravity-LHFEFNMC.js → antigravity-EA4L225L.js} +5 -5
- package/dist/antigravity-EA4L225L.js.map +1 -0
- package/dist/antigravity-VXHL6ZPM.js +18 -0
- package/dist/{antigravity-cli-MOKFSWOU.js → antigravity-cli-B2HXZFYQ.js} +5 -5
- package/dist/antigravity-cli-B2HXZFYQ.js.map +1 -0
- package/dist/{antigravity-cli-MPE27LPI.js → antigravity-cli-JHQ7JGNX.js} +10 -9
- package/dist/antigravity-cli-JHQ7JGNX.js.map +1 -0
- package/dist/{audit-3E5JAOP2.js → audit-BO7JQYIH.js} +8 -8
- package/dist/{chunk-7C2IPIIB.js → chunk-2Y2MZRLP.js} +3 -3
- package/dist/chunk-2Y2MZRLP.js.map +1 -0
- package/dist/{chunk-GZZCHJDP.js → chunk-4KIXXJ7B.js} +2 -2
- package/dist/chunk-4KIXXJ7B.js.map +1 -0
- package/dist/chunk-4NFDNY3C.js +34 -0
- package/dist/chunk-4NFDNY3C.js.map +1 -0
- package/dist/{chunk-C63AAXK7.js → chunk-4QXCNZMD.js} +5 -5
- package/dist/chunk-4QXCNZMD.js.map +1 -0
- package/dist/{chunk-Q7PR2WGT.js → chunk-6TF7MHG5.js} +2 -2
- package/dist/chunk-6TF7MHG5.js.map +1 -0
- package/dist/{chunk-7ZFK2WEO.js → chunk-6WN37NVN.js} +113 -10
- package/dist/chunk-6WN37NVN.js.map +1 -0
- package/dist/{chunk-GCPEPUD7.js → chunk-6XMV2OOA.js} +6 -6
- package/dist/chunk-6XMV2OOA.js.map +1 -0
- package/dist/{chunk-XXLCMSD3.js → chunk-BEFVJ2OE.js} +1 -1
- package/dist/chunk-BEFVJ2OE.js.map +1 -0
- package/dist/{chunk-N4ENLZEU.js → chunk-BV5WK6VQ.js} +19 -19
- package/dist/chunk-BV5WK6VQ.js.map +1 -0
- package/dist/{chunk-WPTNMYYM.js → chunk-BXPSDNIB.js} +6 -6
- package/dist/chunk-BXPSDNIB.js.map +1 -0
- package/dist/{chunk-Q4ISQHUQ.js → chunk-FBJQGRET.js} +1 -1
- package/dist/chunk-FBJQGRET.js.map +1 -0
- package/dist/{chunk-THI4PI4H.js → chunk-FJCUKXGX.js} +2 -2
- package/dist/chunk-FJCUKXGX.js.map +1 -0
- package/dist/{chunk-L2C5UMKW.js → chunk-FKW5A6HE.js} +23 -7
- package/dist/chunk-FKW5A6HE.js.map +1 -0
- package/dist/{chunk-NDMNMAKP.js → chunk-G5HAIYRM.js} +43 -43
- package/dist/chunk-G5HAIYRM.js.map +1 -0
- package/dist/{chunk-SLJI5BOM.js → chunk-GDIAHWNY.js} +2 -2
- package/dist/chunk-GDIAHWNY.js.map +1 -0
- package/dist/{chunk-QYOUQCC6.js → chunk-GZGLCCEE.js} +1 -1
- package/dist/chunk-GZGLCCEE.js.map +1 -0
- package/dist/{chunk-PSGTHJQU.js → chunk-H53QZQJI.js} +1 -1
- package/dist/chunk-H53QZQJI.js.map +1 -0
- package/dist/{chunk-7HHW23AC.js → chunk-IRUYJD23.js} +29 -29
- package/dist/chunk-IRUYJD23.js.map +1 -0
- package/dist/{chunk-IOJDZJ72.js → chunk-IVAWP6HH.js} +2 -2
- package/dist/chunk-IVAWP6HH.js.map +1 -0
- package/dist/{chunk-3FINQ2ZF.js → chunk-JTN3AKZO.js} +30 -20
- package/dist/chunk-JTN3AKZO.js.map +1 -0
- package/dist/{chunk-4GH2KA7V.js → chunk-KHO5WNTP.js} +1 -1
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/{chunk-MLU7NDAZ.js → chunk-KLZBRNFP.js} +12 -12
- package/dist/chunk-KLZBRNFP.js.map +1 -0
- package/dist/{chunk-3EP5V2F4.js → chunk-M6OS4OLU.js} +3 -3
- package/dist/chunk-M6OS4OLU.js.map +1 -0
- package/dist/{chunk-UZZTWWGG.js → chunk-MQPNU2CY.js} +1 -1
- package/dist/chunk-MQPNU2CY.js.map +1 -0
- package/dist/{chunk-LQ55E7QI.js → chunk-N4STCQGP.js} +7 -7
- package/dist/chunk-N4STCQGP.js.map +1 -0
- package/dist/{chunk-KFPSJRHR.js → chunk-NBYKLUF6.js} +2 -2
- package/dist/chunk-NBYKLUF6.js.map +1 -0
- package/dist/{chunk-KM2YXO6V.js → chunk-O7SDRBVB.js} +1 -1
- package/dist/chunk-O7SDRBVB.js.map +1 -0
- package/dist/{chunk-LFWYYWLV.js → chunk-OP4KBXUO.js} +1 -1
- package/dist/chunk-OP4KBXUO.js.map +1 -0
- package/dist/{chunk-XN7S44U4.js → chunk-OPXAP3AC.js} +1 -1
- package/dist/chunk-OPXAP3AC.js.map +1 -0
- package/dist/{chunk-TGZFDXNH.js → chunk-PWCBWAM4.js} +6 -4
- package/dist/chunk-PWCBWAM4.js.map +1 -0
- package/dist/{chunk-Y3K6KJMS.js → chunk-QSY74NAP.js} +2 -2
- package/dist/chunk-QSY74NAP.js.map +1 -0
- package/dist/{chunk-ZSOS2KOR.js → chunk-RK6VBLXP.js} +1 -1
- package/dist/chunk-RK6VBLXP.js.map +1 -0
- package/dist/{chunk-FHYR5Q5T.js → chunk-SFY6YLVK.js} +19 -12
- package/dist/chunk-SFY6YLVK.js.map +1 -0
- package/dist/{chunk-C747DYNT.js → chunk-UM5S7DKK.js} +1 -1
- package/dist/chunk-UM5S7DKK.js.map +1 -0
- package/dist/{chunk-ILWHLGIC.js → chunk-UMQ6NBQR.js} +2 -2
- package/dist/chunk-UMQ6NBQR.js.map +1 -0
- package/dist/{chunk-7PSNXUFK.js → chunk-XD7MY6HB.js} +1 -1
- package/dist/chunk-XD7MY6HB.js.map +1 -0
- package/dist/{chunk-XVEJAFKW.js → chunk-XY3N2U6L.js} +5 -5
- package/dist/chunk-XY3N2U6L.js.map +1 -0
- package/dist/{chunk-XZWMJLIT.js → chunk-YT43MUSJ.js} +1 -1
- package/dist/chunk-YT43MUSJ.js.map +1 -0
- package/dist/{claude-code-QBWDT5RT.js → claude-code-LJ6DVXWQ.js} +24 -14
- package/dist/claude-code-LJ6DVXWQ.js.map +1 -0
- package/dist/{claude-code-FS42PXZO.js → claude-code-NMRKTAP7.js} +4 -4
- package/dist/claude-code-NMRKTAP7.js.map +1 -0
- package/dist/cli/sdk.js +7 -7
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{cline-JKEAYWVR.js → cline-JAPJNOZQ.js} +6 -6
- package/dist/cline-JAPJNOZQ.js.map +1 -0
- package/dist/{codebuddy-EB6EYPC3.js → codebuddy-GC7VAE2Y.js} +7 -7
- package/dist/codebuddy-GC7VAE2Y.js.map +1 -0
- package/dist/{codebuff-5RSXFU6G.js → codebuff-3VODFPD4.js} +6 -6
- package/dist/codebuff-3VODFPD4.js.map +1 -0
- package/dist/{codebuff-6KWBW6CT.js → codebuff-ETYT5UBL.js} +4 -4
- package/dist/codebuff-ETYT5UBL.js.map +1 -0
- package/dist/{codex-ART46CDD.js → codex-RXIS5BHM.js} +9 -9
- package/dist/codex-RXIS5BHM.js.map +1 -0
- package/dist/{codex-DKBAAUCO.js → codex-YAORPCOD.js} +4 -4
- package/dist/codex-YAORPCOD.js.map +1 -0
- package/dist/{continue-JHZCMSPH.js → continue-MECVDV4Z.js} +8 -8
- package/dist/continue-MECVDV4Z.js.map +1 -0
- package/dist/{copilot-cli-CLBJACQ5.js → copilot-cli-MZTAWMPW.js} +4 -4
- package/dist/copilot-cli-MZTAWMPW.js.map +1 -0
- package/dist/{copilot-cli-QVAU5CFM.js → copilot-cli-WVWAWNSM.js} +7 -7
- package/dist/copilot-cli-WVWAWNSM.js.map +1 -0
- package/dist/{crush-A5C5USRL.js → crush-QBXLNN7T.js} +4 -4
- package/dist/crush-QBXLNN7T.js.map +1 -0
- package/dist/{crush-7TORBYUL.js → crush-YB3SK6NK.js} +7 -7
- package/dist/crush-YB3SK6NK.js.map +1 -0
- package/dist/{cursor-D5SWDVSW.js → cursor-DIW43TRZ.js} +3 -3
- package/dist/cursor-DIW43TRZ.js.map +1 -0
- package/dist/cursor-RSLHA2CY.js +22 -0
- package/dist/{define-connector-DTWb46UB.d.ts → define-connector-odRHEC4H.d.ts} +1 -1
- package/dist/{detect-JHSA3G3U.js → detect-ALP4G7WG.js} +4 -4
- package/dist/detect-ALP4G7WG.js.map +1 -0
- package/dist/{devin-SSR7S4WX.js → devin-WPDN3MXE.js} +7 -7
- package/dist/devin-WPDN3MXE.js.map +1 -0
- package/dist/{doctor-CQJ7TZPA.js → doctor-YEQWCWZJ.js} +27 -26
- package/dist/doctor-YEQWCWZJ.js.map +1 -0
- package/dist/{droid-45PJ7JGF.js → droid-HS6MX3IL.js} +10 -8
- package/dist/droid-HS6MX3IL.js.map +1 -0
- package/dist/{droid-PFQ2PZSF.js → droid-U3ZBLQFO.js} +4 -4
- package/dist/droid-U3ZBLQFO.js.map +1 -0
- package/dist/{gemini-cli-Y6RJMU24.js → gemini-cli-NMVVBO3K.js} +4 -4
- package/dist/gemini-cli-NMVVBO3K.js.map +1 -0
- package/dist/{gemini-cli-24PFDK7D.js → gemini-cli-VJ6X5DNF.js} +8 -8
- package/dist/gemini-cli-VJ6X5DNF.js.map +1 -0
- package/dist/{goose-U5D3LCPC.js → goose-3X7ID7YW.js} +9 -9
- package/dist/goose-3X7ID7YW.js.map +1 -0
- package/dist/{goose-K2HKUTBK.js → goose-64V46Y2W.js} +4 -4
- package/dist/goose-64V46Y2W.js.map +1 -0
- package/dist/{grok-cli-L2MHAPBY.js → grok-cli-4VFVF2CQ.js} +7 -7
- package/dist/grok-cli-4VFVF2CQ.js.map +1 -0
- package/dist/{hermes-2S5JUTTJ.js → hermes-AIVUE7LX.js} +10 -8
- package/dist/hermes-AIVUE7LX.js.map +1 -0
- package/dist/{hermes-MF3NX4ZY.js → hermes-F3EGTK6N.js} +4 -4
- package/dist/hermes-F3EGTK6N.js.map +1 -0
- package/dist/{hook-VHICXHXL.js → hook-F63I3SD5.js} +17 -16
- package/dist/hook-F63I3SD5.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/{install-WLENR4KF.js → install-23WRRFBY.js} +21 -21
- package/dist/install-23WRRFBY.js.map +1 -0
- package/dist/{introspect-dNekqPDY.d.ts → introspect-gTx6GzpW.d.ts} +1 -1
- package/dist/{jetbrains-copilot-Z4FC3RM3.js → jetbrains-copilot-XBO2JZRO.js} +6 -6
- package/dist/jetbrains-copilot-XBO2JZRO.js.map +1 -0
- package/dist/{junie-ULGJJIHB.js → junie-UCOS6Q37.js} +6 -6
- package/dist/junie-UCOS6Q37.js.map +1 -0
- package/dist/{kilo-SMHPOHJ5.js → kilo-SW7BH6EG.js} +4 -4
- package/dist/kilo-SW7BH6EG.js.map +1 -0
- package/dist/{kilo-WWIJOVWD.js → kilo-T4OXNUYY.js} +8 -8
- package/dist/kilo-T4OXNUYY.js.map +1 -0
- package/dist/{kilo-cli-QKE2EQLS.js → kilo-cli-I2S3W245.js} +8 -8
- package/dist/kilo-cli-I2S3W245.js.map +1 -0
- package/dist/{kilo-cli-T2SRRRJS.js → kilo-cli-ZF272ZHN.js} +5 -5
- package/dist/kilo-cli-ZF272ZHN.js.map +1 -0
- package/dist/{kimi-MSIDEMCI.js → kimi-5FHEXGZD.js} +4 -4
- package/dist/kimi-5FHEXGZD.js.map +1 -0
- package/dist/{kimi-JMUFTVSF.js → kimi-VLSUFLYV.js} +7 -7
- package/dist/kimi-VLSUFLYV.js.map +1 -0
- package/dist/{kiro-UWUCRKR3.js → kiro-AQFXGOJX.js} +10 -8
- package/dist/kiro-AQFXGOJX.js.map +1 -0
- package/dist/{kiro-NYRRBIKW.js → kiro-WGOI5CGT.js} +4 -4
- package/dist/kiro-WGOI5CGT.js.map +1 -0
- package/dist/{leaderboard-NJWKGMXP.js → leaderboard-YBD3IKC2.js} +7 -7
- package/dist/leaderboard-YBD3IKC2.js.map +1 -0
- package/dist/{mimo-code-BPNYYIVM.js → mimo-code-KETL7W7D.js} +7 -7
- package/dist/mimo-code-KETL7W7D.js.map +1 -0
- package/dist/{mistral-vibe-LT3DAJ3L.js → mistral-vibe-3AU7N2CA.js} +6 -6
- package/dist/mistral-vibe-3AU7N2CA.js.map +1 -0
- package/dist/{mux-AHNUAY5Z.js → mux-BO2L5CTW.js} +6 -6
- package/dist/mux-BO2L5CTW.js.map +1 -0
- package/dist/{mux-7PIJ7HUQ.js → mux-XM6AP35L.js} +4 -4
- package/dist/mux-XM6AP35L.js.map +1 -0
- package/dist/{nemoclaw-RE5RZASZ.js → nemoclaw-WA7RSKF2.js} +7 -7
- package/dist/nemoclaw-WA7RSKF2.js.map +1 -0
- package/dist/{omp-D2EXEPH7.js → omp-UDYJ2PYY.js} +9 -7
- package/dist/omp-UDYJ2PYY.js.map +1 -0
- package/dist/{open-interpreter-SSGBEUKX.js → open-interpreter-WMBNM4MQ.js} +6 -6
- package/dist/open-interpreter-WMBNM4MQ.js.map +1 -0
- package/dist/openclaw-3DHVHX5P.js +17 -0
- package/dist/{openclaw-KAFTNLR2.js → openclaw-5EQFGOWL.js} +4 -4
- package/dist/openclaw-5EQFGOWL.js.map +1 -0
- package/dist/{opencode-YKUKZY3J.js → opencode-IKMI3RI7.js} +7 -7
- package/dist/opencode-IKMI3RI7.js.map +1 -0
- package/dist/{opencode-Z65JYILL.js → opencode-QGP4ALQY.js} +4 -4
- package/dist/opencode-QGP4ALQY.js.map +1 -0
- package/dist/{openhands-SEZMCUC3.js → openhands-QGXMQR6I.js} +7 -7
- package/dist/openhands-QGXMQR6I.js.map +1 -0
- package/dist/{package-JECVQEFT.js → package-TAUTPP7Z.js} +15 -15
- package/dist/package-TAUTPP7Z.js.map +1 -0
- package/dist/{pi-YPYV2ULH.js → pi-A2HCGRJG.js} +9 -7
- package/dist/pi-A2HCGRJG.js.map +1 -0
- package/dist/{pi-DLKCPOJE.js → pi-GGDQREVG.js} +4 -4
- package/dist/pi-GGDQREVG.js.map +1 -0
- package/dist/{qwen-code-ZHCLCYMC.js → qwen-code-DNQTGJOF.js} +35 -17
- package/dist/qwen-code-DNQTGJOF.js.map +1 -0
- package/dist/{qwen-code-26CSFDX6.js → qwen-code-GQILBJ5B.js} +4 -4
- package/dist/qwen-code-GQILBJ5B.js.map +1 -0
- package/dist/{roo-code-HSAE2CJU.js → roo-code-SUWI4BBN.js} +4 -4
- package/dist/roo-code-SUWI4BBN.js.map +1 -0
- package/dist/{roo-code-7F4HYB34.js → roo-code-VI2ZKTZC.js} +6 -6
- package/dist/roo-code-VI2ZKTZC.js.map +1 -0
- package/dist/runtime/index.d.ts +9 -8
- package/dist/runtime/index.js +15 -14
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +12 -11
- package/dist/{serve-LYSBH43G.js → serve-6MDLRQS2.js} +17 -16
- package/dist/serve-6MDLRQS2.js.map +1 -0
- package/dist/{status-PHKKGEW5.js → status-IUP75XHP.js} +11 -11
- package/dist/status-IUP75XHP.js.map +1 -0
- package/dist/{statusline-ZDD4OZ4F.js → statusline-PRODZV2J.js} +16 -15
- package/dist/statusline-PRODZV2J.js.map +1 -0
- package/dist/{synthetic-LUT6V6SD.js → synthetic-6FRA7P5Q.js} +4 -4
- package/dist/synthetic-6FRA7P5Q.js.map +1 -0
- package/dist/{telemetry-HDGMI2BK.js → telemetry-X4PLZEDB.js} +10 -10
- package/dist/telemetry-X4PLZEDB.js.map +1 -0
- package/dist/{trae-SIQI3C66.js → trae-CPPYASR2.js} +4 -4
- package/dist/trae-CPPYASR2.js.map +1 -0
- package/dist/{trae-Y67HSDOW.js → trae-VOJXUYRN.js} +6 -6
- package/dist/trae-VOJXUYRN.js.map +1 -0
- package/dist/{types-JyhpJHJa.d.ts → types-DWXnnx-N.d.ts} +96 -22
- package/dist/{uninstall-RWO2GM2I.js → uninstall-BSIJ4QXN.js} +21 -21
- package/dist/uninstall-BSIJ4QXN.js.map +1 -0
- package/dist/{upgrade-YJCXNUEE.js → upgrade-ZSICU3NE.js} +21 -21
- package/dist/upgrade-ZSICU3NE.js.map +1 -0
- package/dist/{usage-IWO4RQN6.js → usage-EQUNVSCT.js} +4 -4
- package/dist/usage-EQUNVSCT.js.map +1 -0
- package/dist/{usage-event-AFFKCLHE.js → usage-event-J5CQ6LNT.js} +16 -15
- package/dist/usage-event-J5CQ6LNT.js.map +1 -0
- package/dist/{vscode-copilot-5CI5B3X6.js → vscode-copilot-ZBXRPKGG.js} +7 -7
- package/dist/vscode-copilot-ZBXRPKGG.js.map +1 -0
- package/dist/{warp-5YBSP7FP.js → warp-NRBBJQR2.js} +4 -4
- package/dist/warp-NRBBJQR2.js.map +1 -0
- package/dist/{warp-INAKVGBV.js → warp-S444B2S3.js} +9 -7
- package/dist/warp-S444B2S3.js.map +1 -0
- package/dist/{windsurf-4HM57QAY.js → windsurf-R6D2JUTN.js} +6 -6
- package/dist/windsurf-R6D2JUTN.js.map +1 -0
- package/dist/{zed-YN5X37PQ.js → zed-DQV3ZUCU.js} +10 -8
- package/dist/zed-DQV3ZUCU.js.map +1 -0
- package/dist/{zed-XXCNYOIN.js → zed-XJFOOKCO.js} +4 -4
- package/dist/zed-XJFOOKCO.js.map +1 -0
- package/package.json +88 -88
- package/dist/action-IPFDPOZU.js.map +0 -1
- package/dist/amazon-q-IT44LEWV.js.map +0 -1
- package/dist/amp-CEWOSWQO.js.map +0 -1
- package/dist/amp-P35FRU2Z.js.map +0 -1
- package/dist/antigravity-LHFEFNMC.js.map +0 -1
- package/dist/antigravity-TWIWXTQH.js +0 -18
- package/dist/antigravity-cli-MOKFSWOU.js.map +0 -1
- package/dist/antigravity-cli-MPE27LPI.js.map +0 -1
- package/dist/chunk-3EP5V2F4.js.map +0 -1
- package/dist/chunk-3FINQ2ZF.js.map +0 -1
- package/dist/chunk-4GH2KA7V.js.map +0 -1
- package/dist/chunk-7C2IPIIB.js.map +0 -1
- package/dist/chunk-7HHW23AC.js.map +0 -1
- package/dist/chunk-7PSNXUFK.js.map +0 -1
- package/dist/chunk-7ZFK2WEO.js.map +0 -1
- package/dist/chunk-C63AAXK7.js.map +0 -1
- package/dist/chunk-C747DYNT.js.map +0 -1
- package/dist/chunk-FHYR5Q5T.js.map +0 -1
- package/dist/chunk-GCPEPUD7.js.map +0 -1
- package/dist/chunk-GZZCHJDP.js.map +0 -1
- package/dist/chunk-ILWHLGIC.js.map +0 -1
- package/dist/chunk-IOJDZJ72.js.map +0 -1
- package/dist/chunk-KFPSJRHR.js.map +0 -1
- package/dist/chunk-KM2YXO6V.js.map +0 -1
- package/dist/chunk-L2C5UMKW.js.map +0 -1
- package/dist/chunk-LFWYYWLV.js.map +0 -1
- package/dist/chunk-LQ55E7QI.js.map +0 -1
- package/dist/chunk-MLU7NDAZ.js.map +0 -1
- package/dist/chunk-N4ENLZEU.js.map +0 -1
- package/dist/chunk-NDMNMAKP.js.map +0 -1
- package/dist/chunk-PSGTHJQU.js.map +0 -1
- package/dist/chunk-Q4ISQHUQ.js.map +0 -1
- package/dist/chunk-Q7PR2WGT.js.map +0 -1
- package/dist/chunk-QYOUQCC6.js.map +0 -1
- package/dist/chunk-SLJI5BOM.js.map +0 -1
- package/dist/chunk-TGZFDXNH.js.map +0 -1
- package/dist/chunk-THI4PI4H.js.map +0 -1
- package/dist/chunk-UZZTWWGG.js.map +0 -1
- package/dist/chunk-WPTNMYYM.js.map +0 -1
- package/dist/chunk-XN7S44U4.js.map +0 -1
- package/dist/chunk-XVEJAFKW.js.map +0 -1
- package/dist/chunk-XXLCMSD3.js.map +0 -1
- package/dist/chunk-XZWMJLIT.js.map +0 -1
- package/dist/chunk-Y3K6KJMS.js.map +0 -1
- package/dist/chunk-ZSOS2KOR.js.map +0 -1
- package/dist/claude-code-FS42PXZO.js.map +0 -1
- package/dist/claude-code-QBWDT5RT.js.map +0 -1
- package/dist/cline-JKEAYWVR.js.map +0 -1
- package/dist/codebuddy-EB6EYPC3.js.map +0 -1
- package/dist/codebuff-5RSXFU6G.js.map +0 -1
- package/dist/codebuff-6KWBW6CT.js.map +0 -1
- package/dist/codex-ART46CDD.js.map +0 -1
- package/dist/codex-DKBAAUCO.js.map +0 -1
- package/dist/continue-JHZCMSPH.js.map +0 -1
- package/dist/copilot-cli-CLBJACQ5.js.map +0 -1
- package/dist/copilot-cli-QVAU5CFM.js.map +0 -1
- package/dist/crush-7TORBYUL.js.map +0 -1
- package/dist/crush-A5C5USRL.js.map +0 -1
- package/dist/cursor-D5SWDVSW.js.map +0 -1
- package/dist/cursor-W7I4QUFO.js +0 -22
- package/dist/detect-JHSA3G3U.js.map +0 -1
- package/dist/devin-SSR7S4WX.js.map +0 -1
- package/dist/doctor-CQJ7TZPA.js.map +0 -1
- package/dist/droid-45PJ7JGF.js.map +0 -1
- package/dist/droid-PFQ2PZSF.js.map +0 -1
- package/dist/gemini-cli-24PFDK7D.js.map +0 -1
- package/dist/gemini-cli-Y6RJMU24.js.map +0 -1
- package/dist/goose-K2HKUTBK.js.map +0 -1
- package/dist/goose-U5D3LCPC.js.map +0 -1
- package/dist/grok-cli-L2MHAPBY.js.map +0 -1
- package/dist/hermes-2S5JUTTJ.js.map +0 -1
- package/dist/hermes-MF3NX4ZY.js.map +0 -1
- package/dist/hook-VHICXHXL.js.map +0 -1
- package/dist/install-WLENR4KF.js.map +0 -1
- package/dist/jetbrains-copilot-Z4FC3RM3.js.map +0 -1
- package/dist/junie-ULGJJIHB.js.map +0 -1
- package/dist/kilo-SMHPOHJ5.js.map +0 -1
- package/dist/kilo-WWIJOVWD.js.map +0 -1
- package/dist/kilo-cli-QKE2EQLS.js.map +0 -1
- package/dist/kilo-cli-T2SRRRJS.js.map +0 -1
- package/dist/kimi-JMUFTVSF.js.map +0 -1
- package/dist/kimi-MSIDEMCI.js.map +0 -1
- package/dist/kiro-NYRRBIKW.js.map +0 -1
- package/dist/kiro-UWUCRKR3.js.map +0 -1
- package/dist/leaderboard-NJWKGMXP.js.map +0 -1
- package/dist/mimo-code-BPNYYIVM.js.map +0 -1
- package/dist/mistral-vibe-LT3DAJ3L.js.map +0 -1
- package/dist/mux-7PIJ7HUQ.js.map +0 -1
- package/dist/mux-AHNUAY5Z.js.map +0 -1
- package/dist/nemoclaw-RE5RZASZ.js.map +0 -1
- package/dist/omp-D2EXEPH7.js.map +0 -1
- package/dist/open-interpreter-SSGBEUKX.js.map +0 -1
- package/dist/openclaw-IJ33K45M.js +0 -17
- package/dist/openclaw-KAFTNLR2.js.map +0 -1
- package/dist/opencode-YKUKZY3J.js.map +0 -1
- package/dist/opencode-Z65JYILL.js.map +0 -1
- package/dist/openhands-SEZMCUC3.js.map +0 -1
- package/dist/package-JECVQEFT.js.map +0 -1
- package/dist/pi-DLKCPOJE.js.map +0 -1
- package/dist/pi-YPYV2ULH.js.map +0 -1
- package/dist/qwen-code-26CSFDX6.js.map +0 -1
- package/dist/qwen-code-ZHCLCYMC.js.map +0 -1
- package/dist/roo-code-7F4HYB34.js.map +0 -1
- package/dist/roo-code-HSAE2CJU.js.map +0 -1
- package/dist/serve-LYSBH43G.js.map +0 -1
- package/dist/status-PHKKGEW5.js.map +0 -1
- package/dist/statusline-ZDD4OZ4F.js.map +0 -1
- package/dist/synthetic-LUT6V6SD.js.map +0 -1
- package/dist/telemetry-HDGMI2BK.js.map +0 -1
- package/dist/trae-SIQI3C66.js.map +0 -1
- package/dist/trae-Y67HSDOW.js.map +0 -1
- package/dist/uninstall-RWO2GM2I.js.map +0 -1
- package/dist/upgrade-YJCXNUEE.js.map +0 -1
- package/dist/usage-IWO4RQN6.js.map +0 -1
- package/dist/usage-event-AFFKCLHE.js.map +0 -1
- package/dist/vscode-copilot-5CI5B3X6.js.map +0 -1
- package/dist/warp-5YBSP7FP.js.map +0 -1
- package/dist/warp-INAKVGBV.js.map +0 -1
- package/dist/windsurf-4HM57QAY.js.map +0 -1
- package/dist/zed-XXCNYOIN.js.map +0 -1
- package/dist/zed-YN5X37PQ.js.map +0 -1
- /package/dist/{antigravity-TWIWXTQH.js.map → antigravity-VXHL6ZPM.js.map} +0 -0
- /package/dist/{audit-3E5JAOP2.js.map → audit-BO7JQYIH.js.map} +0 -0
- /package/dist/{cursor-W7I4QUFO.js.map → cursor-RSLHA2CY.js.map} +0 -0
- /package/dist/{openclaw-IJ33K45M.js.map → openclaw-3DHVHX5P.js.map} +0 -0
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
readJsonFile,
|
|
4
4
|
readJsonlLines
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-RK6VBLXP.js";
|
|
6
6
|
import {
|
|
7
7
|
firstExistingRoot,
|
|
8
8
|
walkFiles
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-O7SDRBVB.js";
|
|
10
10
|
import {
|
|
11
11
|
emptyTokens,
|
|
12
12
|
inferProvider
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XD7MY6HB.js";
|
|
14
14
|
|
|
15
15
|
// src/usage/readers/droid.ts
|
|
16
16
|
import { statSync } from "fs";
|
|
@@ -221,4 +221,4 @@ var droid_default = droidReader;
|
|
|
221
221
|
export {
|
|
222
222
|
droid_default as default
|
|
223
223
|
};
|
|
224
|
-
//# sourceMappingURL=droid-
|
|
224
|
+
//# sourceMappingURL=droid-U3ZBLQFO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/usage/readers/droid.ts"],"sourcesContent":["/**\n * usage/readers/droid — Droid (Factory.ai) native session-settings reader.\n *\n * Faithful port of tokscale sessions/droid.rs. Reads\n * ~/.factory/sessions/*.settings.json. Each settings file is a single JSON\n * object carrying a cumulative `tokenUsage` block for one session:\n * tokenUsage.inputTokens → input\n * tokenUsage.outputTokens → output\n * tokenUsage.cacheReadTokens → cacheRead\n * tokenUsage.cacheCreationTokens → cacheWrite\n * tokenUsage.thinkingTokens → reasoning\n * A file with no tokenUsage, or whose five dimensions sum to 0, yields no row.\n *\n * Model id comes from the `model` field run through Droid's custom normalization\n * (strip a `custom:` prefix, remove [bracket] groups, trim trailing hyphens,\n * lowercase, dots→hyphens, collapse repeated hyphens — e.g.\n * \"custom:Claude-Opus-4.5-Thinking-[Anthropic]-0\" → \"claude-opus-4-5-thinking-0\").\n * When `model` is absent it falls back to scanning the sibling .jsonl\n * (<id>.settings.json → <id>.jsonl) for a `Model:` system-reminder pattern, and\n * finally to a provider-based default (anthropic→claude-unknown, openai→gpt-unknown,\n * google→gemini-unknown, xai→grok-unknown, else <provider>-unknown).\n *\n * Provider prefers the `providerLock` field; otherwise it is inferred from the\n * model (defaulting to \"unknown\", matching the Rust `unwrap_or(\"unknown\")`).\n *\n * Session id is the filename stem with `.settings` stripped\n * (uuid.settings.json → uuid). Timestamp prefers `providerLockTimestamp`\n * (RFC3339 → epoch ms), falling back to the file mtime; a row with no usable\n * timestamp (0) is dropped — to match the Rust mtime-or-0 path, an unreadable\n * mtime is treated as 0 (not \"now\"), so we do not synthesize a timestamp here.\n *\n * No dedup (the session id is the primary key) and no project attribution\n * (Droid settings carry neither). Confidence is \"host-reported\".\n *\n * Fail-open: no root → []; unreadable/malformed file → skipped.\n */\n\nimport { statSync } from \"node:fs\";\nimport { basename } from \"node:path\";\n\nimport type { UsageReader, UsageRecord } from \"../types.js\";\nimport { emptyTokens } from \"../aggregate.js\";\nimport { readJsonFile, readJsonlLines } from \"../jsonl.js\";\nimport { inferProvider } from \"../normalize.js\";\nimport { firstExistingRoot, walkFiles } from \"../paths.js\";\n\nconst PLATFORM_ID = \"droid\" as const;\nconst DEFAULT_PROVIDER = \"unknown\";\n/** Cap matching the Rust scan (avoids slurping a huge sibling .jsonl). */\nconst JSONL_MODEL_SCAN_LIMIT = 500;\n\n/** The fields we read off a Droid settings.json file (all optional / unknown). */\ninterface DroidSettings {\n model?: unknown;\n providerLock?: unknown;\n providerLockTimestamp?: unknown;\n tokenUsage?: {\n inputTokens?: unknown;\n outputTokens?: unknown;\n cacheCreationTokens?: unknown;\n cacheReadTokens?: unknown;\n thinkingTokens?: unknown;\n };\n}\n\n/** Coerce an unknown to a non-negative integer (0 on absence/garbage). */\nfunction toNonNegInt(v: unknown): number {\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\n if (!Number.isFinite(n)) return 0;\n return Math.max(0, Math.trunc(n));\n}\n\n/**\n * Normalize a model name from Droid's custom format (port of\n * droid.rs normalize_model_name). Order is load-bearing:\n * 1. strip a leading `custom:` prefix;\n * 2. remove every `[...]` bracket group (vendor tags like \"[Anthropic]\");\n * 3. trim trailing hyphens (NOT trailing digits — those are kept);\n * 4. lowercase;\n * 5. replace dots with hyphens;\n * 6. collapse runs of hyphens into one.\n */\nfunction normalizeModelName(model: string): string {\n let normalized = model.startsWith(\"custom:\") ? model.slice(\"custom:\".length) : model;\n\n // Remove [anything] groups (mirrors /\\[.*?\\]/g — bracket-depth-agnostic, just\n // drops chars while inside a bracket span).\n let stripped = \"\";\n let inBracket = false;\n for (const ch of normalized) {\n if (ch === \"[\") inBracket = true;\n else if (ch === \"]\") inBracket = false;\n else if (!inBracket) stripped += ch;\n }\n normalized = stripped;\n\n // Trim trailing hyphens only (mirrors /-+$/), keep trailing digits.\n normalized = normalized.replace(/-+$/, \"\");\n\n normalized = normalized.toLowerCase();\n normalized = normalized.replace(/\\./g, \"-\");\n\n // Collapse consecutive hyphens (mirrors /-+/g → \"-\").\n normalized = normalized.replace(/-+/g, \"-\");\n\n return normalized;\n}\n\n/**\n * Canonicalize a provider segment (port of the subset of\n * provider_identity.rs canonicalize_provider_segment needed by\n * get_default_model_from_provider). Returns the input lowercased/`-`→`_` when no\n * canonical alias applies, so the default-model switch can match cleanly.\n */\nfunction canonicalizeProviderSegment(segment: string): string | undefined {\n const normalized = segment.trim().replace(/\\/+$/, \"\").toLowerCase().replace(/-/g, \"_\");\n if (normalized.startsWith(\"<\") && normalized.endsWith(\">\")) return undefined;\n switch (normalized) {\n case \"\":\n case \"unknown\":\n return undefined;\n case \"x_ai\":\n case \"xai\":\n return \"xai\";\n case \"z_ai\":\n case \"zai\":\n return \"zai\";\n case \"moonshot\":\n case \"moonshotai\":\n return \"moonshotai\";\n case \"meta\":\n case \"meta_llama\":\n return \"meta_llama\";\n case \"azure\":\n case \"azure_ai\":\n return \"azure_ai\";\n case \"anthropic\":\n case \"vertex\":\n case \"vertex_ai\":\n return \"anthropic\";\n case \"together\":\n case \"together_ai\":\n return \"together_ai\";\n case \"fireworks\":\n case \"fireworks_ai\":\n return \"fireworks_ai\";\n case \"google\":\n case \"gemini\":\n return \"google\";\n case \"openai\":\n case \"openai_codex\":\n return \"openai\";\n case \"minimax\":\n case \"minimaxai\":\n case \"minimax_ai\":\n return \"minimax\";\n case \"mistral\":\n case \"mistralai\":\n return \"mistralai\";\n case \"ai21\":\n return \"ai21\";\n default:\n // Reject segments containing digits (model-name fragments, not providers).\n if (/[0-9]/.test(normalized)) return undefined;\n return normalized;\n }\n}\n\n/** Port of canonical_provider: first non-empty canonical tag, or the raw fallback. */\nfunction canonicalProvider(raw: string): string {\n for (const segment of raw.trim().replace(/\\/+$/, \"\").split(\"/\")) {\n const tag = canonicalizeProviderSegment(segment);\n if (tag !== undefined) return tag;\n if (segment.includes(\".\")) {\n for (const dotted of segment.split(\".\")) {\n const dottedTag = canonicalizeProviderSegment(dotted);\n if (dottedTag !== undefined) return dottedTag;\n }\n }\n }\n return raw;\n}\n\n/**\n * Provider-based default model when no model id is available (port of\n * get_default_model_from_provider).\n */\nfunction defaultModelFromProvider(provider: string): string {\n switch (canonicalProvider(provider)) {\n case \"anthropic\":\n return \"claude-unknown\";\n case \"openai\":\n return \"gpt-unknown\";\n case \"google\":\n return \"gemini-unknown\";\n case \"xai\":\n return \"grok-unknown\";\n default:\n return `${provider}-unknown`;\n }\n}\n\n/**\n * Try to extract a model name from the sibling .jsonl by scanning early lines\n * for a `Model:` system-reminder (port of extract_model_from_jsonl). The value\n * runs from after `Model:` up to the first `[`, `\\`, or `\"`, trimmed; the result\n * is run through normalizeModelName. Returns undefined when nothing matches.\n */\nfunction extractModelFromJsonl(jsonlPath: string): string | undefined {\n // readJsonlLines is fail-open ([] on a missing/unreadable file); we scan the\n // raw text of each parsed line's stringification is not what Rust does — Rust\n // scans raw file lines, so we read the lines as-is via the tolerant reader and\n // search their original text. Since readJsonlLines parses JSON, re-serialize is\n // lossy; instead search the parsed objects' stringified form, which preserves\n // the embedded \"Model:\" text that lives inside string fields.\n const lines = readJsonlLines(jsonlPath);\n const scan = lines.slice(0, JSONL_MODEL_SCAN_LIMIT);\n for (const obj of scan) {\n const text = typeof obj === \"string\" ? obj : JSON.stringify(obj);\n const pos = text.indexOf(\"Model:\");\n if (pos < 0) continue;\n const after = text.slice(pos + \"Model:\".length);\n let modelPart = \"\";\n for (const ch of after) {\n if (ch === \"[\" || ch === \"\\\\\" || ch === '\"') break;\n modelPart += ch;\n }\n const trimmed = modelPart.trim();\n if (trimmed !== \"\") return normalizeModelName(trimmed);\n }\n return undefined;\n}\n\n/** File mtime in epoch ms, or 0 when unreadable (matches the Rust mtime-or-0 path). */\nfunction fileMtimeOrZero(path: string): number {\n try {\n return Math.floor(statSync(path).mtimeMs);\n } catch {\n return 0;\n }\n}\n\n/** Session id from a settings filename: stem with a trailing `.settings` removed. */\nfunction sessionIdFromPath(path: string): string {\n const name = basename(path);\n // Drop a final extension (the `.json`), then strip `.settings`.\n const dot = name.lastIndexOf(\".\");\n const stem = dot > 0 ? name.slice(0, dot) : name;\n const id = stem.replace(/\\.settings$/, \"\");\n return id === \"\" ? \"unknown\" : id;\n}\n\n/** Parse one Droid settings.json file into usage records (port of parse_droid_file). */\nfunction parseDroidFile(path: string): UsageRecord[] {\n const raw = readJsonFile(path);\n if (typeof raw !== \"object\" || raw === null) return [];\n const settings = raw as DroidSettings;\n\n const usage = settings.tokenUsage;\n if (usage === undefined || usage === null || typeof usage !== \"object\") return [];\n\n const input = toNonNegInt(usage.inputTokens);\n const output = toNonNegInt(usage.outputTokens);\n const cacheWrite = toNonNegInt(usage.cacheCreationTokens);\n const cacheRead = toNonNegInt(usage.cacheReadTokens);\n const reasoning = toNonNegInt(usage.thinkingTokens);\n\n // Skip sessions with no usage at all.\n if (input + output + cacheWrite + cacheRead + reasoning === 0) return [];\n\n const sessionId = sessionIdFromPath(path);\n\n // Provider: providerLock if a non-empty string, else inferred from the model\n // (defaulting to \"unknown\" — matches the Rust unwrap_or(\"unknown\")).\n const providerLock =\n typeof settings.providerLock === \"string\" && settings.providerLock !== \"\"\n ? settings.providerLock\n : undefined;\n const modelField = typeof settings.model === \"string\" ? settings.model : undefined;\n const providerId =\n providerLock ?? inferProvider(modelField ?? \"\") ?? DEFAULT_PROVIDER;\n\n // Model: normalize the model field, else scan the sibling .jsonl, else default.\n let modelId: string;\n if (modelField !== undefined) {\n modelId = normalizeModelName(modelField);\n } else {\n const jsonlPath = path.replace(/\\.settings\\.json$/, \".jsonl\");\n modelId = jsonlPath !== path\n ? extractModelFromJsonl(jsonlPath) ?? defaultModelFromProvider(providerId)\n : defaultModelFromProvider(providerId);\n }\n\n // Timestamp: providerLockTimestamp (RFC3339 → ms) else file mtime; 0 → drop.\n let ts = 0;\n if (typeof settings.providerLockTimestamp === \"string\") {\n const parsed = Date.parse(settings.providerLockTimestamp);\n if (!Number.isNaN(parsed)) ts = parsed;\n }\n if (ts === 0) ts = fileMtimeOrZero(path);\n if (ts === 0) return [];\n\n const tokens = emptyTokens();\n tokens.input = input;\n tokens.output = output;\n tokens.cacheRead = cacheRead;\n tokens.cacheWrite = cacheWrite;\n tokens.reasoning = reasoning;\n\n return [\n {\n platformId: PLATFORM_ID,\n modelId,\n providerId,\n sessionId,\n tokens,\n ts,\n messageCount: 1,\n confidence: \"host-reported\",\n },\n ];\n}\n\n/** The Droid (Factory.ai) usage reader singleton. */\nconst droidReader: UsageReader = {\n platformId: PLATFORM_ID,\n kind: \"local\",\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\n const root = firstExistingRoot(PLATFORM_ID);\n if (root === undefined) return []; // no ~/.factory/sessions → fail-open\n\n // ~/.factory/sessions/*.settings.json\n const files = walkFiles(root, (name) => name.endsWith(\".settings.json\"));\n\n const records: UsageRecord[] = [];\n for (const file of files) {\n const rows = parseDroidFile(file);\n for (const row of rows) {\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\n records.push(row);\n }\n }\n return records;\n },\n};\n\nexport default droidReader;\n"],"mappings":"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","names":[]}
|
|
@@ -3,14 +3,14 @@ import {
|
|
|
3
3
|
fileMtimeMs,
|
|
4
4
|
readJsonFile,
|
|
5
5
|
readJsonlLines
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-RK6VBLXP.js";
|
|
7
7
|
import {
|
|
8
8
|
firstExistingRoot,
|
|
9
9
|
walkFiles
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-O7SDRBVB.js";
|
|
11
11
|
import {
|
|
12
12
|
emptyTokens
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XD7MY6HB.js";
|
|
14
14
|
|
|
15
15
|
// src/usage/readers/gemini-cli.ts
|
|
16
16
|
import { basename } from "path";
|
|
@@ -366,4 +366,4 @@ var gemini_cli_default = geminiReader;
|
|
|
366
366
|
export {
|
|
367
367
|
gemini_cli_default as default
|
|
368
368
|
};
|
|
369
|
-
//# sourceMappingURL=gemini-cli-
|
|
369
|
+
//# sourceMappingURL=gemini-cli-NMVVBO3K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/usage/readers/gemini-cli.ts"],"sourcesContent":["/**\n * usage/readers/gemini-cli — Gemini CLI native session-log reader.\n *\n * Faithful port of tokscale sessions/gemini.rs. Reads ~/.gemini/tmp/ recursively\n * and supports the three on-disk shapes the Gemini CLI has shipped:\n * 1. legacy structured JSON — `session-*.json` with a top-level\n * { sessionId, messages: [{ type, model, timestamp, tokens }] } object;\n * 2. headless single-value JSON — one object carrying either a direct `tokens`\n * block (type:\"gemini\") or a `stats` / `result.stats` rollup;\n * 3. headless JSONL stream — newline-delimited events: `init` (carries\n * model + session_id), direct-token `gemini` events (keyed by `id`), and\n * `result`/`stats` rollups.\n *\n * Discovery (port of the path filter in parse_gemini_file_with_cache_status):\n * - legacy files whose name starts with \"session-\" are accepted on ANY path;\n * - any other file must sit at exactly `.../tmp/<id>/chats/<file>` (the three\n * components right after a `tmp` segment), so a backup/nested chats dir is\n * rejected. Both .json and .jsonl are read.\n *\n * Token fields (alias list honored exactly as gemini.rs first_i64 / extract_*):\n * input ← input, prompt, input_tokens, prompt_tokens, promptTokenCount\n * output ← output, candidates, output_tokens, completion_tokens,\n * candidates_tokens, candidatesTokenCount\n * cacheRead ← cached, cached_tokens, cachedContentTokenCount\n * reasoning ← thoughts, reasoning, thoughts_tokens, reasoning_tokens\n * tool ← tool, tool_tokens (folded INTO input after normalization)\n * total ← total, totalTokenCount, total_tokens\n * cacheWrite is always 0 (Gemini does not report it).\n *\n * Cache-inclusive input normalization (matches gemini.rs exactly):\n * - structured session messages: promptTokenCount is normally cache-inclusive.\n * normalize_gemini_session_input_and_cache only subtracts the cached portion\n * when a `total` is present AND total == input+output+reasoning+tool (i.e.\n * cached is NOT already counted in input); otherwise input is left as-is.\n * Then `tool` is added to the (possibly net) input.\n * - headless stats: when the chosen input alias is a cache-INCLUSIVE one\n * (prompt*, or a `tokens`-wrapper `input`, or the only alias present),\n * subtract the cached overlap (clamped ≥ 0); when a net `input` alias was\n * used directly, keep it as-is.\n *\n * Dedup (the double-count guard): within a single JSONL file, direct-token\n * events carrying an `id` are deduped LAST-WINS — a later event with the same id\n * replaces the earlier one (port of direct_message_indices HashMap). Stats-\n * derived rows and id-less direct rows are never deduped. The cross-file\n * dedupKey we expose is `<sessionId>:<id>` for the keyed direct rows.\n *\n * Provider is hard-coded \"google\", confidence \"host-reported\".\n *\n * Fail-open: no ~/.gemini/tmp → []; unreadable/malformed file or line → skipped.\n */\n\nimport { basename } from \"node:path\";\n\nimport type { UsageReader, UsageRecord } from \"../types.js\";\nimport { emptyTokens } from \"../aggregate.js\";\nimport { fileMtimeMs, readJsonFile, readJsonlLines } from \"../jsonl.js\";\nimport { firstExistingRoot, walkFiles } from \"../paths.js\";\n\nconst PLATFORM_ID = \"gemini-cli\" as const;\nconst PROVIDER = \"google\";\nconst DEFAULT_MODEL = \"unknown\";\n\n// ─────────────────────────────────────────────────────────────────────────\n// Scalar coercion (ports of utils.rs extract_i64 / extract_string)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** extract_i64: number (int or via Number) or a numeric string → integer, else null. */\nfunction extractI64(v: unknown): number | null {\n if (typeof v === \"number\" && Number.isFinite(v)) return Math.trunc(v);\n if (typeof v === \"string\") {\n const n = Number(v);\n if (Number.isInteger(n)) return n;\n }\n return null;\n}\n\n/** extract_string: a non-undefined string value, else null. */\nfunction extractString(v: unknown): string | null {\n return typeof v === \"string\" ? v : null;\n}\n\n/** first_i64(value, keys): first key whose value coerces to an integer. */\nfunction firstI64(obj: Record<string, unknown>, keys: readonly string[]): number | null {\n for (const k of keys) {\n const got = extractI64(obj[k]);\n if (got !== null) return got;\n }\n return null;\n}\n\n/** Clamp to a non-negative integer (the Rust `.max(0)` on i64 values). */\nfunction nonNeg(n: number): number {\n return n > 0 ? Math.trunc(n) : 0;\n}\n\n/** Saturating add of two non-negative ints (i64 saturating_add ≈ JS add for our ranges). */\nfunction satAdd(a: number, b: number): number {\n return a + b;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Timestamp (ports of utils.rs parse_timestamp_value + extract_timestamp_from_value)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** parse_timestamp_value: RFC3339 string, numeric (s→ms unless already ms), >0 only. */\nfunction parseTimestampValue(v: unknown): number | null {\n if (typeof v === \"string\") {\n const ms = Date.parse(v);\n if (!Number.isNaN(ms)) return ms;\n const numeric = Number(v);\n if (Number.isInteger(numeric)) {\n if (numeric <= 0) return null;\n return numeric >= 1_000_000_000_000 ? numeric : numeric * 1000;\n }\n return null;\n }\n if (typeof v === \"number\" && Number.isFinite(v)) {\n const numeric = Math.trunc(v);\n if (numeric <= 0) return null;\n return numeric >= 1_000_000_000_000 ? numeric : numeric * 1000;\n }\n return null;\n}\n\n/** extract_timestamp_from_value: `timestamp` then `created_at`, via parse_timestamp_value. */\nfunction extractTimestampFromValue(obj: Record<string, unknown>): number | null {\n const ts = obj.timestamp;\n if (ts !== undefined) {\n const got = parseTimestampValue(ts);\n if (got !== null) return got;\n }\n const created = obj.created_at;\n if (created !== undefined) {\n const got = parseTimestampValue(created);\n if (got !== null) return got;\n }\n return null;\n}\n\n/** Parse an RFC3339 timestamp string only (used for structured session messages). */\nfunction parseRfc3339(v: unknown): number | null {\n if (typeof v !== \"string\") return null;\n const ms = Date.parse(v);\n return Number.isNaN(ms) ? null : ms;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Cache-inclusive input normalization (ports of gemini.rs)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** subtract_cached_overlap: net input = max(0, input - min(cached, input)); cached unchanged. */\nfunction subtractCachedOverlap(input: number, cached: number): [number, number] {\n const i = nonNeg(input);\n const c = nonNeg(cached);\n const cachedPortion = Math.min(c, i);\n return [i - cachedPortion, c];\n}\n\n/**\n * normalize_gemini_session_input_and_cache: only subtract the cached overlap\n * when a total is present and equals the cache-EXCLUSIVE sum\n * (input+output+reasoning+tool), i.e. cached is not already inside `input`.\n */\nfunction normalizeSessionInputAndCache(\n input: number,\n cached: number,\n output: number,\n reasoning: number,\n tool: number,\n total: number | null,\n): [number, number] {\n const i = nonNeg(input);\n const c = nonNeg(cached);\n\n if (total === null) return [i, c];\n const t = nonNeg(total);\n\n const inclusiveTotal = satAdd(satAdd(satAdd(i, nonNeg(output)), nonNeg(reasoning)), nonNeg(tool));\n const exclusiveTotal = satAdd(inclusiveTotal, c);\n\n if (c > 0 && t === inclusiveTotal && t !== exclusiveTotal) {\n return subtractCachedOverlap(i, c);\n }\n return [i, c];\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Token deserialization\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface GeminiTokens {\n input: number | null;\n output: number | null;\n cached: number | null;\n thoughts: number | null;\n tool: number | null;\n total: number | null;\n}\n\n/** deserialize_tokens: structured-message alias list via first_i64. */\nfunction deserializeTokens(value: unknown): GeminiTokens | null {\n if (typeof value !== \"object\" || value === null) return null;\n const obj = value as Record<string, unknown>;\n return {\n input: firstI64(obj, [\"input\", \"prompt\", \"input_tokens\", \"prompt_tokens\", \"promptTokenCount\"]),\n output: firstI64(obj, [\n \"output\",\n \"candidates\",\n \"output_tokens\",\n \"completion_tokens\",\n \"candidatesTokenCount\",\n ]),\n cached: firstI64(obj, [\"cached\", \"cached_tokens\", \"cachedContentTokenCount\"]),\n thoughts: firstI64(obj, [\"thoughts\", \"reasoning\", \"thoughts_tokens\"]),\n tool: firstI64(obj, [\"tool\", \"tool_tokens\"]),\n total: firstI64(obj, [\"total\", \"totalTokenCount\", \"total_tokens\"]),\n };\n}\n\n/**\n * build_gemini_token_message: structured-message → record. `tool` is folded into\n * input after the (possibly cache-net) normalization; cacheWrite stays 0.\n */\nfunction buildTokenRecord(\n model: string,\n sessionId: string,\n ts: number,\n tokens: GeminiTokens,\n): UsageRecord {\n const [input, cacheRead] = normalizeSessionInputAndCache(\n tokens.input ?? 0,\n tokens.cached ?? 0,\n tokens.output ?? 0,\n tokens.thoughts ?? 0,\n tokens.tool ?? 0,\n tokens.total,\n );\n const tool = nonNeg(tokens.tool ?? 0);\n\n const tk = emptyTokens();\n tk.input = satAdd(input, tool);\n tk.output = nonNeg(tokens.output ?? 0);\n tk.cacheRead = cacheRead;\n tk.cacheWrite = 0;\n tk.reasoning = nonNeg(tokens.thoughts ?? 0);\n\n return {\n platformId: PLATFORM_ID,\n modelId: model,\n providerId: PROVIDER,\n sessionId,\n tokens: tk,\n ts,\n messageCount: 1,\n confidence: \"host-reported\",\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Headless stats extraction (ports of extract_gemini_usage* + build_messages_from_stats)\n// ─────────────────────────────────────────────────────────────────────────\n\ninterface GeminiHeadlessUsage {\n model: string;\n input: number;\n output: number;\n cached: number;\n reasoning: number;\n inputIncludesCache: boolean;\n}\n\n/** extract_gemini_usage_from_value: pull a usage from a stats blob (optionally `tokens`-wrapped). */\nfunction extractUsageFromValue(model: string, value: unknown): GeminiHeadlessUsage | null {\n if (typeof value !== \"object\" || value === null) return null;\n const outer = value as Record<string, unknown>;\n const hasTokensWrapper = outer.tokens !== undefined;\n const tokens =\n hasTokensWrapper && typeof outer.tokens === \"object\" && outer.tokens !== null\n ? (outer.tokens as Record<string, unknown>)\n : outer;\n\n const promptInput =\n extractI64(tokens.prompt) ??\n extractI64(tokens.input_tokens) ??\n extractI64(tokens.prompt_tokens);\n const netInput = extractI64(tokens.input);\n const wrapperInput = hasTokensWrapper ? netInput : null;\n const input = promptInput ?? wrapperInput ?? netInput ?? 0;\n\n const output =\n extractI64(tokens.candidates) ??\n extractI64(tokens.output) ??\n extractI64(tokens.output_tokens) ??\n extractI64(tokens.candidates_tokens) ??\n 0;\n const cached = extractI64(tokens.cached) ?? extractI64(tokens.cached_tokens) ?? 0;\n const reasoning =\n extractI64(tokens.thoughts) ??\n extractI64(tokens.thoughts_tokens) ??\n extractI64(tokens.reasoning) ??\n extractI64(tokens.reasoning_tokens) ??\n 0;\n\n if (input === 0 && output === 0 && cached === 0 && reasoning === 0) return null;\n\n return {\n model,\n input,\n output,\n cached,\n reasoning,\n inputIncludesCache: promptInput !== null || wrapperInput !== null || netInput === null,\n };\n}\n\n/** extract_gemini_usages: per-model breakdown under stats.models, else a single flat usage. */\nfunction extractUsages(stats: Record<string, unknown>, modelHint: string | null): GeminiHeadlessUsage[] {\n const models = stats.models;\n if (typeof models === \"object\" && models !== null && !Array.isArray(models)) {\n const usages: GeminiHeadlessUsage[] = [];\n for (const [model, data] of Object.entries(models as Record<string, unknown>)) {\n const usage = extractUsageFromValue(model, data);\n if (usage !== null) usages.push(usage);\n }\n if (usages.length > 0) return usages;\n }\n const single = extractUsageFromValue(modelHint ?? DEFAULT_MODEL, stats);\n return single === null ? [] : [single];\n}\n\n/** build_messages_from_stats: usages → records (net input via headless normalization). */\nfunction buildRecordsFromStats(\n stats: Record<string, unknown>,\n modelHint: string | null,\n sessionId: string,\n ts: number,\n): UsageRecord[] {\n return extractUsages(stats, modelHint).map((usage) => {\n const [input, cacheRead] = usage.inputIncludesCache\n ? subtractCachedOverlap(usage.input, usage.cached) // normalize_gemini_headless_input_and_cache\n : [nonNeg(usage.input), nonNeg(usage.cached)];\n const tk = emptyTokens();\n tk.input = input;\n tk.output = nonNeg(usage.output);\n tk.cacheRead = cacheRead;\n tk.cacheWrite = 0;\n tk.reasoning = nonNeg(usage.reasoning);\n return {\n platformId: PLATFORM_ID,\n modelId: usage.model,\n providerId: PROVIDER,\n sessionId,\n tokens: tk,\n ts,\n messageCount: 1,\n confidence: \"host-reported\",\n };\n });\n}\n\n/** stats = value.stats || value.result.stats (the rollup container). */\nfunction findStats(obj: Record<string, unknown>): Record<string, unknown> | null {\n if (typeof obj.stats === \"object\" && obj.stats !== null) return obj.stats as Record<string, unknown>;\n const result = obj.result;\n if (typeof result === \"object\" && result !== null) {\n const inner = (result as Record<string, unknown>).stats;\n if (typeof inner === \"object\" && inner !== null) return inner as Record<string, unknown>;\n }\n return null;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Direct-token messages (type:\"gemini\" or a `tokens` block present)\n// ─────────────────────────────────────────────────────────────────────────\n\n/** parse_direct_gemini_token_message: needs a model (own or hint) and a `tokens` block. */\nfunction parseDirectTokenRecord(\n obj: Record<string, unknown>,\n modelHint: string | null,\n sessionId: string,\n fallbackTs: number,\n): UsageRecord | null {\n const model = extractString(obj.model) ?? modelHint;\n if (model === null) return null;\n if (obj.tokens === undefined) return null;\n const tokens = deserializeTokens(obj.tokens);\n if (tokens === null) return null;\n const ts = extractTimestampFromValue(obj) ?? fallbackTs;\n return buildTokenRecord(model, sessionId, ts, tokens);\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Path discovery (port of the parse_gemini_file_with_cache_status filter)\n// ─────────────────────────────────────────────────────────────────────────\n\nfunction pathComponents(abs: string): string[] {\n return abs.split(/[\\\\/]+/).filter((c) => c !== \"\");\n}\n\n/**\n * Accept this file? Legacy `session-*` names pass anywhere. Otherwise the path\n * must end `.../tmp/<id>/chats/<file>` — exactly three components after a `tmp`\n * segment, with the middle one literally \"chats\" and the last being this file.\n */\nfunction isAcceptedFile(abs: string): boolean {\n const name = basename(abs);\n if (name.startsWith(\"session-\")) return true;\n const comps = pathComponents(abs);\n for (let i = 0; i + 1 < comps.length; i++) {\n if (comps[i] === \"tmp\") {\n const afterTmp = comps.slice(i + 1);\n if (afterTmp.length === 3 && afterTmp[1] === \"chats\" && afterTmp[2] === name) {\n return true;\n }\n }\n }\n return false;\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Per-file parsing\n// ─────────────────────────────────────────────────────────────────────────\n\n/** Is a parsed JSON value a structured GeminiSession (has a messages array)? */\nfunction asGeminiSession(value: unknown): { sessionId: string; messages: unknown[] } | null {\n if (typeof value !== \"object\" || value === null) return null;\n const obj = value as Record<string, unknown>;\n if (!Array.isArray(obj.messages)) return null;\n // serde requires sessionId/projectHash/startTime/lastUpdated as strings; mirror\n // the strict struct shape so a headless value (no sessionId) falls through.\n if (typeof obj.sessionId !== \"string\") return null;\n return { sessionId: obj.sessionId, messages: obj.messages };\n}\n\n/** parse_gemini_session: structured messages with a `tokens` block and a `model`. */\nfunction parseSession(\n session: { sessionId: string; messages: unknown[] },\n fallbackTs: number,\n): UsageRecord[] {\n const out: UsageRecord[] = [];\n for (const raw of session.messages) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const msg = raw as Record<string, unknown>;\n const tokens = deserializeTokens(msg.tokens);\n if (tokens === null) continue; // only messages with token data\n const model = extractString(msg.model);\n if (model === null) continue; // model required\n const ts = parseRfc3339(msg.timestamp) ?? fallbackTs;\n out.push(buildTokenRecord(model, session.sessionId, ts, tokens));\n }\n return out;\n}\n\n/** parse_gemini_headless_value: one JSON value → direct-token row or stats rows. */\nfunction parseHeadlessValue(\n value: unknown,\n sessionId: string,\n fallbackTs: number,\n): UsageRecord[] {\n if (typeof value !== \"object\" || value === null) return [];\n const obj = value as Record<string, unknown>;\n\n if (obj.type === \"gemini\" || obj.tokens !== undefined) {\n const direct = parseDirectTokenRecord(obj, null, sessionId, fallbackTs);\n if (direct !== null) return [direct];\n }\n\n const stats = findStats(obj);\n if (stats === null) return [];\n const modelHint = extractString(obj.model);\n const ts = extractTimestampFromValue(obj) ?? fallbackTs;\n return buildRecordsFromStats(stats, modelHint, sessionId, ts);\n}\n\n/**\n * parse_gemini_headless_jsonl: stateful newline-delimited stream.\n * - `init` sets current_model + session_id;\n * - any line may carry session_id/sessionId (updates the running id);\n * - direct-token events (type:\"gemini\" or has `tokens`) build a row, deduped\n * LAST-WINS by `id` (a later same-id event overwrites the earlier row);\n * - `stats`/`result.stats` rollups append non-deduped rows.\n * Session id seeds from the file stem.\n */\nfunction parseHeadlessJsonl(path: string, fallbackTs: number): UsageRecord[] {\n const lines = readJsonlLines(path);\n let sessionId = stripExt(basename(path)) || \"unknown\";\n let currentModel: string | null = null;\n const records: UsageRecord[] = [];\n const directIndexById = new Map<string, number>();\n\n for (const raw of lines) {\n if (typeof raw !== \"object\" || raw === null) continue;\n const obj = raw as Record<string, unknown>;\n const eventType = extractString(obj.type) ?? \"\";\n\n if (eventType === \"init\") {\n const model = extractString(obj.model);\n if (model !== null) currentModel = model;\n const id = extractString(obj.session_id) ?? extractString(obj.sessionId);\n if (id !== null) sessionId = id;\n continue;\n }\n\n const lineSession = extractString(obj.session_id) ?? extractString(obj.sessionId);\n if (lineSession !== null) sessionId = lineSession;\n\n if (eventType === \"gemini\" || obj.tokens !== undefined) {\n const model = extractString(obj.model);\n if (model !== null) currentModel = model;\n\n const record = parseDirectTokenRecord(obj, currentModel, sessionId, fallbackTs);\n if (record !== null) {\n const id = extractString(obj.id);\n if (id !== null) {\n record.dedupKey = `${sessionId}:${id}`;\n const existing = directIndexById.get(id);\n if (existing !== undefined) {\n records[existing] = record; // replace (last-wins)\n } else {\n directIndexById.set(id, records.length);\n records.push(record);\n }\n } else {\n records.push(record);\n }\n }\n continue;\n }\n\n const stats = findStats(obj);\n if (stats !== null) {\n const ts = extractTimestampFromValue(obj) ?? fallbackTs;\n for (const rec of buildRecordsFromStats(stats, currentModel, sessionId, ts)) {\n records.push(rec);\n }\n }\n }\n\n return records;\n}\n\nfunction stripExt(name: string): string {\n const dot = name.lastIndexOf(\".\");\n return dot > 0 ? name.slice(0, dot) : name;\n}\n\n/** Parse one Gemini file (port of parse_gemini_file_with_cache_status). */\nfunction parseGeminiFile(path: string): UsageRecord[] {\n const fallbackTs = fileMtimeMs(path);\n\n // .jsonl always uses the streaming parser.\n if (path.endsWith(\".jsonl\")) {\n return parseHeadlessJsonl(path, fallbackTs);\n }\n\n // .json: try structured session, then headless value, then JSONL fallback.\n const value = readJsonFile(path);\n if (value !== undefined) {\n const session = asGeminiSession(value);\n if (session !== null) {\n return parseSession(session, fallbackTs);\n }\n const sessionId = stripExt(basename(path)) || \"unknown\";\n const headless = parseHeadlessValue(value, sessionId, fallbackTs);\n if (headless.length > 0) return headless;\n }\n\n // Last resort: treat as JSONL (mirrors the Rust fall-through).\n return parseHeadlessJsonl(path, fallbackTs);\n}\n\n// ─────────────────────────────────────────────────────────────────────────\n// Reader\n// ─────────────────────────────────────────────────────────────────────────\n\nconst geminiReader: UsageReader = {\n platformId: PLATFORM_ID,\n kind: \"local\",\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\n const root = firstExistingRoot(PLATFORM_ID);\n if (root === undefined) return []; // no ~/.gemini/tmp → fail-open\n\n const files = walkFiles(root, (name, abs) => {\n if (!name.endsWith(\".json\") && !name.endsWith(\".jsonl\")) return false;\n return isAcceptedFile(abs);\n });\n\n const records: UsageRecord[] = [];\n for (const file of files) {\n let rows: UsageRecord[];\n try {\n rows = parseGeminiFile(file);\n } catch {\n rows = []; // fail-open per file\n }\n for (const row of rows) {\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\n records.push(row);\n }\n }\n return records;\n },\n};\n\nexport default geminiReader;\n"],"mappings":";;;;;;;;;;;;;;;AAmDA,SAAS,gBAAgB;AAOzB,IAAM,cAAc;AACpB,IAAM,WAAW;AACjB,IAAM,gBAAgB;AAOtB,SAAS,WAAW,GAA2B;AAC7C,MAAI,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,EAAG,QAAO,KAAK,MAAM,CAAC;AACpE,MAAI,OAAO,MAAM,UAAU;AACzB,UAAM,IAAI,OAAO,CAAC;AAClB,QAAI,OAAO,UAAU,CAAC,EAAG,QAAO;AAAA,EAClC;AACA,SAAO;AACT;AAGA,SAAS,cAAc,GAA2B;AAChD,SAAO,OAAO,MAAM,WAAW,IAAI;AACrC;AAGA,SAAS,SAAS,KAA8B,MAAwC;AACtF,aAAW,KAAK,MAAM;AACpB,UAAM,MAAM,WAAW,IAAI,CAAC,CAAC;AAC7B,QAAI,QAAQ,KAAM,QAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAGA,SAAS,OAAO,GAAmB;AACjC,SAAO,IAAI,IAAI,KAAK,MAAM,CAAC,IAAI;AACjC;AAGA,SAAS,OAAO,GAAW,GAAmB;AAC5C,SAAO,IAAI;AACb;AAOA,SAAS,oBAAoB,GAA2B;AACtD,MAAI,OAAO,MAAM,UAAU;AACzB,UAAM,KAAK,KAAK,MAAM,CAAC;AACvB,QAAI,CAAC,OAAO,MAAM,EAAE,EAAG,QAAO;AAC9B,UAAM,UAAU,OAAO,CAAC;AACxB,QAAI,OAAO,UAAU,OAAO,GAAG;AAC7B,UAAI,WAAW,EAAG,QAAO;AACzB,aAAO,WAAW,OAAoB,UAAU,UAAU;AAAA,IAC5D;AACA,WAAO;AAAA,EACT;AACA,MAAI,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,GAAG;AAC/C,UAAM,UAAU,KAAK,MAAM,CAAC;AAC5B,QAAI,WAAW,EAAG,QAAO;AACzB,WAAO,WAAW,OAAoB,UAAU,UAAU;AAAA,EAC5D;AACA,SAAO;AACT;AAGA,SAAS,0BAA0B,KAA6C;AAC9E,QAAM,KAAK,IAAI;AACf,MAAI,OAAO,QAAW;AACpB,UAAM,MAAM,oBAAoB,EAAE;AAClC,QAAI,QAAQ,KAAM,QAAO;AAAA,EAC3B;AACA,QAAM,UAAU,IAAI;AACpB,MAAI,YAAY,QAAW;AACzB,UAAM,MAAM,oBAAoB,OAAO;AACvC,QAAI,QAAQ,KAAM,QAAO;AAAA,EAC3B;AACA,SAAO;AACT;AAGA,SAAS,aAAa,GAA2B;AAC/C,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,QAAM,KAAK,KAAK,MAAM,CAAC;AACvB,SAAO,OAAO,MAAM,EAAE,IAAI,OAAO;AACnC;AAOA,SAAS,sBAAsB,OAAe,QAAkC;AAC9E,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,IAAI,OAAO,MAAM;AACvB,QAAM,gBAAgB,KAAK,IAAI,GAAG,CAAC;AACnC,SAAO,CAAC,IAAI,eAAe,CAAC;AAC9B;AAOA,SAAS,8BACP,OACA,QACA,QACA,WACA,MACA,OACkB;AAClB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,IAAI,OAAO,MAAM;AAEvB,MAAI,UAAU,KAAM,QAAO,CAAC,GAAG,CAAC;AAChC,QAAM,IAAI,OAAO,KAAK;AAEtB,QAAM,iBAAiB,OAAO,OAAO,OAAO,GAAG,OAAO,MAAM,CAAC,GAAG,OAAO,SAAS,CAAC,GAAG,OAAO,IAAI,CAAC;AAChG,QAAM,iBAAiB,OAAO,gBAAgB,CAAC;AAE/C,MAAI,IAAI,KAAK,MAAM,kBAAkB,MAAM,gBAAgB;AACzD,WAAO,sBAAsB,GAAG,CAAC;AAAA,EACnC;AACA,SAAO,CAAC,GAAG,CAAC;AACd;AAgBA,SAAS,kBAAkB,OAAqC;AAC9D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,OAAO,SAAS,KAAK,CAAC,SAAS,UAAU,gBAAgB,iBAAiB,kBAAkB,CAAC;AAAA,IAC7F,QAAQ,SAAS,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,IACD,QAAQ,SAAS,KAAK,CAAC,UAAU,iBAAiB,yBAAyB,CAAC;AAAA,IAC5E,UAAU,SAAS,KAAK,CAAC,YAAY,aAAa,iBAAiB,CAAC;AAAA,IACpE,MAAM,SAAS,KAAK,CAAC,QAAQ,aAAa,CAAC;AAAA,IAC3C,OAAO,SAAS,KAAK,CAAC,SAAS,mBAAmB,cAAc,CAAC;AAAA,EACnE;AACF;AAMA,SAAS,iBACP,OACA,WACA,IACA,QACa;AACb,QAAM,CAAC,OAAO,SAAS,IAAI;AAAA,IACzB,OAAO,SAAS;AAAA,IAChB,OAAO,UAAU;AAAA,IACjB,OAAO,UAAU;AAAA,IACjB,OAAO,YAAY;AAAA,IACnB,OAAO,QAAQ;AAAA,IACf,OAAO;AAAA,EACT;AACA,QAAM,OAAO,OAAO,OAAO,QAAQ,CAAC;AAEpC,QAAM,KAAK,YAAY;AACvB,KAAG,QAAQ,OAAO,OAAO,IAAI;AAC7B,KAAG,SAAS,OAAO,OAAO,UAAU,CAAC;AACrC,KAAG,YAAY;AACf,KAAG,aAAa;AAChB,KAAG,YAAY,OAAO,OAAO,YAAY,CAAC;AAE1C,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ;AAAA,IACA,QAAQ;AAAA,IACR;AAAA,IACA,cAAc;AAAA,IACd,YAAY;AAAA,EACd;AACF;AAgBA,SAAS,sBAAsB,OAAe,OAA4C;AACxF,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,QAAQ;AACd,QAAM,mBAAmB,MAAM,WAAW;AAC1C,QAAM,SACJ,oBAAoB,OAAO,MAAM,WAAW,YAAY,MAAM,WAAW,OACpE,MAAM,SACP;AAEN,QAAM,cACJ,WAAW,OAAO,MAAM,KACxB,WAAW,OAAO,YAAY,KAC9B,WAAW,OAAO,aAAa;AACjC,QAAM,WAAW,WAAW,OAAO,KAAK;AACxC,QAAM,eAAe,mBAAmB,WAAW;AACnD,QAAM,QAAQ,eAAe,gBAAgB,YAAY;AAEzD,QAAM,SACJ,WAAW,OAAO,UAAU,KAC5B,WAAW,OAAO,MAAM,KACxB,WAAW,OAAO,aAAa,KAC/B,WAAW,OAAO,iBAAiB,KACnC;AACF,QAAM,SAAS,WAAW,OAAO,MAAM,KAAK,WAAW,OAAO,aAAa,KAAK;AAChF,QAAM,YACJ,WAAW,OAAO,QAAQ,KAC1B,WAAW,OAAO,eAAe,KACjC,WAAW,OAAO,SAAS,KAC3B,WAAW,OAAO,gBAAgB,KAClC;AAEF,MAAI,UAAU,KAAK,WAAW,KAAK,WAAW,KAAK,cAAc,EAAG,QAAO;AAE3E,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,oBAAoB,gBAAgB,QAAQ,iBAAiB,QAAQ,aAAa;AAAA,EACpF;AACF;AAGA,SAAS,cAAc,OAAgC,WAAiD;AACtG,QAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC3E,UAAM,SAAgC,CAAC;AACvC,eAAW,CAAC,OAAO,IAAI,KAAK,OAAO,QAAQ,MAAiC,GAAG;AAC7E,YAAM,QAAQ,sBAAsB,OAAO,IAAI;AAC/C,UAAI,UAAU,KAAM,QAAO,KAAK,KAAK;AAAA,IACvC;AACA,QAAI,OAAO,SAAS,EAAG,QAAO;AAAA,EAChC;AACA,QAAM,SAAS,sBAAsB,aAAa,eAAe,KAAK;AACtE,SAAO,WAAW,OAAO,CAAC,IAAI,CAAC,MAAM;AACvC;AAGA,SAAS,sBACP,OACA,WACA,WACA,IACe;AACf,SAAO,cAAc,OAAO,SAAS,EAAE,IAAI,CAAC,UAAU;AACpD,UAAM,CAAC,OAAO,SAAS,IAAI,MAAM,qBAC7B,sBAAsB,MAAM,OAAO,MAAM,MAAM,IAC/C,CAAC,OAAO,MAAM,KAAK,GAAG,OAAO,MAAM,MAAM,CAAC;AAC9C,UAAM,KAAK,YAAY;AACvB,OAAG,QAAQ;AACX,OAAG,SAAS,OAAO,MAAM,MAAM;AAC/B,OAAG,YAAY;AACf,OAAG,aAAa;AAChB,OAAG,YAAY,OAAO,MAAM,SAAS;AACrC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,SAAS,MAAM;AAAA,MACf,YAAY;AAAA,MACZ;AAAA,MACA,QAAQ;AAAA,MACR;AAAA,MACA,cAAc;AAAA,MACd,YAAY;AAAA,IACd;AAAA,EACF,CAAC;AACH;AAGA,SAAS,UAAU,KAA8D;AAC/E,MAAI,OAAO,IAAI,UAAU,YAAY,IAAI,UAAU,KAAM,QAAO,IAAI;AACpE,QAAM,SAAS,IAAI;AACnB,MAAI,OAAO,WAAW,YAAY,WAAW,MAAM;AACjD,UAAM,QAAS,OAAmC;AAClD,QAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AAAA,EAC1D;AACA,SAAO;AACT;AAOA,SAAS,uBACP,KACA,WACA,WACA,YACoB;AACpB,QAAM,QAAQ,cAAc,IAAI,KAAK,KAAK;AAC1C,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,IAAI,WAAW,OAAW,QAAO;AACrC,QAAM,SAAS,kBAAkB,IAAI,MAAM;AAC3C,MAAI,WAAW,KAAM,QAAO;AAC5B,QAAM,KAAK,0BAA0B,GAAG,KAAK;AAC7C,SAAO,iBAAiB,OAAO,WAAW,IAAI,MAAM;AACtD;AAMA,SAAS,eAAe,KAAuB;AAC7C,SAAO,IAAI,MAAM,QAAQ,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE;AACnD;AAOA,SAAS,eAAe,KAAsB;AAC5C,QAAM,OAAO,SAAS,GAAG;AACzB,MAAI,KAAK,WAAW,UAAU,EAAG,QAAO;AACxC,QAAM,QAAQ,eAAe,GAAG;AAChC,WAAS,IAAI,GAAG,IAAI,IAAI,MAAM,QAAQ,KAAK;AACzC,QAAI,MAAM,CAAC,MAAM,OAAO;AACtB,YAAM,WAAW,MAAM,MAAM,IAAI,CAAC;AAClC,UAAI,SAAS,WAAW,KAAK,SAAS,CAAC,MAAM,WAAW,SAAS,CAAC,MAAM,MAAM;AAC5E,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAOA,SAAS,gBAAgB,OAAmE;AAC1F,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MAAM;AACZ,MAAI,CAAC,MAAM,QAAQ,IAAI,QAAQ,EAAG,QAAO;AAGzC,MAAI,OAAO,IAAI,cAAc,SAAU,QAAO;AAC9C,SAAO,EAAE,WAAW,IAAI,WAAW,UAAU,IAAI,SAAS;AAC5D;AAGA,SAAS,aACP,SACA,YACe;AACf,QAAM,MAAqB,CAAC;AAC5B,aAAW,OAAO,QAAQ,UAAU;AAClC,QAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM;AAC7C,UAAM,MAAM;AACZ,UAAM,SAAS,kBAAkB,IAAI,MAAM;AAC3C,QAAI,WAAW,KAAM;AACrB,UAAM,QAAQ,cAAc,IAAI,KAAK;AACrC,QAAI,UAAU,KAAM;AACpB,UAAM,KAAK,aAAa,IAAI,SAAS,KAAK;AAC1C,QAAI,KAAK,iBAAiB,OAAO,QAAQ,WAAW,IAAI,MAAM,CAAC;AAAA,EACjE;AACA,SAAO;AACT;AAGA,SAAS,mBACP,OACA,WACA,YACe;AACf,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO,CAAC;AACzD,QAAM,MAAM;AAEZ,MAAI,IAAI,SAAS,YAAY,IAAI,WAAW,QAAW;AACrD,UAAM,SAAS,uBAAuB,KAAK,MAAM,WAAW,UAAU;AACtE,QAAI,WAAW,KAAM,QAAO,CAAC,MAAM;AAAA,EACrC;AAEA,QAAM,QAAQ,UAAU,GAAG;AAC3B,MAAI,UAAU,KAAM,QAAO,CAAC;AAC5B,QAAM,YAAY,cAAc,IAAI,KAAK;AACzC,QAAM,KAAK,0BAA0B,GAAG,KAAK;AAC7C,SAAO,sBAAsB,OAAO,WAAW,WAAW,EAAE;AAC9D;AAWA,SAAS,mBAAmB,MAAc,YAAmC;AAC3E,QAAM,QAAQ,eAAe,IAAI;AACjC,MAAI,YAAY,SAAS,SAAS,IAAI,CAAC,KAAK;AAC5C,MAAI,eAA8B;AAClC,QAAM,UAAyB,CAAC;AAChC,QAAM,kBAAkB,oBAAI,IAAoB;AAEhD,aAAW,OAAO,OAAO;AACvB,QAAI,OAAO,QAAQ,YAAY,QAAQ,KAAM;AAC7C,UAAM,MAAM;AACZ,UAAM,YAAY,cAAc,IAAI,IAAI,KAAK;AAE7C,QAAI,cAAc,QAAQ;AACxB,YAAM,QAAQ,cAAc,IAAI,KAAK;AACrC,UAAI,UAAU,KAAM,gBAAe;AACnC,YAAM,KAAK,cAAc,IAAI,UAAU,KAAK,cAAc,IAAI,SAAS;AACvE,UAAI,OAAO,KAAM,aAAY;AAC7B;AAAA,IACF;AAEA,UAAM,cAAc,cAAc,IAAI,UAAU,KAAK,cAAc,IAAI,SAAS;AAChF,QAAI,gBAAgB,KAAM,aAAY;AAEtC,QAAI,cAAc,YAAY,IAAI,WAAW,QAAW;AACtD,YAAM,QAAQ,cAAc,IAAI,KAAK;AACrC,UAAI,UAAU,KAAM,gBAAe;AAEnC,YAAM,SAAS,uBAAuB,KAAK,cAAc,WAAW,UAAU;AAC9E,UAAI,WAAW,MAAM;AACnB,cAAM,KAAK,cAAc,IAAI,EAAE;AAC/B,YAAI,OAAO,MAAM;AACf,iBAAO,WAAW,GAAG,SAAS,IAAI,EAAE;AACpC,gBAAM,WAAW,gBAAgB,IAAI,EAAE;AACvC,cAAI,aAAa,QAAW;AAC1B,oBAAQ,QAAQ,IAAI;AAAA,UACtB,OAAO;AACL,4BAAgB,IAAI,IAAI,QAAQ,MAAM;AACtC,oBAAQ,KAAK,MAAM;AAAA,UACrB;AAAA,QACF,OAAO;AACL,kBAAQ,KAAK,MAAM;AAAA,QACrB;AAAA,MACF;AACA;AAAA,IACF;AAEA,UAAM,QAAQ,UAAU,GAAG;AAC3B,QAAI,UAAU,MAAM;AAClB,YAAM,KAAK,0BAA0B,GAAG,KAAK;AAC7C,iBAAW,OAAO,sBAAsB,OAAO,cAAc,WAAW,EAAE,GAAG;AAC3E,gBAAQ,KAAK,GAAG;AAAA,MAClB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,SAAS,MAAsB;AACtC,QAAM,MAAM,KAAK,YAAY,GAAG;AAChC,SAAO,MAAM,IAAI,KAAK,MAAM,GAAG,GAAG,IAAI;AACxC;AAGA,SAAS,gBAAgB,MAA6B;AACpD,QAAM,aAAa,YAAY,IAAI;AAGnC,MAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,WAAO,mBAAmB,MAAM,UAAU;AAAA,EAC5C;AAGA,QAAM,QAAQ,aAAa,IAAI;AAC/B,MAAI,UAAU,QAAW;AACvB,UAAM,UAAU,gBAAgB,KAAK;AACrC,QAAI,YAAY,MAAM;AACpB,aAAO,aAAa,SAAS,UAAU;AAAA,IACzC;AACA,UAAM,YAAY,SAAS,SAAS,IAAI,CAAC,KAAK;AAC9C,UAAM,WAAW,mBAAmB,OAAO,WAAW,UAAU;AAChE,QAAI,SAAS,SAAS,EAAG,QAAO;AAAA,EAClC;AAGA,SAAO,mBAAmB,MAAM,UAAU;AAC5C;AAMA,IAAM,eAA4B;AAAA,EAChC,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,MAAM,KAAK,EAAE,QAAQ,GAAiD;AACpE,UAAM,OAAO,kBAAkB,WAAW;AAC1C,QAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,UAAM,QAAQ,UAAU,MAAM,CAAC,MAAM,QAAQ;AAC3C,UAAI,CAAC,KAAK,SAAS,OAAO,KAAK,CAAC,KAAK,SAAS,QAAQ,EAAG,QAAO;AAChE,aAAO,eAAe,GAAG;AAAA,IAC3B,CAAC;AAED,UAAM,UAAyB,CAAC;AAChC,eAAW,QAAQ,OAAO;AACxB,UAAI;AACJ,UAAI;AACF,eAAO,gBAAgB,IAAI;AAAA,MAC7B,QAAQ;AACN,eAAO,CAAC;AAAA,MACV;AACA,iBAAW,OAAO,MAAM;AACtB,YAAI,YAAY,UAAa,IAAI,KAAK,QAAS;AAC/C,gBAAQ,KAAK,GAAG;AAAA,MAClB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEA,IAAO,qBAAQ;","names":[]}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
writeTomlString
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-OPXAP3AC.js";
|
|
5
5
|
import {
|
|
6
6
|
normalizeSessionSource
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-H53QZQJI.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveEnvRefsDeep
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-BEFVJ2OE.js";
|
|
11
11
|
import {
|
|
12
12
|
BaseAdapter,
|
|
13
13
|
renderSkillMd,
|
|
14
14
|
renderSubagentMd
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-JTN3AKZO.js";
|
|
16
16
|
import {
|
|
17
17
|
buildHomeBinHookCommand,
|
|
18
18
|
buildUsageEventCommand,
|
|
@@ -20,9 +20,9 @@ import {
|
|
|
20
20
|
isHomeBinHookCommand,
|
|
21
21
|
isHostNativeUsageEnabled,
|
|
22
22
|
isUsageEventCommand
|
|
23
|
-
} from "./chunk-
|
|
24
|
-
import "./chunk-
|
|
25
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-QSY74NAP.js";
|
|
24
|
+
import "./chunk-UMQ6NBQR.js";
|
|
25
|
+
import "./chunk-GZGLCCEE.js";
|
|
26
26
|
|
|
27
27
|
// src/adapters/gemini-cli/index.ts
|
|
28
28
|
import { existsSync } from "fs";
|
|
@@ -770,4 +770,4 @@ export {
|
|
|
770
770
|
adapter,
|
|
771
771
|
gemini_cli_default as default
|
|
772
772
|
};
|
|
773
|
-
//# sourceMappingURL=gemini-cli-
|
|
773
|
+
//# sourceMappingURL=gemini-cli-VJ6X5DNF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/gemini-cli/index.ts"],"sourcesContent":["/**\n * adapters/gemini-cli — Gemini CLI platform adapter for agent-connector.\n *\n * Gemini CLI (Google) is a json-stdio host: the host pipes a JSON payload to a\n * hook command on stdin and reads a JSON control object / exit code back — the\n * same paradigm as Claude Code. Two things make Gemini distinct, and both are\n * handled below:\n *\n * 1. TRANSPORT IS SELECTED BY KEY (not a `type` field). Under `mcpServers`, a\n * stdio server is `{ command, args, env }`; an SSE server is `{ url }`; a\n * streamable-HTTP server is `{ httpUrl }`. We render stdio with\n * command/args/env and remote transports with the matching key.\n * 2. Gemini's hook EVENT VOCABULARY differs from the Claude-compatible hosts,\n * so our normalized event names are mapped to Gemini's:\n * PreToolUse → BeforeTool\n * PostToolUse → AfterTool\n * PreCompact → PreCompress\n * SessionStart→ SessionStart\n * UserPromptSubmit → BeforeAgent (BeforeAgent fires on prompt submit;\n * additionalContext is appended)\n * SessionEnd → SessionEnd\n * Notification→ Notification\n * `Stop` has no Gemini equivalent and is reported as a warn/skip at install.\n *\n * Native config (JSON):\n * - MCP servers: user → ~/.gemini/settings.json; project → .gemini/settings.json\n * (system scope is /etc/gemini-cli/settings.json — not a target we write).\n * Root key \"mcpServers\".\n * - Hooks: the SAME settings.json, top-level \"hooks\" key, keyed by the Gemini\n * event name, each value an array of `{ matcher, hooks: [{ type:\"command\",\n * command }] }` (the nested shape; Gemini accepts ONLY type \"command\").\n * - Reply (stdout, exit 0):\n * deny → { decision:\"deny\", reason }\n * modify → { hookSpecificOutput:{ tool_input } } (merged with original)\n * context → { hookSpecificOutput:{ additionalContext } }\n * PostToolUse output rewrite → { decision:\"deny\", reason:<newOutput> }\n * (Gemini replaces tool output via a deny+reason on AfterTool).\n * ask → no native \"ask\"; degrade to deny to stay fail-safe.\n *\n * NOTE: Gemini's AfterModel hook payload carries `usageMetadata.totalTokenCount`\n * (per-LLM-call real token usage — the one host-native usage signal in the\n * matrix). This is the OPT-IN host-native usage enricher (4a): when host-native\n * capture is enabled (telemetry.hostNativeUsage, or AGENT_CONNECTOR_HOST_NATIVE=1\n * at install), installHooks ALSO writes an AfterModel hook whose command is the\n * hidden `<homeBin> usage-event gemini-cli --connector <id>` entrypoint. That\n * records a DISTINCT `model_turn` telemetry row (confidence host-native) covering\n * the whole conversation turn — never summed with the per-MCP `serve`-proxy rows.\n * AfterModel is NOT a normalized connector event (no handler dispatch); it is a\n * host-native-only sink. When the opt-in is OFF, the hook is NOT installed and\n * telemetry continues to flow only through the `serve` proxy.\n *\n * Env handling: Gemini's native settings interpolation token is `${VAR}`/`$VAR`,\n * not the framework's `${env:VAR}` syntax. Rather than depend on that, env /\n * header / url refs are resolved to literals at install time via\n * resolveEnvRefsDeep — the safe default for a host without `${env:VAR}` support\n * (matching the Codex / Copilot CLI adapters).\n *\n * Grounded in docs/research/understand-report.md §2 (Platform Integration\n * Matrix, \"Gemini CLI\" row) and context-mode's proven gemini-cli adapter.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nimport { BaseAdapter } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n CommandDef,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PreCompactEvent,\n PreToolUseEvent,\n ServerDef,\n SessionEndEvent,\n SessionStartEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { writeTomlString } from \"../../core/toml.js\";\nimport {\n buildHomeBinHookCommand,\n buildWrappedStdio,\n buildUsageEventCommand,\n isHomeBinHookCommand,\n isHostNativeUsageEnabled,\n isUsageEventCommand,\n} from \"../../core/spawn.js\";\nimport { renderSkillMd, renderSubagentMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"gemini-cli\";\nconst MCP_ROOT_KEY = \"mcpServers\";\n\n/**\n * Gemini-native hook event names (settings.json top-level `hooks` keys).\n * Only the events Gemini fires for the JSON-stdio command paradigm we use.\n */\nconst GEMINI_EVENT = {\n BeforeTool: \"BeforeTool\",\n AfterTool: \"AfterTool\",\n PreCompress: \"PreCompress\",\n SessionStart: \"SessionStart\",\n SessionEnd: \"SessionEnd\",\n BeforeAgent: \"BeforeAgent\",\n Notification: \"Notification\",\n /** Fires AFTER each model turn; payload carries `usageMetadata` (opt-in 4a). */\n AfterModel: \"AfterModel\",\n} as const;\n\n/**\n * Map our normalized event names to Gemini's native hook event names. Only the\n * events Gemini actually supports are present; `Stop` has no Gemini equivalent\n * and is reported as a warn/skip at install time.\n */\nconst EVENT_MAP: Partial<Record<HookEventName, string>> = {\n PreToolUse: GEMINI_EVENT.BeforeTool,\n PostToolUse: GEMINI_EVENT.AfterTool,\n PreCompact: GEMINI_EVENT.PreCompress,\n SessionStart: GEMINI_EVENT.SessionStart,\n SessionEnd: GEMINI_EVENT.SessionEnd,\n UserPromptSubmit: GEMINI_EVENT.BeforeAgent,\n Notification: GEMINI_EVENT.Notification,\n};\n\n/** A single Gemini native hook registration entry (nested, Claude-shaped). */\ninterface GeminiHookEntry {\n matcher: string;\n hooks: Array<{ type: \"command\"; command: string }>;\n}\n\n/** The shape of Gemini's settings.json (only the parts we touch). */\ninterface GeminiSettingsFile {\n mcpServers?: Record<string, unknown>;\n hooks?: Record<string, GeminiHookEntry[]>;\n [key: string]: unknown;\n}\n\n/**\n * Native MCP server entry shapes Gemini accepts under `mcpServers`. Gemini\n * selects the transport by which key is present (NOT a `type` field):\n * stdio → command / args / env\n * SSE → url\n * streamable-HTTP→ httpUrl\n */\ninterface GeminiStdioServer {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n}\ninterface GeminiSseServer {\n url: string;\n headers?: Record<string, string>;\n}\ninterface GeminiHttpServer {\n httpUrl: string;\n headers?: Record<string, string>;\n}\n\n/** Raw Gemini CLI hook stdin payload (snake_case wire fields). */\ninterface GeminiWireInput {\n connector?: unknown;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n // AfterTool (→ PostToolUse) serializes the tool result under `tool_response`,\n // an object { llmContent, returnDisplay, error? } — NOT `tool_output`, and there\n // is no `is_error` on the wire. Source: google-gemini/gemini-cli\n // packages/core/src/hooks/hookEventHandler.ts:107-111 (fireAfterToolEvent sets\n // tool_response: toolResponse), types.ts:518-521 (AfterToolInput.tool_response:\n // Record<string, unknown>), tools.ts:742-768 (ToolResult.{llmContent,returnDisplay,\n // error?}), docs/hooks/reference.md:114-123.\n tool_response?: unknown;\n session_id?: string;\n cwd?: string;\n source?: string;\n trigger?: string;\n reason?: string;\n prompt?: string;\n message?: string;\n}\n\n/**\n * Normalize gemini-cli's AfterTool `tool_response` into a flat `toolOutput` string.\n * `tool_response` is a ToolResult-shaped object { llmContent, returnDisplay, error? }\n * (google-gemini/gemini-cli tools.ts:742-768). Prefer `llmContent` (the content the\n * model sees), then `returnDisplay`; strings pass through, objects are JSON-stringified.\n * Returns undefined when no usable output is present.\n */\nfunction extractToolOutput(toolResponse: unknown): string | undefined {\n if (typeof toolResponse === \"string\") return toolResponse;\n if (toolResponse === null || typeof toolResponse !== \"object\") return undefined;\n const obj = toolResponse as Record<string, unknown>;\n const value = obj.llmContent ?? obj.returnDisplay;\n if (value === undefined || value === null) return undefined;\n return typeof value === \"string\" ? value : JSON.stringify(value);\n}\n\n/**\n * A gemini-cli AfterTool result is a failure iff `tool_response.error` is present\n * (google-gemini/gemini-cli tools.ts:765 — \"If this property is present, the tool\n * call is considered a failure.\"). There is no top-level `is_error` on the wire.\n */\nfunction hasToolError(toolResponse: unknown): boolean {\n if (toolResponse === null || typeof toolResponse !== \"object\") return false;\n return (toolResponse as Record<string, unknown>).error != null;\n}\n\nexport class GeminiCliAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Gemini CLI\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Gemini fires Before/AfterTool, PreCompress, SessionStart/End, BeforeAgent\n // (≈ UserPromptSubmit), and Notification. It has no `Stop` equivalent.\n preToolUse: true,\n postToolUse: true,\n preCompact: true,\n sessionStart: true,\n sessionEnd: true,\n userPromptSubmit: true,\n stop: false,\n notification: true,\n // Newer events: Gemini has no subagent lifecycle hooks, its permission\n // surface is observe-only (Notification with notification_type\n // \"ToolPermission\" — no decision control), and tool failure is merged into\n // AfterTool's tool_response.error rather than a dedicated event. None of\n // those analogs are wired, so permissionRequest / postToolUseFailure /\n // subagentStart / subagentStop stay unset — install reports the standard\n // skip-warn for them.\n // BeforeTool can rewrite tool input (hookSpecificOutput.tool_input); unlike\n // the Claude-family hosts, AfterTool CAN replace already-emitted tool output\n // (via a deny + reason), so output modification is supported here.\n canModifyArgs: true,\n canModifyOutput: true,\n canInjectSessionContext: true,\n // Transport is selected by key: command/args (stdio), url (sse), httpUrl (http).\n transports: [\"stdio\", \"sse\", \"http\"],\n // Content surfaces: Gemini CLI supports all three. Commands are authored as\n // TOML (description + prompt with {{args}} placeholders); skills follow the\n // uniform <geminiDir>/skills/<name>/SKILL.md layout; subagents are md+fm.\n supportsCommands: true,\n supportsSkills: true,\n supportsSubagents: true,\n // Native passthrough hooks: Gemini's LLM-lifecycle events (BeforeModel,\n // AfterAgent, BeforeToolSelection, AfterModel, …) have NO normalized\n // HookEventName — they are request-mutating and gemini-only, below the\n // >=3-host core bar (docs/research/host-specific-hook-events-design.md). A\n // connector reaches them by declaring platforms[\"gemini-cli\"].nativeHooks;\n // installHooks writes those event-name keys verbatim into settings.json with\n // the same home-bin command shape, and the generic uninstall reverses them.\n supportsNativeHooks: true,\n // Memory surface — EXCEPTION host: Gemini reads GEMINI.md by default;\n // AGENTS.md only when the user opted in via settings `context.fileName`.\n // memoryTargets below probes that setting (and NEVER edits it).\n supportsMemory: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(projectDir: string): DetectedPlatform {\n const userDir = join(homedir(), \".gemini\");\n const userSettings = join(userDir, \"settings.json\");\n const projectDirGemini = join(projectDir, \".gemini\");\n const projectSettings = join(projectDirGemini, \"settings.json\");\n const userInstalled = existsSync(userDir) || existsSync(userSettings);\n const projInstalled = existsSync(projectDirGemini) || existsSync(projectSettings);\n const installed = userInstalled || projInstalled;\n // Report the scope/path that actually matched, so a project-only install\n // isn't misreported as a (non-existent) user install.\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\n const configPath = scope === \"project\" ? projectSettings : userSettings;\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope,\n reason: installed\n ? scope === \"project\"\n ? `found project Gemini CLI config at ${projectSettings}`\n : `found Gemini CLI config under ${userDir}`\n : `no Gemini CLI config at ${userDir}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n getConfigDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".gemini\")\n : join(homedir(), \".gemini\");\n }\n\n /** MCP servers live in settings.json under `mcpServers`. */\n getServerConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n /** Hooks live in the SAME settings.json under the top-level `hooks` key. */\n getHookConfigPath(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"settings.json\");\n }\n\n // ── MCP server install / uninstall ───────────────────────────────────────\n\n installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST]?.server;\n if (!connector.server || override === false) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: connector.server\n ? \"server registration disabled for gemini-cli\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Shallow-merge any per-platform server override into the base ServerDef.\n const server: ServerDef =\n override && typeof override === \"object\"\n ? { ...connector.server, ...override }\n : connector.server;\n\n const serverPath = this.getServerConfigPath(ctx);\n const entry = this.renderServerEntry(ctx, server);\n\n return [\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\n ];\n }\n\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const serverPath = this.getServerConfigPath(ctx);\n return [\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\n ];\n }\n\n /**\n * Render a normalized ServerDef into Gemini's native mcpServers entry. The\n * transport is encoded by WHICH KEY is present, not a `type` field.\n */\n private renderServerEntry(\n ctx: InstallContext,\n server: ServerDef,\n ): GeminiStdioServer | GeminiSseServer | GeminiHttpServer {\n const transport: Transport = server.transport;\n\n if (transport === \"stdio\") {\n let command = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n // Transparent telemetry wrapping: route the real command through\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\n\n const entry: GeminiStdioServer = { command: resolveEnvRefsDeep(command) };\n if (args.length > 0) entry.args = args.map((a) => resolveEnvRefsDeep(a));\n const env = this.renderEnv(server.env);\n if (env) entry.env = env;\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\n return entry;\n }\n\n // SSE transport → `url` key.\n if (transport === \"sse\") {\n const entry: GeminiSseServer = { url: resolveEnvRefsDeep(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n // http (streamable-HTTP) and any other remote transport → `httpUrl` key.\n const entry: GeminiHttpServer = { httpUrl: resolveEnvRefsDeep(server.url ?? \"\") };\n const headers = this.renderEnv(server.headers);\n if (headers) entry.headers = headers;\n return entry;\n }\n\n /**\n * Render env/header values. Gemini's native settings token is `${VAR}` (not\n * the framework's `${env:VAR}`), so refs resolve to literals at install time —\n * the safe default for a host without `${env:VAR}` interpolation.\n */\n private renderEnv(\n env: Record<string, string> | undefined,\n ): Record<string, string> | undefined {\n if (!env || Object.keys(env).length === 0) return undefined;\n return resolveEnvRefsDeep({ ...env });\n }\n\n // ── Hook install / uninstall ─────────────────────────────────────────────\n\n installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const override = connector.platforms[HOST];\n\n // `hooks: false` disables only the NORMALIZED events (and the opt-in usage\n // sink). nativeHooks is a sibling, gemini-scoped declaration on the same\n // override and installs regardless — the dev wrote both keys on one object.\n const hooksDisabled = override?.hooks === false;\n const normalizedEvents = hooksDisabled ? [] : connector.hookEvents;\n const nativeHooks = override?.nativeHooks ?? {};\n const nativeEvents = Object.keys(nativeHooks);\n\n // The opt-in host-native usage hook (4a) is a host-native-only sink that does\n // NOT need a connector handler — so it may be installed even for a connector\n // that declares no normalized hook events. (Disabled by `hooks: false`, same\n // as before.)\n const hostNative = !hooksDisabled && isHostNativeUsageEnabled(connector.telemetry);\n if (normalizedEvents.length === 0 && nativeEvents.length === 0 && !hostNative) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n detail: hooksDisabled ? \"hooks disabled for gemini-cli\" : \"connector declares no hooks\",\n },\n ];\n }\n\n const settingsPath = this.getHookConfigPath(ctx);\n const settings = this.readJson<GeminiSettingsFile>(settingsPath) ?? {};\n const __skip = this.malformedHookRootSkip(\n settingsPath,\n (settings as Record<string, unknown>).hooks,\n );\n if (__skip) return [__skip];\n const hooks = (settings.hooks ??= {});\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const event of normalizedEvents) {\n const geminiEvent = EVENT_MAP[event];\n if (!geminiEvent) {\n // No Gemini equivalent for this normalized event (e.g. Stop) — report.\n changes.push({\n platform: this.id,\n action: \"warn\",\n path: settingsPath,\n detail: `${event} has no Gemini CLI hook equivalent — skipped`,\n });\n continue;\n }\n\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, connector.id);\n const matcher = connector.hooks[event]?.matcher ?? \"\";\n const entry: GeminiHookEntry = {\n matcher,\n hooks: [{ type: \"command\", command }],\n };\n\n const bucket = (hooks[geminiEvent] ??= []);\n const existingIdx = bucket.findIndex((e) => this.entryHasOurCommand(e, ctx));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: `hooks.${geminiEvent} already registered`,\n });\n continue;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: settingsPath,\n detail: `hooks.${geminiEvent}`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: settingsPath,\n detail: `hooks.${geminiEvent}`,\n });\n }\n mutated = true;\n }\n\n // NATIVE passthrough events: gemini-native event-name keys (e.g. BeforeModel)\n // written VERBATIM — no EVENT_MAP, since they ARE Gemini events, not\n // normalized ones. Same entry shape + idempotency as above.\n for (const event of nativeEvents) {\n const matcher = nativeHooks[event]?.matcher ?? \"\";\n if (this.upsertNativeHook(ctx, hooks, event, matcher, settingsPath, changes)) {\n mutated = true;\n }\n }\n\n // OPT-IN host-native usage hook (4a): when enabled, register an AfterModel\n // hook whose command is the hidden `usage-event` entrypoint. It carries no\n // matcher (it is not a tool event) and records a DISTINCT `model_turn` row.\n if (hostNative) {\n if (this.installUsageHook(hooks, ctx, settingsPath, changes)) mutated = true;\n }\n\n if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);\n return changes;\n }\n\n /**\n * Register the opt-in AfterModel host-native usage hook (4a) into `hooks`.\n * Idempotent: a byte-identical entry skips, a drifted one updates. Returns true\n * when the file was mutated. The command is the hidden `usage-event` entrypoint\n * (NOT a connector hook), so it carries an empty matcher.\n */\n private installUsageHook(\n hooks: Record<string, GeminiHookEntry[]>,\n ctx: InstallContext,\n settingsPath: string,\n changes: ChangeRecord[],\n ): boolean {\n const command = buildUsageEventCommand(ctx.homeBinPath, HOST, ctx.connector.id);\n const entry: GeminiHookEntry = {\n matcher: \"\",\n hooks: [{ type: \"command\", command }],\n };\n const bucket = (hooks[GEMINI_EVENT.AfterModel] ??= []);\n const existingIdx = bucket.findIndex((e) =>\n (e.hooks ?? []).some((h) => isUsageEventCommand(h.command, ctx.homeBinPath, ctx.connector.id)),\n );\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: `hooks.${GEMINI_EVENT.AfterModel} (host-native usage) already registered`,\n });\n return false;\n }\n bucket[existingIdx] = entry;\n changes.push({\n platform: this.id,\n action: \"update\",\n path: settingsPath,\n detail: `hooks.${GEMINI_EVENT.AfterModel} (host-native usage)`,\n });\n } else {\n bucket.push(entry);\n changes.push({\n platform: this.id,\n action: \"create\",\n path: settingsPath,\n detail: `hooks.${GEMINI_EVENT.AfterModel} (host-native usage)`,\n });\n }\n return true;\n }\n\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n const settingsPath = this.getHookConfigPath(ctx);\n const settings = this.readJson<GeminiSettingsFile>(settingsPath);\n const hooks = settings?.hooks;\n if (!settings || !hooks) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: \"no hooks section present\",\n },\n ];\n }\n\n const changes: ChangeRecord[] = [];\n let mutated = false;\n\n for (const geminiEvent of Object.keys(hooks)) {\n const bucket = hooks[geminiEvent];\n if (!Array.isArray(bucket)) continue;\n\n // Strip our hook command from each entry; drop entries left empty so we\n // never remove another connector's (or the user's own) hook commands.\n const next: GeminiHookEntry[] = [];\n let removed = 0;\n for (const e of bucket) {\n const innerBefore = e.hooks?.length ?? 0;\n const inner = (e.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\n removed += innerBefore - inner.length;\n if (inner.length > 0) next.push({ matcher: e.matcher ?? \"\", hooks: inner });\n }\n\n if (removed > 0) {\n if (next.length > 0) hooks[geminiEvent] = next;\n else delete hooks[geminiEvent];\n changes.push({\n platform: this.id,\n action: \"remove\",\n path: settingsPath,\n detail: `hooks.${geminiEvent} (${removed})`,\n });\n mutated = true;\n }\n }\n\n if (mutated) this.writeJson(settingsPath, settings, ctx.dryRun);\n if (changes.length === 0) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: \"no matching hook entries\",\n });\n }\n return changes;\n }\n\n /**\n * Upsert one NATIVE (gemini-native event-name) hook into `hooks[event]`. The key\n * is written verbatim (no EVENT_MAP). Matched by EXACT command — not just\n * \"one of ours\" — so a native key that coincides with a normalized event's\n * mapped key never clobbers the normalized entry; it adds a second, distinct\n * command instead. Idempotent: byte-identical → skip, drifted → update.\n */\n private upsertNativeHook(\n ctx: InstallContext,\n hooks: Record<string, GeminiHookEntry[]>,\n event: string,\n matcher: string,\n settingsPath: string,\n changes: ChangeRecord[],\n ): boolean {\n const command = buildHomeBinHookCommand(ctx.homeBinPath, HOST, event, ctx.connector.id);\n const entry: GeminiHookEntry = { matcher, hooks: [{ type: \"command\", command }] };\n const bucket = (hooks[event] ??= []);\n const existingIdx = bucket.findIndex((e) => (e.hooks ?? []).some((h) => h.command === command));\n\n if (existingIdx >= 0) {\n if (JSON.stringify(bucket[existingIdx]) === JSON.stringify(entry)) {\n changes.push({\n platform: this.id,\n action: \"skip\",\n path: settingsPath,\n detail: `hooks.${event} (native) already registered`,\n });\n return false;\n }\n bucket[existingIdx] = entry;\n changes.push({ platform: this.id, action: \"update\", path: settingsPath, detail: `hooks.${event} (native)` });\n } else {\n bucket.push(entry);\n changes.push({ platform: this.id, action: \"create\", path: settingsPath, detail: `hooks.${event} (native)` });\n }\n return true;\n }\n\n private entryHasOurCommand(entry: GeminiHookEntry, ctx: InstallContext): boolean {\n return (entry.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx));\n }\n\n /**\n * True when a hook command is ONE OF OURS for this connector — either the\n * universal `hook` dispatcher OR the opt-in `usage-event` sink. Both are\n * anchored on the connector id (see isHomeBinHookCommand) so a shared-prefix id\n * can't collide, and so uninstall reverses the AfterModel usage hook too.\n */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return (\n isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id) ||\n isUsageEventCommand(command, ctx.homeBinPath, ctx.connector.id)\n );\n }\n\n // ── Content surfaces: commands / skills / subagents ──────────────────────\n // CONTENT-ONLY: pure native-file writers under <geminiDir>/{commands,skills,\n // agents}. No runtime dispatch, no home-bin pointer, no telemetry wrap. Each\n // method is idempotent (byte-identical → skip) via BaseAdapter.writeContentFile\n // and reversible via removeContentFile. Honors platforms[\"gemini-cli\"]\n // per-surface false to skip. Commands are TOML (Gemini's native format, with\n // {{args}} placeholders preserved verbatim); skills/subagents mirror the\n // Claude reference (uniform SKILL.md + md+frontmatter subagents).\n\n private commandsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"commands\");\n }\n private skillsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"skills\");\n }\n private agentsDir(ctx: InstallContext): string {\n return join(this.getConfigDir(ctx), \"agents\");\n }\n\n /** Native command file path: <geminiDir>/commands/<name>.toml. */\n private commandPath(ctx: InstallContext, name: string): string {\n return join(this.commandsDir(ctx), `${name}.toml`);\n }\n /** Native skill dir: <geminiDir>/skills/<name>. */\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n /** Native subagent file path: <geminiDir>/agents/<name>.md. */\n private subagentPath(ctx: InstallContext, name: string): string {\n return join(this.agentsDir(ctx), `${name}.md`);\n }\n\n // ── Commands ──────────────────────────────────────────────────────────────\n\n override installCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.commands === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for gemini-cli\" }];\n }\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.writeContentFile(this.commandPath(ctx, cmd.name), this.renderCommand(cmd), ctx.dryRun),\n );\n }\n\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.commands.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\n }\n return connector.commands.map((cmd) =>\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\n );\n }\n\n /**\n * Render a command to Gemini's native TOML: { description, prompt }. Gemini\n * uses `{{args}}` placeholders in the prompt; the prompt body is passed\n * through verbatim so any placeholders are preserved.\n */\n private renderCommand(cmd: CommandDef): string {\n const obj: Record<string, unknown> = {};\n if (cmd.description !== undefined) obj.description = cmd.description;\n obj.prompt = cmd.prompt;\n return writeTomlString(obj);\n }\n\n // ── Skills ────────────────────────────────────────────────────────────────\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for gemini-cli\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Subagents ───────────────────────────────────────────────────────────────\n\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.subagents === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for gemini-cli\" }];\n }\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.writeContentFile(this.subagentPath(ctx, agent.name), renderSubagentMd(agent), ctx.dryRun),\n );\n }\n\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.subagents.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\n }\n return connector.subagents.map((agent) =>\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\n );\n }\n\n // ── Memory surface: GEMINI.md (default) / AGENTS.md (context.fileName opt-in) ─\n // EXCEPTION host. Gemini CLI reads GEMINI.md by default; AGENTS.md is read\n // ONLY when the user set `context.fileName` (string or array) to include it\n // in .gemini/settings.json. PROBE-AND-RESPECT: agent-connector never flips\n // that setting itself — it targets whichever file the running configuration\n // actually loads. NOTE: ~/.gemini is SHARED with Antigravity/agy; the\n // idempotent hash-stamped upsert dedupes convergent writes there.\n\n /**\n * True when project or user settings opt Gemini into reading AGENTS.md\n * (`context.fileName` includes \"AGENTS.md\"). Project settings are probed\n * first, then user settings; the first file that DECLARES context.fileName\n * decides (mirroring Gemini's setting precedence).\n */\n private agentsMdOptedIn(ctx: InstallContext): boolean {\n const candidates = [\n join(ctx.projectDir, \".gemini\", \"settings.json\"),\n join(homedir(), \".gemini\", \"settings.json\"),\n ];\n for (const p of candidates) {\n const settings = this.readJson<{ context?: { fileName?: unknown } }>(p);\n const fileName = settings?.context?.fileName;\n if (fileName === undefined) continue;\n if (typeof fileName === \"string\") return fileName === \"AGENTS.md\";\n if (Array.isArray(fileName)) return fileName.includes(\"AGENTS.md\");\n return false;\n }\n return false;\n }\n\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n // An explicit path override keeps the base resolution (escape hatch wins).\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\n const optedIn = this.agentsMdOptedIn(ctx);\n const file = optedIn ? \"AGENTS.md\" : \"GEMINI.md\";\n const reason = optedIn\n ? \"AGENTS.md (settings context.fileName opts Gemini into the agents.md standard)\"\n : \"GEMINI.md (gemini-cli default context file; AGENTS.md needs the context.fileName opt-in)\";\n return ctx.scope === \"project\"\n ? [{ path: join(ctx.projectDir, file), reason }]\n : [{ path: join(homedir(), \".gemini\", file), reason }];\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const settingsPath = this.getServerConfigPath(ctx);\n const connectorId = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: settings.json present`,\n check: () =>\n existsSync(settingsPath)\n ? { status: \"OK\", detail: settingsPath }\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) {\n return { status: \"OK\", detail: \"no hooks declared\" };\n }\n const settings = this.readJson<GeminiSettingsFile>(settingsPath);\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\n const hooks = settings.hooks ?? {};\n const registered = Object.values(hooks).some((entries) =>\n (entries ?? []).some((e) =>\n (e.hooks ?? []).some((h) =>\n isHomeBinHookCommand(h.command, homeBin, connectorId),\n ),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${settingsPath}` };\n },\n },\n ];\n\n // Content-surface checks: only assert presence of the files this connector\n // declares (skip silently for surfaces it never asked for).\n for (const cmd of ctx.connector.commands) {\n const p = this.commandPath(ctx, cmd.name);\n checks.push({\n name: `${this.name}: command ${cmd.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n for (const agent of ctx.connector.subagents) {\n const p = this.subagentPath(ctx, agent.name);\n checks.push({\n name: `${this.name}: subagent ${agent.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n // ── Runtime: parse Gemini stdin JSON → normalized event ──────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as GeminiWireInput;\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\n const sessionId = typeof input.session_id === \"string\" ? input.session_id : \"\";\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\n\n const base = {\n hostPlatform: HOST,\n connectorId,\n sessionId,\n raw,\n ...(projectDir !== undefined ? { projectDir } : {}),\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n // gemini-cli sends the result as `tool_response` (object), not `tool_output`,\n // and signals failure via `tool_response.error` (no top-level `is_error`).\n // See GeminiWireInput.tool_response above for the source citations.\n const toolOutput = extractToolOutput(input.tool_response);\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutput !== undefined ? { toolOutput } : {}),\n ...(hasToolError(input.tool_response) ? { isError: true } : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n const ev: SessionStartEvent = {\n ...base,\n source: normalizeSessionSource(input.source),\n };\n return ev;\n }\n case \"SessionEnd\": {\n const ev: SessionEndEvent = {\n ...base,\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\n };\n return ev;\n }\n case \"UserPromptSubmit\": {\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n default: {\n // Gemini never delivers `Stop`, `PermissionRequest`, `PostToolUseFailure`,\n // `SubagentStart`, or `SubagentStop` (no native equivalents wired). If\n // the runtime dispatches one anyway, surface it as an explicit\n // unsupported error so the mismatch is loud rather than silently\n // mis-parsed.\n throw new Error(`unsupported gemini-cli hook event: ${String(event)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Gemini native hook reply ──────────────\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // deny → Gemini blocks via a top-level `decision:\"deny\"` + reason (NOT the\n // Claude-style permissionDecision wrapper).\n if (decision === \"deny\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // ask → Gemini has no native \"ask\"; degrade to deny to stay fail-safe.\n if (decision === \"ask\") {\n return this.stdout({\n decision: \"deny\",\n reason: response.reason ?? \"Action requires user confirmation (security policy)\",\n });\n }\n\n // modify → rewrite BeforeTool input. Gemini merges tool_input with the\n // original; output rewrite on AfterTool is expressed as deny + reason.\n if (decision === \"modify\") {\n if (event === \"PreToolUse\" && response.updatedInput) {\n return this.stdout({\n hookSpecificOutput: { tool_input: response.updatedInput },\n });\n }\n if (event === \"PostToolUse\" && response.updatedOutput !== undefined) {\n return this.stdout({ decision: \"deny\", reason: response.updatedOutput });\n }\n // Nothing to apply; fall through to allow.\n }\n\n // context → inject soft guidance via hookSpecificOutput.additionalContext\n // (also the SessionStart / BeforeAgent context-injection path).\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({\n hookSpecificOutput: { additionalContext: response.additionalContext },\n });\n }\n\n // allow / void / unsupported-degradation → pass through with exit 0.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n}\n\nexport const adapter = new GeminiCliAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry","headers"]}
|
|
@@ -2,28 +2,28 @@
|
|
|
2
2
|
import {
|
|
3
3
|
readYaml,
|
|
4
4
|
yamlObjectMapCodec
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FJCUKXGX.js";
|
|
6
6
|
import {
|
|
7
7
|
roamingAppData
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-UM5S7DKK.js";
|
|
9
9
|
import {
|
|
10
10
|
normalizeSessionSource
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-H53QZQJI.js";
|
|
12
12
|
import {
|
|
13
13
|
resolveEnvRefsDeep
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BEFVJ2OE.js";
|
|
15
15
|
import {
|
|
16
16
|
BaseAdapter,
|
|
17
17
|
removeFromObjectMap,
|
|
18
18
|
renderSkillMd,
|
|
19
19
|
upsertInObjectMap
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-JTN3AKZO.js";
|
|
21
21
|
import {
|
|
22
22
|
buildWrappedStdio,
|
|
23
23
|
isHomeBinHookCommand
|
|
24
|
-
} from "./chunk-
|
|
25
|
-
import "./chunk-
|
|
26
|
-
import "./chunk-
|
|
24
|
+
} from "./chunk-QSY74NAP.js";
|
|
25
|
+
import "./chunk-UMQ6NBQR.js";
|
|
26
|
+
import "./chunk-GZGLCCEE.js";
|
|
27
27
|
|
|
28
28
|
// src/adapters/goose/index.ts
|
|
29
29
|
import { existsSync } from "fs";
|
|
@@ -603,4 +603,4 @@ export {
|
|
|
603
603
|
adapter,
|
|
604
604
|
goose_default as default
|
|
605
605
|
};
|
|
606
|
-
//# sourceMappingURL=goose-
|
|
606
|
+
//# sourceMappingURL=goose-3X7ID7YW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/goose/index.ts"],"sourcesContent":["/**\n * adapters/goose — Block's Goose platform adapter for agent-connector.\n *\n * Goose is a json-stdio host, but its two config surfaces use DIFFERENT formats:\n *\n * - MCP servers (Goose calls them \"extensions\") live in a YAML config under the\n * root key `extensions`. Goose's `ExtensionConfig` is a `#[serde(tag=\"type\")]`\n * enum (crates/goose/src/agents/extension.rs); we render two of its variants:\n * stdio → { type: \"stdio\", cmd: <exe>, args: [...], envs: {...}, timeout, enabled }\n * NOTE the field is `cmd` (NOT `command`) and the env map is `envs` (NOT\n * `env`).\n * http → { type: \"streamable_http\", uri, headers?, envs?, timeout, enabled }\n * Goose's CURRENT remote transport is Streamable HTTP — the field is `uri`\n * (NOT `url`). The legacy `type: \"sse\"` variant still deserializes for old\n * config-file compatibility but Goose REJECTS it at connect time\n * (\"SSE is unsupported, migrate to streamable_http\" —\n * crates/goose/src/agents/extension_manager.rs), so we do NOT emit it and\n * do NOT advertise `sse` in capabilities; an `sse`/`ws` server warn-skips.\n * Because the file is YAML, the BaseAdapter JSON helpers do not apply — we\n * merge via core/yaml's readYaml/writeYaml, preserving any other config.\n *\n * - Hooks use Goose's Open Plugins system, which stores hook registrations in\n * JSON at <root>/.agents/plugins/<plugin-name>/hooks/hooks.json (project root\n * = <projectDir>/.agents; user root = ~/.agents):\n * { hooks: { <Event>: [ { matcher?, hooks:[{ type:\"command\", command }] } ] } }\n * The shape is the Claude-style NESTED rule (an optional `matcher` plus an\n * inner `hooks` array), and there is NO top-level `version` key. This file is\n * plain JSON, so the standard fs/JSON helpers are used for it.\n *\n * Wire protocol (parse) is Claude-compatible JSON on stdin, except Goose names\n * the working directory field `working_dir` (not `cwd`). The deny reply is\n * Goose's `{ decision: \"block\", reason }` (NOT Claude's hookSpecificOutput\n * permissionDecision shape).\n *\n * Native config locations (user scope):\n * - Linux/macOS: ~/.config/goose/config.yaml\n * - Windows: %APPDATA%/Block/goose/config/config.yaml\n */\n\nimport { existsSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\n\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\nimport type {\n ChangeRecord,\n DetectedPlatform,\n HealthCheck,\n HookEventName,\n HookParadigm,\n HookResponse,\n NotificationEvent,\n PlatformCapabilities,\n PlatformId,\n PostToolUseEvent,\n PostToolUseFailureEvent,\n PreCompactEvent,\n PreToolUseEvent,\n SessionEndEvent,\n SessionStartEvent,\n ServerDef,\n StopEvent,\n Transport,\n UserPromptSubmitEvent,\n} from \"../../core/types.js\";\nimport { removeFromObjectMap, upsertInObjectMap } from \"../../core/object-map.js\";\nimport { roamingAppData } from \"../../core/host-paths.js\";\nimport { readYaml, yamlObjectMapCodec } from \"../../core/yaml.js\";\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\nimport { buildWrappedStdio, isHomeBinHookCommand } from \"../../core/spawn.js\";\nimport { renderSkillMd } from \"../claude-code/render.js\";\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\n\nconst HOST: PlatformId = \"goose\";\n/** Root key under which Goose stores MCP servers (\"extensions\") in config.yaml. */\nconst MCP_ROOT_KEY = \"extensions\";\n\n/**\n * Map each normalized hook event to the matching capability flag on this\n * adapter. The adapter's own `capabilities` literal is the single source of\n * truth for what Goose's Open-Plugins runtime delivers (PreToolUse/PostToolUse/\n * SessionStart/PostToolUseFailure); installHooks filters declared events\n * through this map so an unsupported event (e.g. UserPromptSubmit) is never\n * written verbatim into hooks.json — it is reported as a graceful warn/skip\n * instead.\n */\nconst EVENT_CAPABILITY: Record<HookEventName, keyof PlatformCapabilities> = {\n SessionStart: \"sessionStart\",\n SessionEnd: \"sessionEnd\",\n UserPromptSubmit: \"userPromptSubmit\",\n PreToolUse: \"preToolUse\",\n PostToolUse: \"postToolUse\",\n PreCompact: \"preCompact\",\n Stop: \"stop\",\n Notification: \"notification\",\n // Newer events. Goose's hooks system ships a dedicated PostToolUseFailure;\n // it has NO permission-dialog or subagent lifecycle events, so those three\n // flags stay unset on `capabilities` and warn-skip at install.\n PermissionRequest: \"permissionRequest\",\n PostToolUseFailure: \"postToolUseFailure\",\n SubagentStart: \"subagentStart\",\n SubagentStop: \"subagentStop\",\n // Goose has no post-compaction hook either — postCompact stays unset on\n // `capabilities`, so a declared PostCompact warn-skips at install.\n PostCompact: \"postCompact\",\n};\n\n/**\n * Goose extension (MCP server) entry — note the Goose-specific field names:\n * `cmd` (not `command`) and `envs` (not `env`).\n */\ninterface GooseStdioExtension {\n type: \"stdio\";\n cmd: string;\n args: string[];\n envs?: Record<string, string>;\n timeout: number;\n enabled: boolean;\n}\n\n/**\n * Goose remote extension (MCP Streamable HTTP server) — Goose's CURRENT remote\n * transport. Note the Goose-specific field name `uri` (NOT `url`); `headers` and\n * `envs` are the StreamableHttp variant's optional maps (see the `ExtensionConfig`\n * enum in crates/goose/src/agents/extension.rs).\n */\ninterface GooseStreamableHttpExtension {\n type: \"streamable_http\";\n uri: string;\n headers?: Record<string, string>;\n envs?: Record<string, string>;\n timeout: number;\n enabled: boolean;\n}\n\ntype GooseExtension = GooseStdioExtension | GooseStreamableHttpExtension;\n\n/** One inner command entry inside a hook rule. */\ninterface GooseHookCommand {\n type: \"command\";\n command: string;\n}\n\n/**\n * One nested-rule entry under a hook event. Goose's Open Plugins spec uses the\n * Claude-shaped nested rule: an optional `matcher` plus an inner `hooks` array\n * of `{ type, command }` commands (NOT a flat list of commands).\n */\ninterface GooseHookRule {\n matcher?: string;\n hooks: GooseHookCommand[];\n}\n\n/**\n * Goose Open-Plugins hooks.json shape: `{ hooks: { <Event>: [ rule, ... ] } }`.\n * There is NO top-level `version` key in the spec.\n */\ninterface GooseHooksFile {\n hooks: Record<string, GooseHookRule[]>;\n}\n\n/**\n * Raw Goose hook stdin payload — the serialized `HookContext` struct\n * (crates/goose/src/hooks/mod.rs:162-176). Goose's HookContext carries ONLY:\n * event, session_id, matcher_context, tool_name?, tool_input?, tool_output?,\n * message?, working_dir?\n * It is NOT Claude-compatible: there is no `prompt`, `tool_response`, `error`,\n * `is_error`, `source`, `reason`, `stop_hook_active`, `tool_use_id`,\n * `is_interrupt`, or `duration_ms` field on the wire — reading any of those\n * (kimi #189 false-friend class) yields undefined for every event. The prompt\n * rides on `message` (`.with_message`, agent.rs:1505-1509); the tool result\n * rides on `tool_output` (NOT `tool_response`).\n */\ninterface GooseWireInput {\n session_id?: string;\n /** Goose names the working directory `working_dir`; `cwd` is a fallback. */\n working_dir?: string;\n cwd?: string;\n hook_event_name?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n /** PostToolUse result field is `tool_output` (NOT Claude's `tool_response`);\n * goose's PostToolUse ctx never calls with_tool_output, so it is absent on the\n * wire — kept for forward-compat (agent.rs:534-536, hooks/mod.rs:171,200-203). */\n tool_output?: unknown;\n /** UserPromptSubmit prompt text lives here via `.with_message`\n * (agent.rs:1505-1509); goose has NO `prompt` field. */\n message?: string;\n trigger?: string;\n /** Injected by the entrypoint so the runtime knows which connector to dispatch. */\n connector?: string;\n}\n\nexport class GooseAdapter extends BaseAdapter implements Adapter {\n readonly id: PlatformId = HOST;\n readonly name = \"Goose\";\n readonly paradigm: HookParadigm = \"json-stdio\";\n\n readonly capabilities: PlatformCapabilities = {\n // Memory surface: AGENTS.md-first managed block (project <projectDir>/AGENTS.md\n // via the base default — goose reads AGENTS.md AND .goosehints at each level,\n // .goosehints left untouched; user scope → the global .goosehints below).\n supportsMemory: true,\n preToolUse: true,\n postToolUse: true,\n preCompact: false,\n sessionStart: true,\n // Goose's Open Plugins runtime fires SessionEnd / UserPromptSubmit / Stop\n // (goose-docs.ai/blog/2026/05/14/goose-hooks/); parseEvent + the wire types\n // already handle all three, so they are wired (were incorrectly gated false).\n sessionEnd: true,\n userPromptSubmit: true,\n stop: true,\n notification: false,\n // Newer events: Goose ships a dedicated PostToolUseFailure hook (feedback\n // beside the error; the failure itself is not blockable). Goose has no\n // permission-dialog event and no subagent lifecycle hooks, so\n // permissionRequest / subagentStart / subagentStop stay unset — install\n // reports the standard skip-warn for them.\n postToolUseFailure: true,\n // Open Plugins documents PreToolUse/PostToolUse/SessionStart; argument\n // rewrite is not guaranteed across versions, so default to the safe value.\n canModifyArgs: false,\n canModifyOutput: false,\n canInjectSessionContext: true,\n // Goose registers two MCP extension transports: local `stdio` and remote\n // `http` (rendered as Goose's `type: \"streamable_http\"`). The legacy\n // `type: \"sse\"` variant still parses for old-config compatibility but Goose\n // refuses to connect over it (\"SSE is unsupported, migrate to\n // streamable_http\" — crates/goose/src/agents/extension_manager.rs), so it is\n // NOT advertised — an `sse`/`ws` server warn-skips at install.\n transports: [\"stdio\", \"http\"],\n // Content surfaces: goose reads SKILL.md from the cross-agent .agents dir\n // skill → <projectDir>/.agents/skills/<name>/SKILL.md (project)\n // skill → ~/.agents/skills/<name>/SKILL.md (user)\n // (NOT ~/.config/goose). Commands/subagents have no confirmed native dir, so\n // those flags stay unset and warn-skip via the BaseAdapter default.\n supportsSkills: true,\n };\n\n // ── Detection ────────────────────────────────────────────────────────────\n\n detectInstalled(_projectDir: string): DetectedPlatform {\n const configPath = this.userConfigPath();\n const configDir = dirname(configPath);\n const installed = existsSync(configDir) || existsSync(configPath);\n return {\n id: this.id,\n name: this.name,\n installed,\n paradigm: this.paradigm,\n capabilities: this.capabilities,\n configPath,\n scope: \"user\",\n reason: installed\n ? `found Goose config at ${configPath}`\n : `no Goose config at ${configPath}`,\n confidence: installed ? \"high\" : \"low\",\n };\n }\n\n // ── Native paths ─────────────────────────────────────────────────────────\n\n override getConfigDir(_ctx: InstallContext): string {\n return dirname(this.userConfigPath());\n }\n\n /** MCP config: the YAML config.yaml (user scope). */\n override getServerConfigPath(_ctx: InstallContext): string {\n return this.userConfigPath();\n }\n\n /**\n * Hooks: Open-Plugins hooks.json under the `.agents/plugins/<plugin-name>/`\n * dir. The connector id is the plugin name. Project scope roots at\n * `<projectDir>/.agents`; user scope roots at `~/.agents`.\n */\n override getHookConfigPath(ctx: InstallContext): string {\n const root = ctx.scope === \"project\" ? ctx.projectDir : homedir();\n return join(root, \".agents\", \"plugins\", ctx.connector.id, \"hooks\", \"hooks.json\");\n }\n\n /**\n * OS-correct user config.yaml path:\n * - Windows: %APPDATA%/Block/goose/config/config.yaml\n * - macOS/Linux: ~/.config/goose/config.yaml\n */\n private userConfigPath(): string {\n if (process.platform === \"win32\") {\n return join(roamingAppData(), \"Block\", \"goose\", \"config\", \"config.yaml\");\n }\n return join(homedir(), \".config\", \"goose\", \"config.yaml\");\n }\n\n // ── Memory surface: global .goosehints at user scope ────────────────────\n // Project scope stays on the AGENTS.md base default (goose reads project\n // AGENTS.md and .goosehints at each level by default — one canonical copy in\n // the standard file; the user's .goosehints is never touched). User scope:\n // goose's only documented global memory file is the .goosehints next to\n // config.yaml (~/.config/goose/.goosehints; Windows under\n // %APPDATA%\\Block\\goose\\config — adapter-corroborated, verify per version).\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\n if (this.memoryOverride(ctx)?.path || ctx.scope !== \"user\") {\n return super.memoryTargets(ctx);\n }\n return [\n {\n path: join(dirname(this.userConfigPath()), \".goosehints\"),\n reason: \"goose global hints file (.goosehints beside config.yaml)\",\n },\n ];\n }\n\n // ── MCP server install / uninstall (YAML — merge via readYaml/writeYaml) ──\n\n override installServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const path = this.getServerConfigPath(ctx);\n const server = this.effectiveServer(ctx);\n\n if (!server) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path,\n detail: connector.server\n ? \"server registration disabled for goose\"\n : \"connector declares no MCP server\",\n },\n ];\n }\n\n // Goose registers stdio extensions ({ type:\"stdio\", cmd, args }) AND remote\n // Streamable-HTTP extensions ({ type:\"streamable_http\", uri }). It has no\n // live SSE transport (the `sse` variant parses but Goose refuses to connect —\n // crates/goose/src/agents/extension_manager.rs), so anything else is\n // reported, never silently written as a broken empty-cmd stdio entry.\n const transport: Transport = server.transport;\n const isStdio = transport === \"stdio\" && !!server.command;\n const isHttp = transport === \"http\" && !!server.url;\n if (!isStdio && !isHttp) {\n return [\n {\n platform: this.id,\n action: \"skip\",\n path,\n detail: `transport \"${transport}\" not registrable in ${MCP_ROOT_KEY} (stdio + http/streamable_http only)`,\n },\n ];\n }\n\n const symlink = this.symlinkPathWarning(path);\n if (symlink) return [symlink];\n\n const entry = this.renderExtension(ctx, server);\n\n // Merge into existing YAML, preserving every other config key + extension.\n return [\n upsertInObjectMap({\n codec: yamlObjectMapCodec(),\n rootKey: MCP_ROOT_KEY,\n policy: \"coerce\",\n platform: this.id,\n configPath: path,\n entryId: connector.id,\n entry,\n dryRun,\n }),\n ];\n }\n\n override uninstallServer(ctx: InstallContext): ChangeRecord[] {\n const { connector, dryRun } = ctx;\n const path = this.getServerConfigPath(ctx);\n const symlink = this.symlinkPathWarning(path);\n if (symlink) return [symlink];\n\n return [\n removeFromObjectMap({\n codec: yamlObjectMapCodec(),\n rootKey: MCP_ROOT_KEY,\n policy: \"coerce\",\n platform: this.id,\n configPath: path,\n entryId: connector.id,\n dryRun,\n }),\n ];\n }\n\n /**\n * Render a normalized ServerDef into Goose's native extension entry. Goose has\n * no native env interpolation, so `${env:VAR}` refs are resolved to literals at\n * install time.\n *\n * stdio → { type:\"stdio\", cmd, args, envs?, timeout, enabled } — honors the\n * telemetry serve-wrapper (cmd=homeBin, args=[serve…]).\n * http → { type:\"streamable_http\", uri, headers?, envs?, timeout, enabled } —\n * a remote URL has no local command to route through the serve proxy,\n * so it is never telemetry-wrapped; env-refs in uri/headers/env resolve\n * to literals. The Goose field is `uri` (NOT `url`).\n */\n private renderExtension(ctx: InstallContext, server: ServerDef): GooseExtension {\n const timeoutMs = server.timeoutMs;\n const timeout =\n typeof timeoutMs === \"number\" && timeoutMs > 0 ? Math.round(timeoutMs / 1000) : 300;\n\n // Remote (Streamable HTTP) — never serve-wrapped; `uri` is the Goose field.\n if (server.transport === \"http\") {\n const entry: GooseStreamableHttpExtension = {\n type: \"streamable_http\",\n uri: resolveEnvRefsDeep(server.url ?? \"\"),\n timeout,\n enabled: server.enabled !== false,\n };\n if (server.headers && Object.keys(server.headers).length > 0) {\n const headers: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.headers))) {\n headers[k] = String(v);\n }\n entry.headers = headers;\n }\n if (server.env && Object.keys(server.env).length > 0) {\n const envs: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {\n envs[k] = String(v);\n }\n entry.envs = envs;\n }\n return entry;\n }\n\n let cmd = server.command ?? \"\";\n let args = [...(server.args ?? [])];\n\n ({ command: cmd, args } = buildWrappedStdio(ctx, server, this.id, cmd, args));\n\n cmd = resolveEnvRefsDeep(cmd);\n args = resolveEnvRefsDeep(args);\n\n const entry: GooseStdioExtension = {\n type: \"stdio\",\n cmd,\n args,\n timeout,\n enabled: server.enabled !== false,\n };\n\n if (server.env && Object.keys(server.env).length > 0) {\n const envs: Record<string, string> = {};\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {\n envs[k] = String(v);\n }\n entry.envs = envs;\n }\n return entry;\n }\n\n // ── Hook install / uninstall (JSON Open-Plugins hooks.json) ───────────────\n\n override installHooks(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n const path = this.getHookConfigPath(ctx);\n\n if (connector.platforms[HOST]?.hooks === false) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"hooks disabled for goose\" }];\n }\n if (connector.hookEvents.length === 0) {\n return [{ platform: this.id, action: \"skip\", path, detail: \"connector declares no hooks\" }];\n }\n\n const pending = connector.hookEvents.map((event) => ({\n event,\n matcher: connector.hooks[event]?.matcher ?? \"\",\n }));\n return this.upsertHookEntries(ctx, path, pending, this.hookDescriptor(ctx));\n }\n\n override uninstallHooks(ctx: InstallContext): ChangeRecord[] {\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\n }\n\n /**\n * Goose's hook-merge descriptor for the shared object-map engine. Goose's hook\n * file is the DEDICATED per-connector `.agents/plugins/<id>/hooks/hooks.json`\n * (NESTED rule shape `{ matcher?, hooks:[{type,command}] }`), so every\n * observable string + ownership predicate is carried here to reproduce the\n * prior in-adapter loop byte-for-byte:\n * - malformedPolicy \"coerce\" — a present-but-malformed `hooks` root (array /\n * primitive, hand-edited) and a non-array event bucket are coerced to fresh\n * containers, matching the old readHooksFile coerce + the `??=` bucket fill.\n * - mapEvent = the CAPABILITY FILTER: an event Goose's Open-Plugins runtime\n * does not deliver (e.g. UserPromptSubmit, PreCompact) maps to undefined →\n * the engine emits the `<event> unsupported on goose — skipped` warn and\n * never writes it; supported events map to themselves (identity).\n * - entryOwnsCommand is connector-GENERIC (ANY of our commands in the nested\n * inner `hooks`) — the old ruleHasOurCommand.\n * - uninstall is NESTED: ownsEntryForRemove is never-true so the engine only\n * runs stripInner — strip our owned inner commands, keep foreign ones, drop\n * emptied rules. The rebuilt rule OMITS `matcher` when it was undefined\n * (distinct from claude/droid/qwen, which always emit a matcher); `removed`\n * is the inner-command count, surfaced in the `(<n>)` remove detail.\n */\n private hookDescriptor(ctx: InstallContext): HookMergeDescriptor<GooseHookRule> {\n return {\n malformedPolicy: \"coerce\",\n // CAPABILITY FILTER → identity-or-undefined: supported events map to\n // themselves; an unsupported one (capability !== true) maps to undefined,\n // routing it to the warn-skip path.\n mapEvent: (e) =>\n this.capabilities[EVENT_CAPABILITY[e as HookEventName]] === true ? e : undefined,\n unmappedWarnDetail: (e) => `${e} unsupported on goose — skipped`,\n // NESTED rule, matcher-FIRST key order (matches the old `desired`).\n renderEntry: (_event, matcher, command) => ({\n matcher,\n hooks: [{ type: \"command\", command }],\n }),\n // Connector-generic find (= the old ruleHasOurCommand): ANY inner command ours.\n entryOwnsCommand: (rule, _command) =>\n (rule.hooks ?? []).some((h) => this.isOurCommand(h.command, ctx)),\n // NESTED: never drop a whole rule; inner-strip only.\n ownsEntryForRemove: () => () => false,\n stripInner: (c) => (rule) => {\n const innerBefore = rule.hooks?.length ?? 0;\n const inner = (rule.hooks ?? []).filter((h) => !this.isOurCommand(h.command, c));\n return {\n // MATCHER-OMITTED-WHEN-UNDEFINED: reproduce the old rebuild exactly —\n // key order is `matcher` (only when present) then `hooks`.\n next:\n inner.length > 0\n ? { ...(rule.matcher !== undefined ? { matcher: rule.matcher } : {}), hooks: inner }\n : null,\n removed: innerBefore - inner.length,\n };\n },\n skipDetail: (e) => `hooks.${e}`,\n removeDetail: (e, n) => `hooks.${e} (${n})`,\n absentDetail: \"no hooks.json\",\n noMatchDetail: \"no matching hook entries\",\n };\n }\n\n /** True when a hook command is ours (anchored home-bin + connector id). */\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\n }\n\n // ── Diagnostics ──────────────────────────────────────────────────────────\n\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\n const serverPath = this.getServerConfigPath(ctx);\n const hookPath = this.getHookConfigPath(ctx);\n const id = ctx.connector.id;\n const homeBin = ctx.homeBinPath;\n const hookEvents = ctx.connector.hookEvents;\n const checks: HealthCheck[] = [\n {\n name: `${this.name}: config.yaml present`,\n check: () =>\n existsSync(serverPath)\n ? { status: \"OK\", detail: serverPath }\n : { status: \"FAIL\", detail: `not found: ${serverPath}` },\n },\n {\n name: `${this.name}: ${MCP_ROOT_KEY}.${id} registered`,\n check: () => {\n if (!ctx.connector.server) return { status: \"OK\", detail: \"no MCP server declared\" };\n const cfg = readYaml<Record<string, unknown>>(serverPath);\n const bucket = cfg?.[MCP_ROOT_KEY];\n const present =\n typeof bucket === \"object\" &&\n bucket !== null &&\n !Array.isArray(bucket) &&\n id in (bucket as Record<string, unknown>);\n return present\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${id}` }\n : { status: \"FAIL\", detail: `${MCP_ROOT_KEY}.${id} not found in ${serverPath}` };\n },\n },\n {\n name: `${this.name}: hook command registered`,\n check: () => {\n if (hookEvents.length === 0) return { status: \"OK\", detail: \"no hooks declared\" };\n const file = this.readJson<GooseHooksFile>(hookPath);\n if (!file || !file.hooks) {\n return { status: \"FAIL\", detail: `cannot read ${hookPath}` };\n }\n const registered = Object.values(file.hooks).some((bucket) =>\n (bucket ?? []).some((rule) =>\n (rule.hooks ?? []).some((h) => isHomeBinHookCommand(h.command, homeBin, id)),\n ),\n );\n return registered\n ? { status: \"OK\", detail: \"hook command present\" }\n : { status: \"FAIL\", detail: `no hook for ${id} in ${hookPath}` };\n },\n },\n ];\n\n // Content-surface checks: assert presence only for skills this connector\n // declares (goose skills live under the .agents skills dir at either scope).\n for (const skill of ctx.connector.skills) {\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\n checks.push({\n name: `${this.name}: skill ${skill.name} present`,\n check: () =>\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\n });\n }\n return checks;\n }\n\n // ── Content surface: skills ───────────────────────────────────────────────\n // CONTENT-ONLY: pure native-file writer. No runtime dispatch, no home-bin\n // pointer, no telemetry wrap. Idempotent (byte-identical → skip) via\n // writeContentFile and reversible via removeContentFile + removeDirIfEmpty.\n // Honors platforms[\"goose\"].skills === false to skip.\n //\n // goose reads SKILL.md from the cross-agent .agents dir (NOT ~/.config/goose):\n // project scope → <projectDir>/.agents/skills/<name>/SKILL.md\n // user scope → ~/.agents/skills/<name>/SKILL.md\n\n private skillsDir(ctx: InstallContext): string {\n return ctx.scope === \"project\"\n ? join(ctx.projectDir, \".agents\", \"skills\")\n : join(homedir(), \".agents\", \"skills\");\n }\n\n private skillDir(ctx: InstallContext, name: string): string {\n return join(this.skillsDir(ctx), name);\n }\n\n override installSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.platforms[HOST]?.skills === false) {\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for goose\" }];\n }\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n changes.push(\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\n );\n // Bundle any resource files beside SKILL.md (relative path → contents).\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\n // (config-time validation already rejects these, but never trust input).\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) {\n changes.push({\n platform: this.id,\n action: \"warn\",\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\n });\n continue;\n }\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\n }\n }\n return changes;\n }\n\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\n const { connector } = ctx;\n if (connector.skills.length === 0) {\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\n }\n const changes: ChangeRecord[] = [];\n for (const skill of connector.skills) {\n const dir = this.skillDir(ctx, skill.name);\n // Remove only the files we wrote (SKILL.md + declared resources), then the\n // skill dir itself when we own its full contents.\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\n for (const rel of Object.keys(skill.resources ?? {})) {\n const target = this.resolveWithin(dir, rel);\n if (target === null) continue; // never delete outside the skill dir\n changes.push(this.removeContentFile(target, ctx.dryRun));\n }\n // Only remove the skill dir when WE own its full contents — never rm -rf a\n // dir that still holds user-added / sibling-tool / shared files.\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\n }\n return changes;\n }\n\n // ── Runtime: parse Goose stdin JSON → normalized event ───────────────────\n\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\n const input = (raw ?? {}) as GooseWireInput;\n // Goose sends the working directory as `working_dir`; fall back to `cwd`.\n const projectDir =\n typeof input.working_dir === \"string\"\n ? input.working_dir\n : typeof input.cwd === \"string\"\n ? input.cwd\n : undefined;\n const base = {\n hostPlatform: HOST,\n connectorId: typeof input.connector === \"string\" ? input.connector : \"\",\n sessionId: typeof input.session_id === \"string\" ? input.session_id : \"\",\n ...(projectDir !== undefined ? { projectDir } : {}),\n raw,\n } as const;\n\n switch (event) {\n case \"PreToolUse\": {\n const ev: PreToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n };\n return ev;\n }\n case \"PostToolUse\": {\n // SOURCE (hooks/mod.rs:171, agent.rs:534-536): the result field is\n // `tool_output` (NOT `tool_response`), AND goose's PostToolUse ctx is\n // built with only with_tool + with_working_dir — it never calls\n // with_tool_output — so no output is on the wire today. The read is kept\n // for forward-compat (if goose later populates tool_output it maps here).\n // There is NO `is_error` field on HookContext: goose signals failure by\n // emitting PostToolUseFailure as a DISTINCT event (agent.rs:526-531),\n // not via a boolean — so isError is never set here.\n const ev: PostToolUseEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n ...(toolOutputToString(input.tool_output) !== undefined\n ? { toolOutput: toolOutputToString(input.tool_output) }\n : {}),\n };\n return ev;\n }\n case \"SessionStart\": {\n // SOURCE (agent.rs:409-416 emit_hook + hooks/mod.rs:736-737 test): goose\n // emits SessionStart as a BARE HookContext::new with no builders — its\n // struct has no `source` discriminator, so there is no field to read.\n // normalizeSessionSource(undefined) → 'startup'; that is the only honest\n // value goose can supply. If goose later adds a start-reason field, map\n // it here.\n const ev: SessionStartEvent = { ...base, source: normalizeSessionSource(undefined) };\n return ev;\n }\n case \"SessionEnd\": {\n // SOURCE (agent.rs:409-416 emit_hook): SessionEnd is also a bare\n // HookContext with no `reason` field on the struct — goose provides no\n // end-reason on stdin (the hooks/mod.rs `reason` is the hook→host deny\n // REPLY direction, not input). The optional normalized reason is omitted.\n const ev: SessionEndEvent = { ...base };\n return ev;\n }\n case \"UserPromptSubmit\": {\n // SOURCE (agent.rs:1505-1509 .with_message + hooks/mod.rs:173): goose has\n // NO `prompt` field; the prompt text is carried on `message`. Reading\n // input.prompt always dropped the whole prompt — read input.message.\n const ev: UserPromptSubmitEvent = {\n ...base,\n prompt: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PreCompact\": {\n const ev: PreCompactEvent = {\n ...base,\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\n ? { trigger: input.trigger }\n : {}),\n };\n return ev;\n }\n case \"Stop\": {\n // SOURCE (agent.rs:1851-1854, 2536-2539, 2575 emit_hook + hooks/mod.rs\n // :162-176): every Stop emit site constructs a bare HookContext::new\n // (Stop); the struct has no `stop_hook_active` field, so the optional\n // stopHookActive is omitted (goose emits no such boolean).\n const ev: StopEvent = { ...base };\n return ev;\n }\n case \"Notification\": {\n const ev: NotificationEvent = {\n ...base,\n message: typeof input.message === \"string\" ? input.message : \"\",\n };\n return ev;\n }\n case \"PostToolUseFailure\": {\n // SOURCE (agent.rs:526-537 + hooks/mod.rs:162-176): goose builds the\n // failure HookContext with ONLY with_tool + with_working_dir. The struct\n // carries no `error` text on the wire — HOST GAP: the failure message is\n // genuinely never serialized on stdin (the hooks/mod.rs `reason` is the\n // hook→host deny REPLY, not input), so the REQUIRED normalized `error`\n // stays \"\". There is also no `tool_use_id`, `is_interrupt`, or\n // `duration_ms` field on HookContext — those optional fields are omitted\n // (no correlation id / interrupt flag / duration is delivered).\n const ev: PostToolUseFailureEvent = {\n ...base,\n toolName: input.tool_name ?? \"\",\n toolInput: input.tool_input ?? {},\n error: \"\",\n };\n return ev;\n }\n case \"PermissionRequest\":\n case \"SubagentStart\":\n case \"SubagentStop\":\n case \"PostCompact\": {\n // No Goose analog (no permission-dialog event, no subagent lifecycle\n // hooks, no post-compaction hook). Install already skip-warns these via\n // EVENT_CAPABILITY; a runtime dispatch is a mis-route — fail loudly.\n throw new Error(`unsupported goose hook event: ${String(event)}`);\n }\n default: {\n const _never: never = event;\n throw new Error(`unsupported goose hook event: ${String(_never)}`);\n }\n }\n }\n\n // ── Runtime: normalized response → Goose native hook reply (Claude-shaped) ─\n\n formatReply(event: HookEventName, response: HookResponse): HookReply {\n const decision = response.decision ?? \"allow\";\n\n // PostToolUseFailure is feedback-only (the tool already failed, nothing is\n // blockable): \"context\" injects additionalContext beside the error, and a\n // \"deny\" DEGRADES to the same shape carrying the reason — it must never\n // render as `{ decision: \"block\" }`.\n if (event === \"PostToolUseFailure\") {\n const context =\n decision === \"context\"\n ? response.additionalContext\n : decision === \"deny\"\n ? response.reason ?? response.additionalContext\n : undefined;\n if (context) return this.stdout({ additionalContext: context });\n return { exitCode: 0 };\n }\n\n // deny → Goose blocks via `{ decision: \"block\", reason }` on stdout JSON\n // (NOT Claude's hookSpecificOutput.permissionDecision shape).\n if (decision === \"deny\") {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Blocked by hook\",\n });\n }\n\n // ask → Goose has no native \"ask\"; degrade to block to stay fail-safe.\n if (decision === \"ask\") {\n return this.stdout({\n decision: \"block\",\n reason: response.reason ?? \"Confirmation required by hook\",\n });\n }\n\n if (decision === \"context\" && response.additionalContext) {\n return this.stdout({ additionalContext: response.additionalContext });\n }\n\n // allow / modify (unsupported) / void → pass through.\n return { exitCode: 0 };\n }\n\n private stdout(payload: unknown): HookReply {\n return { exitCode: 0, stdout: JSON.stringify(payload) };\n }\n\n // ── Internal helpers ──────────────────────────────────────────────────────\n\n /** Resolve the per-platform server override into an effective ServerDef. */\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\n const override = ctx.connector.platforms[this.id]?.server;\n if (override === false) return undefined;\n const base = ctx.connector.server;\n if (!base) return undefined;\n return override && typeof override === \"object\" ? { ...base, ...override } : base;\n }\n}\n\n/** Coerce a Goose PostToolUse `tool_output` (hooks/mod.rs:171) into a string. */\nfunction toolOutputToString(value: unknown): string | undefined {\n if (value == null) return undefined;\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport const adapter = new GooseAdapter();\nexport default adapter;\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
openSqlite
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-YT43MUSJ.js";
|
|
5
5
|
import {
|
|
6
6
|
firstExistingRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-O7SDRBVB.js";
|
|
8
8
|
import {
|
|
9
9
|
emptyTokens,
|
|
10
10
|
inferProvider
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-XD7MY6HB.js";
|
|
12
12
|
|
|
13
13
|
// src/usage/readers/goose.ts
|
|
14
14
|
var PLATFORM_ID = "goose";
|
|
@@ -209,4 +209,4 @@ var goose_default = gooseReader;
|
|
|
209
209
|
export {
|
|
210
210
|
goose_default as default
|
|
211
211
|
};
|
|
212
|
-
//# sourceMappingURL=goose-
|
|
212
|
+
//# sourceMappingURL=goose-64V46Y2W.js.map
|