@ken-jo/agent-connector 0.4.98 → 0.4.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -202
- package/NOTICE +6 -6
- package/README.md +604 -596
- package/dist/{action-5JM23CFJ.js → action-5OEM3QC4.js} +17 -16
- package/dist/action-5OEM3QC4.js.map +1 -0
- package/dist/{amazon-q-LFZNGN27.js → amazon-q-7DPVJXJN.js} +6 -6
- package/dist/amazon-q-7DPVJXJN.js.map +1 -0
- package/dist/{amp-CEWOSWQO.js → amp-BQZOL5GR.js} +4 -4
- package/dist/amp-BQZOL5GR.js.map +1 -0
- package/dist/{amp-S22XTPEQ.js → amp-VYXZWHXW.js} +7 -7
- package/dist/amp-VYXZWHXW.js.map +1 -0
- package/dist/{antigravity-LHFEFNMC.js → antigravity-EA4L225L.js} +5 -5
- package/dist/antigravity-EA4L225L.js.map +1 -0
- package/dist/antigravity-VXHL6ZPM.js +18 -0
- package/dist/{antigravity-cli-MOKFSWOU.js → antigravity-cli-B2HXZFYQ.js} +5 -5
- package/dist/antigravity-cli-B2HXZFYQ.js.map +1 -0
- package/dist/{antigravity-cli-PN474FXM.js → antigravity-cli-JHQ7JGNX.js} +10 -9
- package/dist/antigravity-cli-JHQ7JGNX.js.map +1 -0
- package/dist/{audit-2H7E3Z4N.js → audit-BO7JQYIH.js} +8 -8
- package/dist/{chunk-7C2IPIIB.js → chunk-2Y2MZRLP.js} +3 -3
- package/dist/chunk-2Y2MZRLP.js.map +1 -0
- package/dist/{chunk-B6PKHS5I.js → chunk-4KIXXJ7B.js} +2 -2
- package/dist/chunk-4KIXXJ7B.js.map +1 -0
- package/dist/chunk-4NFDNY3C.js +34 -0
- package/dist/chunk-4NFDNY3C.js.map +1 -0
- package/dist/{chunk-RPWD5H6Y.js → chunk-4QXCNZMD.js} +5 -5
- package/dist/chunk-4QXCNZMD.js.map +1 -0
- package/dist/{chunk-Q7PR2WGT.js → chunk-6TF7MHG5.js} +2 -2
- package/dist/chunk-6TF7MHG5.js.map +1 -0
- package/dist/{chunk-KWC5DQ5Z.js → chunk-6WN37NVN.js} +113 -10
- package/dist/chunk-6WN37NVN.js.map +1 -0
- package/dist/{chunk-DWZ5IWF4.js → chunk-6XMV2OOA.js} +6 -6
- package/dist/chunk-6XMV2OOA.js.map +1 -0
- package/dist/{chunk-XXLCMSD3.js → chunk-BEFVJ2OE.js} +1 -1
- package/dist/chunk-BEFVJ2OE.js.map +1 -0
- package/dist/{chunk-HATCOSQT.js → chunk-BV5WK6VQ.js} +19 -19
- package/dist/chunk-BV5WK6VQ.js.map +1 -0
- package/dist/{chunk-KTBAB556.js → chunk-BXPSDNIB.js} +2 -2
- package/dist/chunk-BXPSDNIB.js.map +1 -0
- package/dist/{chunk-Q4ISQHUQ.js → chunk-FBJQGRET.js} +1 -1
- package/dist/chunk-FBJQGRET.js.map +1 -0
- package/dist/{chunk-THI4PI4H.js → chunk-FJCUKXGX.js} +2 -2
- package/dist/chunk-FJCUKXGX.js.map +1 -0
- package/dist/{chunk-6XWORQM6.js → chunk-FKW5A6HE.js} +23 -7
- package/dist/chunk-FKW5A6HE.js.map +1 -0
- package/dist/{chunk-TOSNS2BY.js → chunk-G5HAIYRM.js} +43 -43
- package/dist/chunk-G5HAIYRM.js.map +1 -0
- package/dist/{chunk-RNVIK5YJ.js → chunk-GDIAHWNY.js} +2 -2
- package/dist/chunk-GDIAHWNY.js.map +1 -0
- package/dist/{chunk-QYOUQCC6.js → chunk-GZGLCCEE.js} +1 -1
- package/dist/chunk-GZGLCCEE.js.map +1 -0
- package/dist/{chunk-PSGTHJQU.js → chunk-H53QZQJI.js} +1 -1
- package/dist/chunk-H53QZQJI.js.map +1 -0
- package/dist/{chunk-7HHW23AC.js → chunk-IRUYJD23.js} +29 -29
- package/dist/chunk-IRUYJD23.js.map +1 -0
- package/dist/{chunk-IOJDZJ72.js → chunk-IVAWP6HH.js} +2 -2
- package/dist/chunk-IVAWP6HH.js.map +1 -0
- package/dist/{chunk-UNU2KPYJ.js → chunk-JTN3AKZO.js} +23 -15
- package/dist/chunk-JTN3AKZO.js.map +1 -0
- package/dist/{chunk-4GH2KA7V.js → chunk-KHO5WNTP.js} +1 -1
- package/dist/chunk-KHO5WNTP.js.map +1 -0
- package/dist/{chunk-S25MVWBP.js → chunk-KLZBRNFP.js} +12 -12
- package/dist/chunk-KLZBRNFP.js.map +1 -0
- package/dist/{chunk-DOPFBUCX.js → chunk-M6OS4OLU.js} +3 -3
- package/dist/chunk-M6OS4OLU.js.map +1 -0
- package/dist/{chunk-UZZTWWGG.js → chunk-MQPNU2CY.js} +1 -1
- package/dist/chunk-MQPNU2CY.js.map +1 -0
- package/dist/{chunk-LZL2YITN.js → chunk-N4STCQGP.js} +7 -7
- package/dist/chunk-N4STCQGP.js.map +1 -0
- package/dist/{chunk-KFPSJRHR.js → chunk-NBYKLUF6.js} +2 -2
- package/dist/chunk-NBYKLUF6.js.map +1 -0
- package/dist/{chunk-KM2YXO6V.js → chunk-O7SDRBVB.js} +1 -1
- package/dist/chunk-O7SDRBVB.js.map +1 -0
- package/dist/{chunk-LFWYYWLV.js → chunk-OP4KBXUO.js} +1 -1
- package/dist/chunk-OP4KBXUO.js.map +1 -0
- package/dist/{chunk-XN7S44U4.js → chunk-OPXAP3AC.js} +1 -1
- package/dist/chunk-OPXAP3AC.js.map +1 -0
- package/dist/{chunk-LD5HAN6O.js → chunk-PWCBWAM4.js} +6 -4
- package/dist/chunk-PWCBWAM4.js.map +1 -0
- package/dist/{chunk-W7AGWAMH.js → chunk-QSY74NAP.js} +2 -2
- package/dist/chunk-QSY74NAP.js.map +1 -0
- package/dist/{chunk-ZSOS2KOR.js → chunk-RK6VBLXP.js} +1 -1
- package/dist/chunk-RK6VBLXP.js.map +1 -0
- package/dist/{chunk-7VSZXOXJ.js → chunk-SFY6YLVK.js} +19 -12
- package/dist/chunk-SFY6YLVK.js.map +1 -0
- package/dist/{chunk-C747DYNT.js → chunk-UM5S7DKK.js} +1 -1
- package/dist/chunk-UM5S7DKK.js.map +1 -0
- package/dist/{chunk-ILWHLGIC.js → chunk-UMQ6NBQR.js} +2 -2
- package/dist/chunk-UMQ6NBQR.js.map +1 -0
- package/dist/{chunk-7PSNXUFK.js → chunk-XD7MY6HB.js} +1 -1
- package/dist/chunk-XD7MY6HB.js.map +1 -0
- package/dist/{chunk-FJ6F5U3W.js → chunk-XY3N2U6L.js} +5 -5
- package/dist/chunk-XY3N2U6L.js.map +1 -0
- package/dist/{chunk-XZWMJLIT.js → chunk-YT43MUSJ.js} +1 -1
- package/dist/chunk-YT43MUSJ.js.map +1 -0
- package/dist/{claude-code-TA53454O.js → claude-code-LJ6DVXWQ.js} +22 -12
- package/dist/claude-code-LJ6DVXWQ.js.map +1 -0
- package/dist/{claude-code-FS42PXZO.js → claude-code-NMRKTAP7.js} +4 -4
- package/dist/claude-code-NMRKTAP7.js.map +1 -0
- package/dist/cli/sdk.js +7 -7
- package/dist/cli/sdk.js.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/{cline-GZFN32BM.js → cline-JAPJNOZQ.js} +6 -6
- package/dist/cline-JAPJNOZQ.js.map +1 -0
- package/dist/{codebuddy-IYS3TQZ3.js → codebuddy-GC7VAE2Y.js} +7 -7
- package/dist/codebuddy-GC7VAE2Y.js.map +1 -0
- package/dist/{codebuff-D3MIKJHC.js → codebuff-3VODFPD4.js} +6 -6
- package/dist/codebuff-3VODFPD4.js.map +1 -0
- package/dist/{codebuff-6KWBW6CT.js → codebuff-ETYT5UBL.js} +4 -4
- package/dist/codebuff-ETYT5UBL.js.map +1 -0
- package/dist/{codex-ZKLP5IXZ.js → codex-RXIS5BHM.js} +9 -9
- package/dist/codex-RXIS5BHM.js.map +1 -0
- package/dist/{codex-DKBAAUCO.js → codex-YAORPCOD.js} +4 -4
- package/dist/codex-YAORPCOD.js.map +1 -0
- package/dist/{continue-I34FNSTJ.js → continue-MECVDV4Z.js} +8 -8
- package/dist/continue-MECVDV4Z.js.map +1 -0
- package/dist/{copilot-cli-CLBJACQ5.js → copilot-cli-MZTAWMPW.js} +4 -4
- package/dist/copilot-cli-MZTAWMPW.js.map +1 -0
- package/dist/{copilot-cli-NWPM5GE6.js → copilot-cli-WVWAWNSM.js} +7 -7
- package/dist/copilot-cli-WVWAWNSM.js.map +1 -0
- package/dist/{crush-A5C5USRL.js → crush-QBXLNN7T.js} +4 -4
- package/dist/crush-QBXLNN7T.js.map +1 -0
- package/dist/{crush-MDGPZSZU.js → crush-YB3SK6NK.js} +7 -7
- package/dist/crush-YB3SK6NK.js.map +1 -0
- package/dist/{cursor-D5SWDVSW.js → cursor-DIW43TRZ.js} +3 -3
- package/dist/cursor-DIW43TRZ.js.map +1 -0
- package/dist/cursor-RSLHA2CY.js +22 -0
- package/dist/{define-connector-B7tLHVnx.d.ts → define-connector-odRHEC4H.d.ts} +1 -1
- package/dist/{detect-FKJC36P4.js → detect-ALP4G7WG.js} +4 -4
- package/dist/detect-ALP4G7WG.js.map +1 -0
- package/dist/{devin-TZMRC57O.js → devin-WPDN3MXE.js} +7 -7
- package/dist/devin-WPDN3MXE.js.map +1 -0
- package/dist/{doctor-PGVYUQYG.js → doctor-YEQWCWZJ.js} +27 -26
- package/dist/doctor-YEQWCWZJ.js.map +1 -0
- package/dist/{droid-SCFWDJR4.js → droid-HS6MX3IL.js} +10 -8
- package/dist/droid-HS6MX3IL.js.map +1 -0
- package/dist/{droid-PFQ2PZSF.js → droid-U3ZBLQFO.js} +4 -4
- package/dist/droid-U3ZBLQFO.js.map +1 -0
- package/dist/{gemini-cli-Y6RJMU24.js → gemini-cli-NMVVBO3K.js} +4 -4
- package/dist/gemini-cli-NMVVBO3K.js.map +1 -0
- package/dist/{gemini-cli-MLDGOR2L.js → gemini-cli-VJ6X5DNF.js} +8 -8
- package/dist/gemini-cli-VJ6X5DNF.js.map +1 -0
- package/dist/{goose-5DBHDSJW.js → goose-3X7ID7YW.js} +9 -9
- package/dist/goose-3X7ID7YW.js.map +1 -0
- package/dist/{goose-K2HKUTBK.js → goose-64V46Y2W.js} +4 -4
- package/dist/goose-64V46Y2W.js.map +1 -0
- package/dist/{grok-cli-LX6Q6RUY.js → grok-cli-4VFVF2CQ.js} +7 -7
- package/dist/grok-cli-4VFVF2CQ.js.map +1 -0
- package/dist/{hermes-LJB3SJKB.js → hermes-AIVUE7LX.js} +10 -8
- package/dist/hermes-AIVUE7LX.js.map +1 -0
- package/dist/{hermes-MF3NX4ZY.js → hermes-F3EGTK6N.js} +4 -4
- package/dist/hermes-F3EGTK6N.js.map +1 -0
- package/dist/{hook-PVGBQUQI.js → hook-F63I3SD5.js} +17 -16
- package/dist/hook-F63I3SD5.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +5 -5
- package/dist/{install-HPDIK7F6.js → install-23WRRFBY.js} +21 -21
- package/dist/install-23WRRFBY.js.map +1 -0
- package/dist/{introspect-DWCu0Krk.d.ts → introspect-gTx6GzpW.d.ts} +1 -1
- package/dist/{jetbrains-copilot-2DSVAJMJ.js → jetbrains-copilot-XBO2JZRO.js} +6 -6
- package/dist/jetbrains-copilot-XBO2JZRO.js.map +1 -0
- package/dist/{junie-GUBDRADP.js → junie-UCOS6Q37.js} +6 -6
- package/dist/junie-UCOS6Q37.js.map +1 -0
- package/dist/{kilo-SMHPOHJ5.js → kilo-SW7BH6EG.js} +4 -4
- package/dist/kilo-SW7BH6EG.js.map +1 -0
- package/dist/{kilo-HRLWMENX.js → kilo-T4OXNUYY.js} +8 -8
- package/dist/kilo-T4OXNUYY.js.map +1 -0
- package/dist/{kilo-cli-IQMFMYZF.js → kilo-cli-I2S3W245.js} +8 -8
- package/dist/kilo-cli-I2S3W245.js.map +1 -0
- package/dist/{kilo-cli-T2SRRRJS.js → kilo-cli-ZF272ZHN.js} +5 -5
- package/dist/kilo-cli-ZF272ZHN.js.map +1 -0
- package/dist/{kimi-MSIDEMCI.js → kimi-5FHEXGZD.js} +4 -4
- package/dist/kimi-5FHEXGZD.js.map +1 -0
- package/dist/{kimi-EPD46UJK.js → kimi-VLSUFLYV.js} +7 -7
- package/dist/kimi-VLSUFLYV.js.map +1 -0
- package/dist/{kiro-A7DL52FX.js → kiro-AQFXGOJX.js} +10 -8
- package/dist/kiro-AQFXGOJX.js.map +1 -0
- package/dist/{kiro-NYRRBIKW.js → kiro-WGOI5CGT.js} +4 -4
- package/dist/kiro-WGOI5CGT.js.map +1 -0
- package/dist/{leaderboard-KCT7XPCI.js → leaderboard-YBD3IKC2.js} +7 -7
- package/dist/leaderboard-YBD3IKC2.js.map +1 -0
- package/dist/{mimo-code-NDGLBXNC.js → mimo-code-KETL7W7D.js} +7 -7
- package/dist/mimo-code-KETL7W7D.js.map +1 -0
- package/dist/{mistral-vibe-LLWASF5X.js → mistral-vibe-3AU7N2CA.js} +6 -6
- package/dist/mistral-vibe-3AU7N2CA.js.map +1 -0
- package/dist/{mux-ON4QK3OC.js → mux-BO2L5CTW.js} +6 -6
- package/dist/mux-BO2L5CTW.js.map +1 -0
- package/dist/{mux-7PIJ7HUQ.js → mux-XM6AP35L.js} +4 -4
- package/dist/mux-XM6AP35L.js.map +1 -0
- package/dist/{nemoclaw-45R5MFBF.js → nemoclaw-WA7RSKF2.js} +7 -7
- package/dist/nemoclaw-WA7RSKF2.js.map +1 -0
- package/dist/{omp-ROCTFV3A.js → omp-UDYJ2PYY.js} +9 -7
- package/dist/omp-UDYJ2PYY.js.map +1 -0
- package/dist/{open-interpreter-V6CN542J.js → open-interpreter-WMBNM4MQ.js} +6 -6
- package/dist/open-interpreter-WMBNM4MQ.js.map +1 -0
- package/dist/openclaw-3DHVHX5P.js +17 -0
- package/dist/{openclaw-KAFTNLR2.js → openclaw-5EQFGOWL.js} +4 -4
- package/dist/openclaw-5EQFGOWL.js.map +1 -0
- package/dist/{opencode-YYWQ45LF.js → opencode-IKMI3RI7.js} +7 -7
- package/dist/opencode-IKMI3RI7.js.map +1 -0
- package/dist/{opencode-Z65JYILL.js → opencode-QGP4ALQY.js} +4 -4
- package/dist/opencode-QGP4ALQY.js.map +1 -0
- package/dist/{openhands-OFFMWCQW.js → openhands-QGXMQR6I.js} +7 -7
- package/dist/openhands-QGXMQR6I.js.map +1 -0
- package/dist/{package-TALOSRQ4.js → package-TAUTPP7Z.js} +15 -15
- package/dist/package-TAUTPP7Z.js.map +1 -0
- package/dist/{pi-4W74ETTI.js → pi-A2HCGRJG.js} +9 -7
- package/dist/pi-A2HCGRJG.js.map +1 -0
- package/dist/{pi-DLKCPOJE.js → pi-GGDQREVG.js} +4 -4
- package/dist/pi-GGDQREVG.js.map +1 -0
- package/dist/{qwen-code-JOBFNEVT.js → qwen-code-DNQTGJOF.js} +28 -10
- package/dist/qwen-code-DNQTGJOF.js.map +1 -0
- package/dist/{qwen-code-26CSFDX6.js → qwen-code-GQILBJ5B.js} +4 -4
- package/dist/qwen-code-GQILBJ5B.js.map +1 -0
- package/dist/{roo-code-HSAE2CJU.js → roo-code-SUWI4BBN.js} +4 -4
- package/dist/roo-code-SUWI4BBN.js.map +1 -0
- package/dist/{roo-code-RHIGJZNY.js → roo-code-VI2ZKTZC.js} +6 -6
- package/dist/roo-code-VI2ZKTZC.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -1
- package/dist/runtime/index.js +15 -14
- package/dist/sdk/index.d.ts +4 -4
- package/dist/sdk/index.js +6 -6
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/test.d.ts +2 -2
- package/dist/sdk/test.js +12 -11
- package/dist/{serve-4TEHK726.js → serve-6MDLRQS2.js} +17 -16
- package/dist/serve-6MDLRQS2.js.map +1 -0
- package/dist/{status-DVD4EHMX.js → status-IUP75XHP.js} +11 -11
- package/dist/status-IUP75XHP.js.map +1 -0
- package/dist/{statusline-ZVNH7XBK.js → statusline-PRODZV2J.js} +16 -15
- package/dist/statusline-PRODZV2J.js.map +1 -0
- package/dist/{synthetic-LUT6V6SD.js → synthetic-6FRA7P5Q.js} +4 -4
- package/dist/synthetic-6FRA7P5Q.js.map +1 -0
- package/dist/{telemetry-NWUJPIK3.js → telemetry-X4PLZEDB.js} +10 -10
- package/dist/telemetry-X4PLZEDB.js.map +1 -0
- package/dist/{trae-SIQI3C66.js → trae-CPPYASR2.js} +4 -4
- package/dist/trae-CPPYASR2.js.map +1 -0
- package/dist/{trae-TLAFSQRQ.js → trae-VOJXUYRN.js} +6 -6
- package/dist/trae-VOJXUYRN.js.map +1 -0
- package/dist/{types-C6j18a6R.d.ts → types-DWXnnx-N.d.ts} +83 -8
- package/dist/{uninstall-DZVFV7KE.js → uninstall-BSIJ4QXN.js} +21 -21
- package/dist/uninstall-BSIJ4QXN.js.map +1 -0
- package/dist/{upgrade-OUE4ED52.js → upgrade-ZSICU3NE.js} +21 -21
- package/dist/upgrade-ZSICU3NE.js.map +1 -0
- package/dist/{usage-NT3ZXALZ.js → usage-EQUNVSCT.js} +4 -4
- package/dist/usage-EQUNVSCT.js.map +1 -0
- package/dist/{usage-event-IELZE6WO.js → usage-event-J5CQ6LNT.js} +16 -15
- package/dist/usage-event-J5CQ6LNT.js.map +1 -0
- package/dist/{vscode-copilot-VZ5XYSTK.js → vscode-copilot-ZBXRPKGG.js} +7 -7
- package/dist/vscode-copilot-ZBXRPKGG.js.map +1 -0
- package/dist/{warp-5YBSP7FP.js → warp-NRBBJQR2.js} +4 -4
- package/dist/warp-NRBBJQR2.js.map +1 -0
- package/dist/{warp-P2HWXIKT.js → warp-S444B2S3.js} +9 -7
- package/dist/warp-S444B2S3.js.map +1 -0
- package/dist/{windsurf-3JC73GZK.js → windsurf-R6D2JUTN.js} +6 -6
- package/dist/windsurf-R6D2JUTN.js.map +1 -0
- package/dist/{zed-6CMUKXLI.js → zed-DQV3ZUCU.js} +10 -8
- package/dist/zed-DQV3ZUCU.js.map +1 -0
- package/dist/{zed-XXCNYOIN.js → zed-XJFOOKCO.js} +4 -4
- package/dist/zed-XJFOOKCO.js.map +1 -0
- package/package.json +88 -88
- package/dist/action-5JM23CFJ.js.map +0 -1
- package/dist/amazon-q-LFZNGN27.js.map +0 -1
- package/dist/amp-CEWOSWQO.js.map +0 -1
- package/dist/amp-S22XTPEQ.js.map +0 -1
- package/dist/antigravity-LHFEFNMC.js.map +0 -1
- package/dist/antigravity-PZXYAO3X.js +0 -18
- package/dist/antigravity-cli-MOKFSWOU.js.map +0 -1
- package/dist/antigravity-cli-PN474FXM.js.map +0 -1
- package/dist/chunk-4GH2KA7V.js.map +0 -1
- package/dist/chunk-6XWORQM6.js.map +0 -1
- package/dist/chunk-7C2IPIIB.js.map +0 -1
- package/dist/chunk-7HHW23AC.js.map +0 -1
- package/dist/chunk-7PSNXUFK.js.map +0 -1
- package/dist/chunk-7VSZXOXJ.js.map +0 -1
- package/dist/chunk-B6PKHS5I.js.map +0 -1
- package/dist/chunk-C747DYNT.js.map +0 -1
- package/dist/chunk-DOPFBUCX.js.map +0 -1
- package/dist/chunk-DWZ5IWF4.js.map +0 -1
- package/dist/chunk-FJ6F5U3W.js.map +0 -1
- package/dist/chunk-HATCOSQT.js.map +0 -1
- package/dist/chunk-ILWHLGIC.js.map +0 -1
- package/dist/chunk-IOJDZJ72.js.map +0 -1
- package/dist/chunk-KFPSJRHR.js.map +0 -1
- package/dist/chunk-KM2YXO6V.js.map +0 -1
- package/dist/chunk-KTBAB556.js.map +0 -1
- package/dist/chunk-KWC5DQ5Z.js.map +0 -1
- package/dist/chunk-LD5HAN6O.js.map +0 -1
- package/dist/chunk-LFWYYWLV.js.map +0 -1
- package/dist/chunk-LZL2YITN.js.map +0 -1
- package/dist/chunk-PSGTHJQU.js.map +0 -1
- package/dist/chunk-Q4ISQHUQ.js.map +0 -1
- package/dist/chunk-Q7PR2WGT.js.map +0 -1
- package/dist/chunk-QYOUQCC6.js.map +0 -1
- package/dist/chunk-RNVIK5YJ.js.map +0 -1
- package/dist/chunk-RPWD5H6Y.js.map +0 -1
- package/dist/chunk-S25MVWBP.js.map +0 -1
- package/dist/chunk-THI4PI4H.js.map +0 -1
- package/dist/chunk-TOSNS2BY.js.map +0 -1
- package/dist/chunk-UNU2KPYJ.js.map +0 -1
- package/dist/chunk-UZZTWWGG.js.map +0 -1
- package/dist/chunk-W7AGWAMH.js.map +0 -1
- package/dist/chunk-XN7S44U4.js.map +0 -1
- package/dist/chunk-XXLCMSD3.js.map +0 -1
- package/dist/chunk-XZWMJLIT.js.map +0 -1
- package/dist/chunk-ZSOS2KOR.js.map +0 -1
- package/dist/claude-code-FS42PXZO.js.map +0 -1
- package/dist/claude-code-TA53454O.js.map +0 -1
- package/dist/cline-GZFN32BM.js.map +0 -1
- package/dist/codebuddy-IYS3TQZ3.js.map +0 -1
- package/dist/codebuff-6KWBW6CT.js.map +0 -1
- package/dist/codebuff-D3MIKJHC.js.map +0 -1
- package/dist/codex-DKBAAUCO.js.map +0 -1
- package/dist/codex-ZKLP5IXZ.js.map +0 -1
- package/dist/continue-I34FNSTJ.js.map +0 -1
- package/dist/copilot-cli-CLBJACQ5.js.map +0 -1
- package/dist/copilot-cli-NWPM5GE6.js.map +0 -1
- package/dist/crush-A5C5USRL.js.map +0 -1
- package/dist/crush-MDGPZSZU.js.map +0 -1
- package/dist/cursor-D5SWDVSW.js.map +0 -1
- package/dist/cursor-JRVK56QA.js +0 -22
- package/dist/detect-FKJC36P4.js.map +0 -1
- package/dist/devin-TZMRC57O.js.map +0 -1
- package/dist/doctor-PGVYUQYG.js.map +0 -1
- package/dist/droid-PFQ2PZSF.js.map +0 -1
- package/dist/droid-SCFWDJR4.js.map +0 -1
- package/dist/gemini-cli-MLDGOR2L.js.map +0 -1
- package/dist/gemini-cli-Y6RJMU24.js.map +0 -1
- package/dist/goose-5DBHDSJW.js.map +0 -1
- package/dist/goose-K2HKUTBK.js.map +0 -1
- package/dist/grok-cli-LX6Q6RUY.js.map +0 -1
- package/dist/hermes-LJB3SJKB.js.map +0 -1
- package/dist/hermes-MF3NX4ZY.js.map +0 -1
- package/dist/hook-PVGBQUQI.js.map +0 -1
- package/dist/install-HPDIK7F6.js.map +0 -1
- package/dist/jetbrains-copilot-2DSVAJMJ.js.map +0 -1
- package/dist/junie-GUBDRADP.js.map +0 -1
- package/dist/kilo-HRLWMENX.js.map +0 -1
- package/dist/kilo-SMHPOHJ5.js.map +0 -1
- package/dist/kilo-cli-IQMFMYZF.js.map +0 -1
- package/dist/kilo-cli-T2SRRRJS.js.map +0 -1
- package/dist/kimi-EPD46UJK.js.map +0 -1
- package/dist/kimi-MSIDEMCI.js.map +0 -1
- package/dist/kiro-A7DL52FX.js.map +0 -1
- package/dist/kiro-NYRRBIKW.js.map +0 -1
- package/dist/leaderboard-KCT7XPCI.js.map +0 -1
- package/dist/mimo-code-NDGLBXNC.js.map +0 -1
- package/dist/mistral-vibe-LLWASF5X.js.map +0 -1
- package/dist/mux-7PIJ7HUQ.js.map +0 -1
- package/dist/mux-ON4QK3OC.js.map +0 -1
- package/dist/nemoclaw-45R5MFBF.js.map +0 -1
- package/dist/omp-ROCTFV3A.js.map +0 -1
- package/dist/open-interpreter-V6CN542J.js.map +0 -1
- package/dist/openclaw-AOKFJGRQ.js +0 -17
- package/dist/openclaw-KAFTNLR2.js.map +0 -1
- package/dist/opencode-YYWQ45LF.js.map +0 -1
- package/dist/opencode-Z65JYILL.js.map +0 -1
- package/dist/openhands-OFFMWCQW.js.map +0 -1
- package/dist/package-TALOSRQ4.js.map +0 -1
- package/dist/pi-4W74ETTI.js.map +0 -1
- package/dist/pi-DLKCPOJE.js.map +0 -1
- package/dist/qwen-code-26CSFDX6.js.map +0 -1
- package/dist/qwen-code-JOBFNEVT.js.map +0 -1
- package/dist/roo-code-HSAE2CJU.js.map +0 -1
- package/dist/roo-code-RHIGJZNY.js.map +0 -1
- package/dist/serve-4TEHK726.js.map +0 -1
- package/dist/status-DVD4EHMX.js.map +0 -1
- package/dist/statusline-ZVNH7XBK.js.map +0 -1
- package/dist/synthetic-LUT6V6SD.js.map +0 -1
- package/dist/telemetry-NWUJPIK3.js.map +0 -1
- package/dist/trae-SIQI3C66.js.map +0 -1
- package/dist/trae-TLAFSQRQ.js.map +0 -1
- package/dist/uninstall-DZVFV7KE.js.map +0 -1
- package/dist/upgrade-OUE4ED52.js.map +0 -1
- package/dist/usage-NT3ZXALZ.js.map +0 -1
- package/dist/usage-event-IELZE6WO.js.map +0 -1
- package/dist/vscode-copilot-VZ5XYSTK.js.map +0 -1
- package/dist/warp-5YBSP7FP.js.map +0 -1
- package/dist/warp-P2HWXIKT.js.map +0 -1
- package/dist/windsurf-3JC73GZK.js.map +0 -1
- package/dist/zed-6CMUKXLI.js.map +0 -1
- package/dist/zed-XXCNYOIN.js.map +0 -1
- /package/dist/{antigravity-PZXYAO3X.js.map → antigravity-VXHL6ZPM.js.map} +0 -0
- /package/dist/{audit-2H7E3Z4N.js.map → audit-BO7JQYIH.js.map} +0 -0
- /package/dist/{cursor-JRVK56QA.js.map → cursor-RSLHA2CY.js.map} +0 -0
- /package/dist/{openclaw-AOKFJGRQ.js.map → openclaw-3DHVHX5P.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/codebuddy/index.ts"],"sourcesContent":["/**\r\n * adapters/codebuddy — Tencent CodeBuddy Code platform adapter for agent-connector.\r\n *\r\n * CodeBuddy Code (`@tencent-ai/codebuddy-code`, bin `codebuddy`) is Tencent's\r\n * terminal AI assistant and a CLOSE Claude Code fork: same json-stdio hook\r\n * paradigm, same hook event names, same snake_case stdin fields, and the same\r\n * `hookSpecificOutput` reply envelope — so it reuses claude-code's wire module\r\n * (parseEvent/formatReply contract) verbatim. The fork rebrands every storage\r\n * path from `.claude*` to `.codebuddy*`:\r\n * - MCP servers: user scope → `~/.codebuddy.json` (\"mcpServers\"); project\r\n * scope → `<projectDir>/.mcp.json` (\"mcpServers\").\r\n * - Hooks: `<configDir>/settings.json` under \"hooks\", keyed by event name,\r\n * each value an array of { matcher, hooks:[{ type:\"command\", command }] }.\r\n * - Config dir: `~/.codebuddy` (override `$CODEBUDDY_CONFIG_DIR`); project\r\n * `<projectDir>/.codebuddy`. Content surfaces live under\r\n * `<configDir>/{commands,skills,agents}`.\r\n * - Memory: `CODEBUDDY.md` (the fork renames CLAUDE.md; it does NOT read\r\n * AGENTS.md by default — verified against the v2.109.0 bundle, which lists\r\n * `.codebuddy/settings*.json`, `CODEBUDDY.md`, `CODEBUDDY.local.md`,\r\n * `.codebuddy.json`, `.codebuddy/rules/`, `.codebuddy/hooks`).\r\n * - Reply: a `hookSpecificOutput` object (permissionDecision allow|deny|ask +\r\n * reason, additionalContext, updatedInput) on stdout with exit 0; Stop-class\r\n * blocks use the top-level {\"decision\":\"block\",\"reason\"} — identical to\r\n * Claude Code.\r\n *\r\n * Every fact above is BYTE-CONFIRMED against the official npm bundle\r\n * `@tencent-ai/codebuddy-code@2.109.0` (dist/codebuddy.js): bin `codebuddy`,\r\n * `.codebuddy.json`/`.mcp.json` + root key `mcpServers`, `.codebuddy/settings.json`\r\n * hooks, the 13 Claude hook event names, the snake_case stdin fields, and the\r\n * `hookSpecificOutput`/`permissionDecision` reply shape. CodeBuddy needs Tencent\r\n * auth, so this is NOT live-verifiable locally — placement + byte-oracle ceiling.\r\n *\r\n * SCOPE: the byte-confirmed core surfaces (MCP stdio+http, the 13 normalized\r\n * hooks + nativeHooks passthrough, commands/skills/subagents, CODEBUDDY.md\r\n * memory). The claude-code-v1-only surfaces (configPatch sensitive-key denylist,\r\n * statusLine wiring, the agents-import bridge) are NOT ported — their CodeBuddy\r\n * behavior is not byte-confirmed, and the instruction is to enable only\r\n * byte-confirmed flags.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type { Adapter, HookReply, InstallContext, MemoryTarget, NormalizedEvent } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n CommandDef,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n NotificationEvent,\r\n PermissionRequestEvent,\r\n PlatformCapabilities,\r\n PlatformId,\r\n PostCompactEvent,\r\n PostToolUseEvent,\r\n PostToolUseFailureEvent,\r\n PreCompactEvent,\r\n PreToolUseEvent,\r\n SessionEndEvent,\r\n SessionStartEvent,\r\n ServerDef,\r\n SkillDef,\r\n StopEvent,\r\n SubagentDef,\r\n SubagentStartEvent,\r\n SubagentStopEvent,\r\n Transport,\r\n UserPromptSubmitEvent,\r\n} from \"../../core/types.js\";\r\nimport { resolveEnvRefsDeep, rewriteEnvRefs } from \"../../core/interpolate.js\";\r\nimport { buildWrappedStdio, isHomeBinHookCommand } from \"../../core/spawn.js\";\r\nimport {\r\n type ClaudeHookEvent,\r\n type ClaudeWireInput,\r\n extractSessionId,\r\n normalizeSessionSource,\r\n toolResponseToString,\r\n} from \"../claude-code/wire.js\";\r\nimport { renderCommandMd, renderSkillMd, renderSubagentMd } from \"../claude-code/render.js\";\r\n\r\nconst HOST: PlatformId = \"codebuddy\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/** The config-dir env override CodeBuddy honors (verified in the bundle). */\r\nconst CONFIG_DIR_ENV = \"CODEBUDDY_CONFIG_DIR\";\r\n\r\n/** A single hook registration entry as CodeBuddy stores it in settings.json. */\r\ninterface CodeBuddyHookEntry {\r\n matcher: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/** Native MCP server entry shapes CodeBuddy accepts under `mcpServers`. */\r\ninterface CodeBuddyStdioServer {\r\n type: \"stdio\";\r\n command: string;\r\n args: string[];\r\n env?: Record<string, string>;\r\n cwd?: string;\r\n}\r\ninterface CodeBuddyHttpServer {\r\n type: \"http\";\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport class CodeBuddyAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"CodeBuddy\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // CodeBuddy ships the full Claude hook set (bundle-confirmed event names).\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n sessionStart: true,\r\n sessionEnd: true,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: true,\r\n permissionRequest: true,\r\n postToolUseFailure: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // Claude-fork reply envelope: PreToolUse can rewrite input (updatedInput);\r\n // a PostToolUse hook cannot rewrite already-emitted output.\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n // settings.json hook keys are free-form event names, so any host event\r\n // declared under platforms[\"codebuddy\"].nativeHooks installs verbatim.\r\n supportsNativeHooks: true,\r\n transports: [\"stdio\", \"http\"],\r\n // CodeBuddy preserves Claude's native ${VAR} interpolation in mcpServers\r\n // env/url, so secret-bearing fields survive into the config (never baked).\r\n nativeServerEnvInterpolation: true,\r\n // Content surfaces under <configDir>/{commands,skills,agents}.\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n // Memory surface — EXCEPTION host: CodeBuddy reads CODEBUDDY.md (the fork's\r\n // CLAUDE.md rename), NOT AGENTS.md, so memoryTargets below overrides the base\r\n // AGENTS.md-first default.\r\n supportsMemory: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = this.userConfigDir();\r\n const userSettings = join(userDir, \"settings.json\");\r\n const userServers = join(homedir(), \".codebuddy.json\");\r\n const projectServers = join(projectDir, \".mcp.json\");\r\n const userInstalled =\r\n existsSync(userDir) || existsSync(userSettings) || existsSync(userServers);\r\n const projInstalled = existsSync(projectServers);\r\n const installed = userInstalled || projInstalled;\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projectServers : userSettings;\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? scope === \"project\"\r\n ? `found project CodeBuddy config at ${projectServers}`\r\n : `found CodeBuddy config under ${userDir}`\r\n : `no CodeBuddy config at ${userDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n /** User config dir: `$CODEBUDDY_CONFIG_DIR` || `~/.codebuddy`. */\r\n private userConfigDir(): string {\r\n const override = process.env[CONFIG_DIR_ENV];\r\n return override && override.trim() !== \"\" ? override : join(homedir(), \".codebuddy\");\r\n }\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".codebuddy\")\r\n : this.userConfigDir();\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".mcp.json\")\r\n : join(homedir(), \".codebuddy.json\");\r\n }\r\n\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"settings.json\");\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for codebuddy\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /** Render a normalized ServerDef into CodeBuddy's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): CodeBuddyStdioServer | CodeBuddyHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n const entry: CodeBuddyStdioServer = { type: \"stdio\", command, args };\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n if (server.cwd) entry.cwd = resolveEnvRefsDeep(server.cwd);\r\n return entry;\r\n }\r\n\r\n // http (and any other remote transport we surface) — register a URL.\r\n const entry: CodeBuddyHttpServer = {\r\n type: \"http\",\r\n url: rewriteEnvRefs(server.url ?? \"\", codebuddyEnvToken),\r\n };\r\n if (server.headers) {\r\n entry.headers = this.renderEnv(server.headers) ?? {};\r\n }\r\n return entry;\r\n }\r\n\r\n /**\r\n * Render env/header values using CodeBuddy's native `${VAR}` interpolation\r\n * (inherited from Claude Code), so `${env:VAR}` refs survive into the config\r\n * rather than baking a secret. Literals pass through unchanged.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n const out: Record<string, string> = {};\r\n for (const [k, v] of Object.entries(env)) {\r\n out[k] = rewriteEnvRefs(v, codebuddyEnvToken);\r\n }\r\n return out;\r\n }\r\n\r\n // ── Hook install / uninstall ─────────────────────────────────────────────\r\n\r\n installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST];\r\n\r\n // `hooks: false` disables only the NORMALIZED hooks; nativeHooks is a\r\n // sibling declaration that installs regardless.\r\n const normalizedEvents = override?.hooks === false ? [] : connector.hookEvents;\r\n const nativeHooks = override?.nativeHooks ?? {};\r\n const nativeEvents = Object.keys(nativeHooks);\r\n\r\n if (normalizedEvents.length === 0 && nativeEvents.length === 0) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail:\r\n override?.hooks === false\r\n ? \"hooks disabled for codebuddy\"\r\n : \"connector declares no hooks\",\r\n },\r\n ];\r\n }\r\n\r\n const settingsPath = this.getHookConfigPath(ctx);\r\n\r\n const pending: Array<{ event: string; matcher: string }> = [\r\n ...normalizedEvents.map((event) => ({\r\n event: event as string,\r\n matcher: connector.hooks[event]?.matcher ?? \"\",\r\n })),\r\n ...nativeEvents.map((event) => ({\r\n event,\r\n matcher: nativeHooks[event]?.matcher ?? \"\",\r\n })),\r\n ];\r\n\r\n return this.upsertHookEntries(ctx, settingsPath, pending, this.hookDescriptor());\r\n }\r\n\r\n uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor());\r\n }\r\n\r\n /**\r\n * CodeBuddy's hook-merge descriptor — the Claude NESTED shape\r\n * `{ matcher, hooks: [...] }`: install find = THIS command present in the\r\n * entry's inner `hooks`; uninstall is inner-strip only (drop entries left\r\n * empty); never remove a whole entry by ownership.\r\n */\r\n private hookDescriptor(): HookMergeDescriptor<CodeBuddyHookEntry> {\r\n return {\r\n renderEntry: (_event, matcher, command) => ({\r\n matcher,\r\n hooks: [{ type: \"command\", command }],\r\n }),\r\n entryOwnsCommand: (entry, command) =>\r\n (entry.hooks ?? []).some((h) => h.command === command),\r\n ownsEntryForRemove: () => () => false,\r\n stripInner: (ctx) => (entry) => {\r\n const innerBefore = entry.hooks?.length ?? 0;\r\n const inner = (entry.hooks ?? []).filter((h) => !this.isOurCommand(h.command, ctx));\r\n return {\r\n next: inner.length > 0 ? { matcher: entry.matcher ?? \"\", hooks: inner } : null,\r\n removed: innerBefore - inner.length,\r\n };\r\n },\r\n skipDetail: (event) => `hooks.${event} already registered`,\r\n removeDetail: (event, removed) => `hooks.${event} (${removed})`,\r\n absentDetail: \"no hooks section present\",\r\n noMatchDetail: \"no matching hook entries\",\r\n };\r\n }\r\n\r\n /** True when a hook command references our home binary AND this connector id. */\r\n private isOurCommand(command: string | undefined, ctx: InstallContext): boolean {\r\n return isHomeBinHookCommand(command, ctx.homeBinPath, ctx.connector.id);\r\n }\r\n\r\n // ── Content surfaces: commands / skills / subagents ──────────────────────\r\n // Pure native-file writers under <configDir>/{commands,skills,agents}, the\r\n // fork's confirmed surface dirs. Idempotent (byte-identical → skip) and\r\n // reversible. Honors platforms[\"codebuddy\"] per-surface `false` to skip.\r\n\r\n private commandsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"commands\");\r\n }\r\n private skillsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"skills\");\r\n }\r\n private agentsDir(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"agents\");\r\n }\r\n\r\n private commandPath(ctx: InstallContext, name: string): string {\r\n return join(this.commandsDir(ctx), `${name}.md`);\r\n }\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.skillsDir(ctx), name);\r\n }\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.agentsDir(ctx), `${name}.md`);\r\n }\r\n\r\n override installCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for codebuddy\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(this.commandPath(ctx, cmd.name), this.renderCommand(cmd), ctx.dryRun),\r\n );\r\n }\r\n\r\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.removeContentFile(this.commandPath(ctx, cmd.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n private renderCommand(cmd: CommandDef): string {\r\n return renderCommandMd(cmd);\r\n }\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codebuddy\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(\r\n this.writeContentFile(join(dir, \"SKILL.md\"), this.renderSkill(skill), ctx.dryRun),\r\n );\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue;\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n private renderSkill(skill: SkillDef): string {\r\n return renderSkillMd(skill);\r\n }\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for codebuddy\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(this.subagentPath(ctx, agent.name), this.renderSubagent(agent), ctx.dryRun),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n private renderSubagent(agent: SubagentDef): string {\r\n return renderSubagentMd(agent);\r\n }\r\n\r\n // ── Memory surface: CODEBUDDY.md managed block ────────────────────────────\r\n // EXCEPTION host. CodeBuddy reads CODEBUDDY.md (the fork's CLAUDE.md rename),\r\n // NOT AGENTS.md (bundle-confirmed path list), so the base AGENTS.md-first\r\n // default is overridden. HTML-comment markers are correct here for the same\r\n // reason as Claude Code (comment-stripped before context injection). Unlike\r\n // claude-code this adapter does NOT ship the opt-in agents-import bridge —\r\n // only the canonical block in the host's own memory file.\r\n\r\n private memoryFilePath(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \"CODEBUDDY.md\")\r\n : join(this.userConfigDir(), \"CODEBUDDY.md\");\r\n }\r\n\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n // An explicit path override keeps the base resolution (escape hatch wins).\r\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\r\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\r\n return [\r\n {\r\n path: this.memoryFilePath(ctx),\r\n reason:\r\n \"CODEBUDDY.md (CodeBuddy reads CODEBUDDY.md, not AGENTS.md; \" +\r\n \"HTML-comment markers are stripped from the model's context)\",\r\n },\r\n ];\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const settingsPath = this.getHookConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const homeBin = ctx.homeBinPath;\r\n const declaredHookCount =\r\n ctx.connector.hookEvents.length +\r\n Object.keys(ctx.connector.platforms[HOST]?.nativeHooks ?? {}).length;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: settings.json present`,\r\n check: () => {\r\n if (declaredHookCount === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n return existsSync(settingsPath)\r\n ? { status: \"OK\", detail: settingsPath }\r\n : { status: \"FAIL\", detail: `not found: ${settingsPath}` };\r\n },\r\n },\r\n {\r\n name: `${this.name}: hook command registered`,\r\n check: () => {\r\n if (declaredHookCount === 0) {\r\n return { status: \"OK\", detail: \"no hooks declared\" };\r\n }\r\n const settings = this.readJson<{ hooks?: Record<string, CodeBuddyHookEntry[]> }>(\r\n settingsPath,\r\n );\r\n if (!settings) return { status: \"FAIL\", detail: `cannot read ${settingsPath}` };\r\n const hooks = settings.hooks ?? {};\r\n const registered = Object.values(hooks).some((entries) =>\r\n (entries ?? []).some((e) =>\r\n (e.hooks ?? []).some((h) => isHomeBinHookCommand(h.command, homeBin, connectorId)),\r\n ),\r\n );\r\n return registered\r\n ? { status: \"OK\", detail: \"hook command present\" }\r\n : { status: \"FAIL\", detail: `no hook for ${connectorId} in ${settingsPath}` };\r\n },\r\n },\r\n ];\r\n\r\n for (const cmd of ctx.connector.commands) {\r\n const p = this.commandPath(ctx, cmd.name);\r\n checks.push({\r\n name: `${this.name}: command ${cmd.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Runtime: parse CodeBuddy stdin JSON → normalized event ────────────────\r\n // CodeBuddy's wire is the Claude shape (snake_case fields, PascalCase events),\r\n // so the claude-code/wire helpers (extractSessionId, toolResponseToString,\r\n // normalizeSessionSource) apply 1:1.\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as ClaudeWireInput;\r\n const connectorId = typeof input.connector === \"string\" ? input.connector : \"\";\r\n const sessionId = extractSessionId(input);\r\n const projectDir = typeof input.cwd === \"string\" ? input.cwd : undefined;\r\n\r\n const base = {\r\n hostPlatform: HOST,\r\n connectorId,\r\n sessionId,\r\n raw,\r\n ...(projectDir !== undefined ? { projectDir } : {}),\r\n } as const;\r\n\r\n switch (event) {\r\n case \"PreToolUse\": {\r\n const ev: PreToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUse\": {\r\n const ev: PostToolUseEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(toolResponseToString(input.tool_response) !== undefined\r\n ? { toolOutput: toolResponseToString(input.tool_response) }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SessionStart\": {\r\n const ev: SessionStartEvent = { ...base, source: normalizeSessionSource(input.source) };\r\n return ev;\r\n }\r\n case \"SessionEnd\": {\r\n const ev: SessionEndEvent = {\r\n ...base,\r\n ...(typeof input.reason === \"string\" ? { reason: input.reason } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"UserPromptSubmit\": {\r\n const ev: UserPromptSubmitEvent = {\r\n ...base,\r\n prompt: typeof input.prompt === \"string\" ? input.prompt : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PreCompact\": {\r\n const ev: PreCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Stop\": {\r\n const ev: StopEvent = {\r\n ...base,\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"Notification\": {\r\n const ev: NotificationEvent = {\r\n ...base,\r\n message: typeof input.message === \"string\" ? input.message : \"\",\r\n };\r\n return ev;\r\n }\r\n case \"PermissionRequest\": {\r\n const ev: PermissionRequestEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n ...(Array.isArray(input.permission_suggestions)\r\n ? { permissionSuggestions: input.permission_suggestions }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostToolUseFailure\": {\r\n const ev: PostToolUseFailureEvent = {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error: typeof input.error === \"string\" ? input.error : \"\",\r\n ...(typeof input.tool_use_id === \"string\" ? { toolUseId: input.tool_use_id } : {}),\r\n ...(typeof input.is_interrupt === \"boolean\" ? { isInterrupt: input.is_interrupt } : {}),\r\n ...(typeof input.duration_ms === \"number\" ? { durationMs: input.duration_ms } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStart\": {\r\n const ev: SubagentStartEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\r\n };\r\n return ev;\r\n }\r\n case \"SubagentStop\": {\r\n const ev: SubagentStopEvent = {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\r\n ...(typeof input.agent_transcript_path === \"string\"\r\n ? { agentTranscriptPath: input.agent_transcript_path }\r\n : {}),\r\n ...(typeof input.last_assistant_message === \"string\"\r\n ? { lastAssistantMessage: input.last_assistant_message }\r\n : {}),\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n case \"PostCompact\": {\r\n // Not wired as a normalized lifecycle hook (capabilities.postCompact is\r\n // unset), but the exhaustive guard requires an arm; mirror PreCompact.\r\n const ev: PostCompactEvent = {\r\n ...base,\r\n ...(input.trigger === \"auto\" || input.trigger === \"manual\"\r\n ? { trigger: input.trigger }\r\n : {}),\r\n };\r\n return ev;\r\n }\r\n default: {\r\n const _never: never = event;\r\n throw new Error(`unsupported codebuddy hook event: ${String(_never)}`);\r\n }\r\n }\r\n }\r\n\r\n // ── Runtime: normalized response → CodeBuddy native hook reply ────────────\r\n // Identical envelope to Claude Code (bundle-confirmed: hookSpecificOutput,\r\n // permissionDecision/permissionDecisionReason, additionalContext,\r\n // updatedInput; Stop-class blocks use the top-level decision:\"block\").\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n const hookEventName = event as ClaudeHookEvent;\r\n const decision = response.decision ?? \"allow\";\r\n\r\n if (event === \"PermissionRequest\") {\r\n if (response.decision === \"deny\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: { behavior: \"deny\", message: response.reason ?? \"Blocked by hook\" },\r\n },\r\n });\r\n }\r\n if (\r\n response.decision === \"allow\" ||\r\n (response.decision === \"modify\" && response.updatedInput)\r\n ) {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n decision: {\r\n behavior: \"allow\",\r\n ...(response.updatedInput ? { updatedInput: response.updatedInput } : {}),\r\n },\r\n },\r\n });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // PostToolUseFailure / SubagentStart are observe/context-only.\r\n if (event === \"PostToolUseFailure\" || event === \"SubagentStart\") {\r\n const context =\r\n decision === \"context\"\r\n ? response.additionalContext\r\n : decision === \"deny\"\r\n ? response.reason ?? response.additionalContext\r\n : undefined;\r\n if (context) {\r\n return this.stdout({ hookSpecificOutput: { hookEventName, additionalContext: context } });\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // deny → block. Stop-class events honor only the TOP-LEVEL decision:\"block\".\r\n if (decision === \"deny\") {\r\n if (\r\n event === \"Stop\" ||\r\n event === \"SubagentStop\" ||\r\n event === \"UserPromptSubmit\" ||\r\n event === \"PostToolUse\"\r\n ) {\r\n return this.stdout({ decision: \"block\", reason: response.reason ?? \"Blocked by hook\" });\r\n }\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"deny\",\r\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\r\n },\r\n });\r\n }\r\n\r\n if (decision === \"ask\") {\r\n return this.stdout({\r\n hookSpecificOutput: {\r\n hookEventName,\r\n permissionDecision: \"ask\",\r\n permissionDecisionReason: response.reason ?? \"Confirmation required by hook\",\r\n },\r\n });\r\n }\r\n\r\n if (decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, updatedInput: response.updatedInput },\r\n });\r\n }\r\n // Output rewrite is unsupported; fall through to allow.\r\n }\r\n\r\n if (decision === \"context\" && response.additionalContext) {\r\n return this.stdout({\r\n hookSpecificOutput: { hookEventName, additionalContext: response.additionalContext },\r\n });\r\n }\r\n\r\n return { exitCode: 0 };\r\n }\r\n\r\n private stdout(payload: unknown): HookReply {\r\n return { exitCode: 0, stdout: JSON.stringify(payload) };\r\n }\r\n}\r\n\r\n/** CodeBuddy native interpolation token: `${env:VAR}` → `${VAR}`. */\r\nfunction codebuddyEnvToken(name: string): string {\r\n return `\\${${name}}`;\r\n}\r\n\r\nexport const adapter = new CodeBuddyAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/usage/readers/codebuff.ts"],"sourcesContent":["/**\r\n * usage/readers/codebuff — Codebuff (formerly Manicode) native session reader.\r\n *\r\n * Faithful port of tokscale sessions/codebuff.rs. Codebuff persists chat history\r\n * under ~/.config/manicode/projects/<project>/chats/<chatId>/chat-messages.json,\r\n * with parallel \"dev\" and \"staging\" channels under manicode-dev / manicode-staging.\r\n * Each file is a JSON array of ChatMessage objects; only assistant messages\r\n * (variant/role ∈ {ai, agent, assistant}) carry token usage, which can live in\r\n * THREE places (tried in order, each merged as a fallback for missing fields):\r\n *\r\n * 1. metadata.usage\r\n * 2. metadata.codebuff.usage\r\n * 3. the stashed RunState message history —\r\n * metadata.runState.sessionState.mainAgentState.messageHistory[].providerOptions\r\n * (.usage / .codebuff.usage / .codebuff.model), where OpenRouter-routed calls\r\n * land their final token counts. We scan that history newest-first and merge\r\n * each assistant entry as a fallback.\r\n *\r\n * Token fields accept BOTH camelCase and snake_case (matching the @ccusage/codebuff\r\n * valibot schema): input ← inputTokens|input_tokens|promptTokens|prompt_tokens;\r\n * output ← outputTokens|output_tokens|completionTokens|completion_tokens;\r\n * cacheRead ← cacheReadInputTokens|cache_read_input_tokens|cachedTokensCreated|\r\n * cached_tokens_created, or promptTokensDetails.cachedTokens|prompt_tokens_details.cached_tokens;\r\n * cacheWrite ← cacheCreationInputTokens|cache_creation_input_tokens|\r\n * cacheCreationTokens|cache_creation_tokens. reasoning is always 0. A `credits`\r\n * field (on the usage object or the message) becomes cost. A message with no\r\n * token signal at all (and no credits) is skipped.\r\n *\r\n * Attribution comes from the path: sessionId = \"<channel>/<project>/<chatId>\"\r\n * (e.g. \"manicode/sandbox/2025-12-14T10-00-00.000Z\"); projectKey/projectLabel\r\n * derive from the <project> ancestor. Timestamp resolution: message.timestamp |\r\n * message.createdAt | metadata.timestamp, else the chatId parsed back to ms\r\n * (the filesystem-safe ISO form 2025-12-14T10-00-00.000Z has its two TIME\r\n * separators restored to ':' WITHOUT touching the date '-'), else file mtime.\r\n *\r\n * Dedup: the upstream ChatMessage.id when present (stable across re-imports), else\r\n * a deterministic composite codebuff:<session>:<ts>:<model>:<ordinal>:<i>:<o>:<cr>:<cw>.\r\n * Provider is inferred from the model (default \"codebuff-unknown\" → \"unknown\").\r\n * Confidence is \"host-reported\" (real host token counts).\r\n *\r\n * Fail-open: no root → []; unreadable/malformed file → skipped (never throws).\r\n * Read-only.\r\n */\r\n\r\nimport { basename, dirname, isAbsolute, join, resolve } from \"node:path\";\r\nimport { homedir } from \"node:os\";\r\n\r\nimport type { TokenBreakdown, UsageReader, UsageRecord } from \"../types.js\";\r\nimport { emptyTokens } from \"../aggregate.js\";\r\nimport { fileMtimeMs, readJsonFile } from \"../jsonl.js\";\r\nimport { inferProvider, workspaceFromPath } from \"../normalize.js\";\r\nimport { expandHome, walkFiles } from \"../paths.js\";\r\n\r\nconst PLATFORM_ID = \"codebuff\" as const;\r\nconst DEFAULT_MODEL = \"codebuff-unknown\";\r\nconst DEFAULT_PROVIDER = \"unknown\";\r\n\r\n/** The three Codebuff release channels, each its own ~/.config/<channel> root. */\r\nconst CHANNELS = [\"manicode\", \"manicode-dev\", \"manicode-staging\"] as const;\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Root resolution\r\n//\r\n// codebuff is not in paths.ts hostRoots(), so we resolve its channel roots\r\n// here, mirroring the paths.ts convention exactly: an explicit non-empty\r\n// AGENT_CONNECTOR_CODEBUFF_DIR override wins (treated as the projects dir),\r\n// otherwise the OS config dir per channel. Read-only; never created.\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** $XDG_CONFIG_HOME (when set & non-empty) else ~/.config — matches paths.ts. */\r\nfunction xdgConfigHome(): string {\r\n const xdg = process.env.XDG_CONFIG_HOME;\r\n if (xdg !== undefined && xdg.trim() !== \"\") return resolve(expandHome(xdg.trim()));\r\n return join(homedir(), \".config\");\r\n}\r\n\r\n/**\r\n * Env override, treating empty/blank as unset (paths.ts envOverride contract):\r\n * relative paths resolve against CWD; \"~\" expands. Returns undefined when unset.\r\n */\r\nfunction envOverride(name: string): string | undefined {\r\n const raw = process.env[name];\r\n if (raw == null || raw.trim() === \"\") return undefined;\r\n const expanded = expandHome(raw.trim());\r\n return isAbsolute(expanded) ? expanded : resolve(expanded);\r\n}\r\n\r\n/**\r\n * Candidate `projects` roots, most-preferred first. The override (when present)\r\n * is the projects dir for the default channel; otherwise one root per channel\r\n * under the config home. Readers walk each existing root.\r\n */\r\nfunction codebuffProjectRoots(): string[] {\r\n const out: string[] = [];\r\n const override = envOverride(\"AGENT_CONNECTOR_CODEBUFF_DIR\");\r\n if (override !== undefined) out.push(override);\r\n const config = xdgConfigHome();\r\n for (const channel of CHANNELS) {\r\n out.push(join(config, channel, \"projects\"));\r\n }\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Raw value helpers (everything off a parsed JSON value is unknown)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nfunction asRecord(v: unknown): Record<string, unknown> | undefined {\r\n return typeof v === \"object\" && v !== null && !Array.isArray(v)\r\n ? (v as Record<string, unknown>)\r\n : undefined;\r\n}\r\n\r\nfunction asString(v: unknown): string | undefined {\r\n return typeof v === \"string\" ? v : undefined;\r\n}\r\n\r\n/** Coerce to a finite number (i64/u64/f64 in Rust), or null. */\r\nfunction asNumber(v: unknown): number | null {\r\n if (typeof v === \"number\") return Number.isFinite(v) ? v : null;\r\n return null;\r\n}\r\n\r\n/**\r\n * pick_number: first key whose value coerces to a positive integer wins (>0,\r\n * truncated). Mirrors the Rust as_i64/as_u64/as_f64 chain with its `n > 0` gate.\r\n */\r\nfunction pickNumber(obj: Record<string, unknown>, keys: readonly string[]): number | null {\r\n for (const key of keys) {\r\n const num = asNumber(obj[key]);\r\n if (num !== null) {\r\n const n = Math.trunc(num);\r\n if (n > 0) return n;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Timestamp parsing (port of utils.rs parse_timestamp_str / parse_timestamp_value)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** RFC3339 / numeric-string → epoch ms; null when unusable (port of parse_timestamp_str). */\r\nfunction parseTimestampStr(value: string): number | null {\r\n const ms = Date.parse(value);\r\n if (!Number.isNaN(ms)) return ms;\r\n // Pure-integer string fallback (Rust value.parse::<i64>()).\r\n if (/^-?\\d+$/.test(value)) {\r\n const numeric = Number(value);\r\n if (!Number.isFinite(numeric) || numeric <= 0) return null;\r\n return numeric >= 1_000_000_000_000 ? numeric : numeric * 1000;\r\n }\r\n return null;\r\n}\r\n\r\n/** JSON value (string or positive number) → epoch ms (port of parse_timestamp_value). */\r\nfunction parseTimestampValue(value: unknown): number | null {\r\n if (typeof value === \"string\") return parseTimestampStr(value);\r\n const numeric = asNumber(value);\r\n if (numeric === null) return null;\r\n const n = Math.trunc(numeric);\r\n if (n <= 0) return null;\r\n return n >= 1_000_000_000_000 ? n : n * 1000;\r\n}\r\n\r\n/**\r\n * Convert a filesystem-safe chatId back to epoch ms. Codebuff's chatId is the\r\n * chat's ISO-8601 timestamp with the two TIME separators (HH-MM-SS) flipped to\r\n * '-' for filesystem safety (e.g. 2025-12-14T10-00-00.000Z). Restore ONLY the\r\n * first two '-' AFTER the 'T' back to ':'; a naive global replace would corrupt\r\n * the date to 2025:12:14T... and break parsing. Trailing '-' (ms/timezone) stay.\r\n */\r\nfunction parseChatIdToMillis(chatId: string): number | null {\r\n const tIndex = chatId.indexOf(\"T\");\r\n if (tIndex < 0) return null;\r\n const date = chatId.slice(0, tIndex);\r\n const timeWithSeparator = chatId.slice(tIndex); // starts with 'T'\r\n const rebuilt = date + replaceFirst(timeWithSeparator, \"-\", \":\", 2);\r\n return parseTimestampStr(rebuilt);\r\n}\r\n\r\n/** Replace the first `count` occurrences of `from` with `to` (Rust replacen). */\r\nfunction replaceFirst(s: string, from: string, to: string, count: number): string {\r\n let result = s;\r\n let done = 0;\r\n let idx = result.indexOf(from);\r\n while (idx >= 0 && done < count) {\r\n result = result.slice(0, idx) + to + result.slice(idx + from.length);\r\n done++;\r\n idx = result.indexOf(from, idx + to.length);\r\n }\r\n return result;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Path → (channel, project, chatId) and session id\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * Walk up a chat-messages.json path → (channel, project, chatId). Layout:\r\n * <channel>/projects/<project>/chats/<chatId>/chat-messages.json. Missing\r\n * ancestors fall back to deterministic defaults (lossy, never throws).\r\n */\r\nfunction deriveContextFromPath(path: string): { channel: string; project: string; chatId: string } {\r\n const chatDir = dirname(path); // .../chats/<chatId>\r\n const chatId = basename(chatDir) || \"unknown\";\r\n\r\n const chatsDir = dirname(chatDir); // .../<project>/chats\r\n const projectDir = dirname(chatsDir); // .../<project>\r\n const project = basename(projectDir) || \"unknown\";\r\n\r\n const projectsDir = dirname(projectDir); // .../projects\r\n const channelDir = dirname(projectsDir); // .../<channel>\r\n const channel = basename(channelDir) || \"manicode\";\r\n\r\n return { channel, project, chatId };\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Assistant role + timestamp\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nfunction isAssistantRole(msg: Record<string, unknown>): boolean {\r\n const variant = asString(msg.variant) ?? asString(msg.role) ?? \"\";\r\n return variant === \"ai\" || variant === \"agent\" || variant === \"assistant\";\r\n}\r\n\r\n/** message.timestamp | message.createdAt | metadata.timestamp → ms, else null. */\r\nfunction messageTimestamp(msg: Record<string, unknown>): number | null {\r\n for (const key of [\"timestamp\", \"createdAt\"] as const) {\r\n if (key in msg) {\r\n const ts = parseTimestampValue(msg[key]);\r\n if (ts !== null) return ts;\r\n }\r\n }\r\n const meta = asRecord(msg.metadata);\r\n if (meta !== undefined && \"timestamp\" in meta) {\r\n return parseTimestampValue(meta.timestamp);\r\n }\r\n return null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Usage extraction (port of AssistantUsage + extract_assistant_usage)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface AssistantUsage {\r\n model?: string;\r\n credits: number;\r\n input: number;\r\n output: number;\r\n cacheRead: number;\r\n cacheWrite: number;\r\n}\r\n\r\nfunction newUsage(): AssistantUsage {\r\n return { credits: 0, input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };\r\n}\r\n\r\nfunction hasSignal(u: AssistantUsage): boolean {\r\n return u.input > 0 || u.output > 0 || u.cacheRead > 0 || u.cacheWrite > 0 || u.credits > 0;\r\n}\r\n\r\n/** Fill any unset (<=0 / undefined) field of `self` from `other` (merge_fallback). */\r\nfunction mergeFallback(self: AssistantUsage, other: AssistantUsage): void {\r\n if (self.input <= 0) self.input = other.input;\r\n if (self.output <= 0) self.output = other.output;\r\n if (self.cacheRead <= 0) self.cacheRead = other.cacheRead;\r\n if (self.cacheWrite <= 0) self.cacheWrite = other.cacheWrite;\r\n if (self.model === undefined) self.model = other.model;\r\n if (self.credits <= 0) self.credits = other.credits;\r\n}\r\n\r\n/** Parse a usage object, accepting camelCase and snake_case (parse_usage_object). */\r\nfunction parseUsageObject(value: unknown): AssistantUsage {\r\n const usage = newUsage();\r\n const obj = asRecord(value);\r\n if (obj === undefined) return usage;\r\n\r\n const input = pickNumber(obj, [\"inputTokens\", \"input_tokens\", \"promptTokens\", \"prompt_tokens\"]);\r\n const output = pickNumber(obj, [\r\n \"outputTokens\",\r\n \"output_tokens\",\r\n \"completionTokens\",\r\n \"completion_tokens\",\r\n ]);\r\n let cacheRead = pickNumber(obj, [\r\n \"cacheReadInputTokens\",\r\n \"cache_read_input_tokens\",\r\n \"cachedTokensCreated\",\r\n \"cached_tokens_created\",\r\n ]);\r\n if (cacheRead === null) {\r\n const details = asRecord(obj.promptTokensDetails) ?? asRecord(obj.prompt_tokens_details);\r\n if (details !== undefined) {\r\n const cached = asNumber(details.cachedTokens ?? details.cached_tokens);\r\n if (cached !== null) cacheRead = Math.trunc(cached);\r\n }\r\n }\r\n const cacheWrite = pickNumber(obj, [\r\n \"cacheCreationInputTokens\",\r\n \"cache_creation_input_tokens\",\r\n \"cacheCreationTokens\",\r\n \"cache_creation_tokens\",\r\n ]);\r\n\r\n usage.input = input ?? 0;\r\n usage.output = output ?? 0;\r\n usage.cacheRead = cacheRead ?? 0;\r\n usage.cacheWrite = cacheWrite ?? 0;\r\n\r\n const credits = asNumber(obj.credits);\r\n if (credits !== null) usage.credits = credits;\r\n const model = asString(obj.model);\r\n if (model !== undefined) usage.model = model;\r\n\r\n return usage;\r\n}\r\n\r\n/**\r\n * Last assistant entry in metadata.runState.sessionState.mainAgentState.\r\n * messageHistory, pulling providerOptions.usage / providerOptions.codebuff.usage\r\n * (+ .codebuff.model). Scans newest-first, merging each as a fallback. Returns\r\n * undefined when no usable entry is found (port of extract_usage_from_run_state).\r\n */\r\nfunction extractUsageFromRunState(metadata: Record<string, unknown>): AssistantUsage | undefined {\r\n const history = asRecord(asRecord(asRecord(asRecord(metadata.runState)?.sessionState)?.mainAgentState));\r\n const rawHistory = history?.messageHistory;\r\n if (!Array.isArray(rawHistory)) return undefined;\r\n\r\n const accumulator = newUsage();\r\n let foundAny = false;\r\n for (let i = rawHistory.length - 1; i >= 0; i--) {\r\n const entry = asRecord(rawHistory[i]);\r\n if (entry === undefined) continue;\r\n if (asString(entry.role) !== \"assistant\") continue;\r\n const providerOptions = asRecord(entry.providerOptions);\r\n if (providerOptions === undefined) continue;\r\n\r\n const entryUsage = newUsage();\r\n if (\"usage\" in providerOptions) {\r\n mergeFallback(entryUsage, parseUsageObject(providerOptions.usage));\r\n }\r\n const codebuff = asRecord(providerOptions.codebuff);\r\n if (codebuff !== undefined && \"usage\" in codebuff) {\r\n mergeFallback(entryUsage, parseUsageObject(codebuff.usage));\r\n }\r\n const cbModel = codebuff !== undefined ? asString(codebuff.model) : undefined;\r\n if (cbModel !== undefined) entryUsage.model = cbModel;\r\n\r\n if (hasSignal(entryUsage) || entryUsage.model !== undefined) foundAny = true;\r\n mergeFallback(accumulator, entryUsage);\r\n }\r\n return foundAny ? accumulator : undefined;\r\n}\r\n\r\n/**\r\n * Extract assistant usage, trying in order metadata.usage, metadata.codebuff.usage,\r\n * then the RunState message history; each is merged as a fallback. A top-level\r\n * `credits` fills cost when the usage objects carry none (extract_assistant_usage).\r\n */\r\nfunction extractAssistantUsage(msg: Record<string, unknown>): AssistantUsage {\r\n const usage = newUsage();\r\n const metadata = asRecord(msg.metadata);\r\n\r\n if (metadata !== undefined) {\r\n const model = asString(metadata.model);\r\n if (model !== undefined) usage.model = model;\r\n if (\"usage\" in metadata) {\r\n mergeFallback(usage, parseUsageObject(metadata.usage));\r\n }\r\n const codebuff = asRecord(metadata.codebuff);\r\n if (codebuff !== undefined && \"usage\" in codebuff) {\r\n mergeFallback(usage, parseUsageObject(codebuff.usage));\r\n }\r\n const runStateUsage = extractUsageFromRunState(metadata);\r\n if (runStateUsage !== undefined) mergeFallback(usage, runStateUsage);\r\n }\r\n\r\n const credits = asNumber(msg.credits);\r\n if (credits !== null && credits > 0 && usage.credits <= 0) usage.credits = credits;\r\n\r\n return usage;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Dedup\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Upstream ChatMessage.id when a non-empty string (stable across re-imports). */\r\nfunction upstreamMessageId(msg: Record<string, unknown>): string | undefined {\r\n const id = asString(msg.id);\r\n return id !== undefined && id !== \"\" ? id : undefined;\r\n}\r\n\r\n/** Deterministic fallback dedup key (derive_dedup_key). */\r\nfunction deriveDedupKey(\r\n sessionId: string,\r\n ts: number,\r\n model: string,\r\n usage: AssistantUsage,\r\n ordinal: number,\r\n): string {\r\n const i = Math.max(0, usage.input);\r\n const o = Math.max(0, usage.output);\r\n const cr = Math.max(0, usage.cacheRead);\r\n const cw = Math.max(0, usage.cacheWrite);\r\n return `codebuff:${sessionId}:${ts}:${model}:${ordinal}:${i}:${o}:${cr}:${cw}`;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// File parse\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Parse one chat-messages.json into usage records (port of parse_codebuff_file). */\r\nfunction parseCodebuffFile(path: string): UsageRecord[] {\r\n const root = readJsonFile(path);\r\n if (!Array.isArray(root)) return []; // missing / malformed / non-array → no rows\r\n\r\n const { channel, project, chatId } = deriveContextFromPath(path);\r\n const sessionId = `${channel}/${project}/${chatId}`;\r\n const { projectKey, projectLabel } = workspaceFromPath(project);\r\n\r\n const chatIdTs = parseChatIdToMillis(chatId); // null when unparseable\r\n const mtime = fileMtimeMs(path);\r\n\r\n const out: UsageRecord[] = [];\r\n for (let ordinal = 0; ordinal < root.length; ordinal++) {\r\n const msg = asRecord(root[ordinal]);\r\n if (msg === undefined) continue;\r\n if (!isAssistantRole(msg)) continue;\r\n\r\n const usage = extractAssistantUsage(msg);\r\n if (!hasSignal(usage)) continue;\r\n\r\n const ts = messageTimestamp(msg) ?? (chatIdTs !== null && chatIdTs > 0 ? chatIdTs : mtime);\r\n const modelId = usage.model ?? DEFAULT_MODEL;\r\n const providerId = inferProvider(modelId) ?? DEFAULT_PROVIDER;\r\n const dedupKey =\r\n upstreamMessageId(msg) ?? deriveDedupKey(sessionId, ts, modelId, usage, ordinal);\r\n\r\n const tokens: TokenBreakdown = emptyTokens();\r\n tokens.input = Math.max(0, usage.input);\r\n tokens.output = Math.max(0, usage.output);\r\n tokens.cacheRead = Math.max(0, usage.cacheRead);\r\n tokens.cacheWrite = Math.max(0, usage.cacheWrite);\r\n // reasoning stays 0 (Codebuff does not report it).\r\n\r\n const record: UsageRecord = {\r\n platformId: PLATFORM_ID,\r\n modelId,\r\n providerId,\r\n sessionId,\r\n tokens,\r\n ts,\r\n messageCount: 1,\r\n dedupKey,\r\n confidence: \"host-reported\",\r\n };\r\n const cost = Math.max(0, usage.credits);\r\n if (cost > 0) record.cost = cost;\r\n if (projectKey !== undefined) record.projectKey = projectKey;\r\n if (projectLabel !== undefined) record.projectLabel = projectLabel;\r\n out.push(record);\r\n }\r\n\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Reader\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The Codebuff (Manicode) usage reader singleton. */\r\nconst codebuffReader: UsageReader = {\r\n platformId: PLATFORM_ID,\r\n kind: \"local\",\r\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\r\n const records: UsageRecord[] = [];\r\n\r\n // Scan each channel's projects root that exists.\r\n // <root>/<project>/chats/<chatId>/chat-messages.json\r\n for (const root of codebuffProjectRoots()) {\r\n const files = walkFiles(root, (name, abs) => {\r\n return (\r\n name === \"chat-messages.json\" &&\r\n /[\\\\/]chats[\\\\/][^\\\\/]+[\\\\/]chat-messages\\.json$/.test(abs)\r\n );\r\n });\r\n for (const file of files) {\r\n for (const row of parseCodebuffFile(file)) {\r\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\r\n records.push(row);\r\n }\r\n }\r\n }\r\n\r\n return records;\r\n },\r\n};\r\n\r\nexport default codebuffReader;\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/codebuff/index.ts"],"sourcesContent":["/**\r\n * adapters/codebuff — Codebuff platform adapter for agent-connector.\r\n *\r\n * Codebuff is an **mcp-only** host: it exposes no lifecycle hook system, and MCP\r\n * is its extensibility mechanism. This adapter therefore installs only the MCP\r\n * server and reports hooks as unavailable (mirrors the Warp reference path that\r\n * validates the `mcp-only` paradigm end-to-end).\r\n *\r\n * MCP config (SPEC):\r\n * - project scope (preferred) → <projectDir>/.agents/mcp.json\r\n * - user scope → ~/.agents/mcp.json\r\n * Both are JSON, root key \"mcpServers\". There is no separate hook file — the\r\n * hook \"config path\" is the same mcp.json so the generic doctor/backup behave\r\n * sensibly.\r\n *\r\n * A stdio server entry is the standard `{ type:\"stdio\", command, args, env }`\r\n * shape. Codebuff supports native `$VAR` interpolation, so `${env:VAR}` refs are\r\n * rewritten to Codebuff's native `$VAR` token (rewriteEnvRefs) rather than being\r\n * resolved to literals — secrets are never baked into the config file.\r\n */\r\n\r\nimport { existsSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { join } from \"node:path\";\r\n\r\nimport { BaseAdapter } from \"../base.js\";\r\nimport type { Adapter, InstallContext } from \"../spi.js\";\r\nimport type {\r\n ChangeRecord,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookParadigm,\r\n PlatformCapabilities,\r\n PlatformId,\r\n ServerDef,\r\n SubagentDef,\r\n Transport,\r\n} from \"../../core/types.js\";\r\nimport { rewriteEnvRefs } from \"../../core/interpolate.js\";\r\nimport {\r\n buildWrappedStdio,\r\n} from \"../../core/spawn.js\";\r\nimport { renderSkillMd } from \"../claude-code/render.js\";\r\n\r\nconst HOST: PlatformId = \"codebuff\";\r\nconst MCP_ROOT_KEY = \"mcpServers\";\r\n\r\n/**\r\n * Render `${env:VAR}`/`${env:VAR:-default}` into Codebuff's native `$VAR` token.\r\n *\r\n * When the portable ref carried a default (`${env:VAR:-fallback}`), Codebuff's\r\n * native `$VAR` token cannot express it — so a bare native token would silently\r\n * DROP the default. Instead, resolve the default at install time: emit the live\r\n * value when VAR is set and non-empty, else the literal fallback. The native\r\n * token is only emitted when there is no default to preserve.\r\n */\r\nconst toNativeRef = (name: string, def?: string): string => {\r\n if (def !== undefined) {\r\n const v = process.env[name];\r\n return v != null && v !== \"\" ? v : def;\r\n }\r\n return `$${name}`;\r\n};\r\n\r\n/** Recursively rewrite every `${env:VAR}` ref in a JSON-ish value to `$VAR`. */\r\nfunction rewriteEnvRefsDeep<T>(value: T): T {\r\n if (typeof value === \"string\") {\r\n return rewriteEnvRefs(value, toNativeRef) as unknown as T;\r\n }\r\n if (Array.isArray(value)) {\r\n return value.map((v) => rewriteEnvRefsDeep(v)) as unknown as T;\r\n }\r\n if (value && typeof value === \"object\") {\r\n const out: Record<string, unknown> = {};\r\n for (const [k, v] of Object.entries(value)) out[k] = rewriteEnvRefsDeep(v);\r\n return out as T;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Render one AgentDefinition field as a ` key: value,` line for the emitted\r\n * `.agents/<id>.ts` module. The value is serialized with JSON.stringify (correct\r\n * string/array/object escaping); a known-identifier key is emitted unquoted, and\r\n * anything else (only reachable via `extra`) is quoted. Multi-line JSON (arrays /\r\n * nested objects) is reindented so it sits under the 2-space object body.\r\n */\r\nfunction renderAgentField(key: string, value: unknown): string {\r\n const k = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : JSON.stringify(key);\r\n const json = JSON.stringify(value, null, 2);\r\n const v = json.includes(\"\\n\") ? json.replace(/\\n/g, \"\\n \") : json;\r\n return ` ${k}: ${v},`;\r\n}\r\n\r\n/**\r\n * Native MCP server entry shapes Codebuff accepts under `mcpServers`.\r\n * A stdio entry is tagged with `type:\"stdio\"`; remote transports carry a `url`.\r\n */\r\ninterface CodebuffStdioServer {\r\n type: \"stdio\";\r\n command: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n}\r\ninterface CodebuffHttpServer {\r\n type: \"http\";\r\n url: string;\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport class CodebuffAdapter extends BaseAdapter implements Adapter {\r\n readonly id: PlatformId = HOST;\r\n readonly name = \"Codebuff\";\r\n readonly paradigm: HookParadigm = \"mcp-only\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block via the BaseAdapter default\r\n // (memoryTargets: project <projectDir>/AGENTS.md; user scope where documented).\r\n supportsMemory: true,\r\n // Codebuff has no lifecycle hook system — every hook capability is false.\r\n preToolUse: false,\r\n postToolUse: false,\r\n preCompact: false,\r\n sessionStart: false,\r\n sessionEnd: false,\r\n userPromptSubmit: false,\r\n stop: false,\r\n notification: false,\r\n canModifyArgs: false,\r\n canModifyOutput: false,\r\n canInjectSessionContext: false,\r\n // Codebuff registers stdio and Streamable HTTP MCP servers.\r\n transports: [\"stdio\", \"http\"],\r\n // Server env/url use Codebuff's NATIVE ${env:VAR} interpolation\r\n // (rewriteEnvRefs) — the token survives into the config, never a baked\r\n // literal — so the installer's unset-env-ref bake warn does not apply here.\r\n nativeServerEnvInterpolation: true,\r\n // Content surfaces: Codebuff reads AgentSkills from\r\n // <configDir>/skills/<name>/SKILL.md (configDir is .agents, so the path is\r\n // .agents/skills/<name>/SKILL.md). Verified against codebuff source\r\n // sdk/src/skills/load-skills.ts — the frontmatter `name` MUST equal the dir\r\n // name. Commands have no native Codebuff surface. Subagents ARE natively\r\n // supported — executable .agents/*.ts AgentDefinition modules (codebuff docs:\r\n // \"Create a new TypeScript file in .agents/\") — and are now WIRED:\r\n // installSubagents emits one `.agents/<id>.ts` AgentDefinition module per\r\n // declared subagent (PROJECT scope; see renderSubagent), each\r\n // default-exporting the AgentDefinition object WITHOUT the type-only\r\n // `agent-definition` import (erased at runtime; emitting it would only couple\r\n // the module to a generated types file that may not exist).\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n };\r\n\r\n // ── Detection ────────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = join(homedir(), \".agents\");\r\n const userMcp = join(userDir, \"mcp.json\");\r\n const projDir = join(projectDir, \".agents\");\r\n const projMcp = join(projDir, \"mcp.json\");\r\n\r\n const userInstalled = existsSync(userDir) || existsSync(userMcp);\r\n const projInstalled = existsSync(projDir) || existsSync(projMcp);\r\n const installed = userInstalled || projInstalled;\r\n // Project is the preferred scope; fall back to user when only that matched.\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projMcp : userMcp;\r\n\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? `found Codebuff config (${scope})`\r\n : `no .agents config dir at ${userDir} or ${projDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ─────────────────────────────────────────────────────────\r\n\r\n getConfigDir(ctx: InstallContext): string {\r\n return ctx.scope === \"project\"\r\n ? join(ctx.projectDir, \".agents\")\r\n : join(homedir(), \".agents\");\r\n }\r\n\r\n getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"mcp.json\");\r\n }\r\n\r\n /**\r\n * Codebuff has no hook file — hooks are not a thing here. The hook \"config\r\n * path\" is the same mcp.json so the generic doctor/backup behave sensibly.\r\n */\r\n getHookConfigPath(ctx: InstallContext): string {\r\n return this.getServerConfigPath(ctx);\r\n }\r\n\r\n // ── MCP server install / uninstall ───────────────────────────────────────\r\n\r\n installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n const override = connector.platforms[HOST]?.server;\r\n if (!connector.server || override === false) {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: connector.server\r\n ? \"server registration disabled for codebuff\"\r\n : \"connector declares no MCP server\",\r\n },\r\n ];\r\n }\r\n\r\n // Shallow-merge any per-platform server override into the base ServerDef.\r\n const server: ServerDef =\r\n override && typeof override === \"object\"\r\n ? { ...connector.server, ...override }\r\n : connector.server;\r\n\r\n const serverPath = this.getServerConfigPath(ctx);\r\n const entry = this.renderServerEntry(ctx, server);\r\n\r\n return [\r\n this.upsertServerInJson(serverPath, MCP_ROOT_KEY, connector.id, entry, ctx.dryRun),\r\n ];\r\n }\r\n\r\n uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const serverPath = this.getServerConfigPath(ctx);\r\n return [\r\n this.removeServerFromJson(serverPath, MCP_ROOT_KEY, ctx.connector.id, ctx.dryRun),\r\n ];\r\n }\r\n\r\n /** Render a normalized ServerDef into Codebuff's native mcpServers entry. */\r\n private renderServerEntry(\r\n ctx: InstallContext,\r\n server: ServerDef,\r\n ): CodebuffStdioServer | CodebuffHttpServer {\r\n const transport: Transport = server.transport;\r\n\r\n if (transport === \"stdio\") {\r\n let command = server.command ?? \"\";\r\n let args = [...(server.args ?? [])];\r\n\r\n // Transparent telemetry wrapping: route the real command through\r\n // `<homeBin> serve --connector <id> -- <command> <args...>`.\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n // Codebuff supports native `$VAR` interpolation, so rewrite every\r\n // ${env:VAR} ref to `$VAR` rather than baking literals into the config.\r\n const entry: CodebuffStdioServer = {\r\n type: \"stdio\",\r\n command: rewriteEnvRefsDeep(command),\r\n };\r\n if (args.length > 0) entry.args = rewriteEnvRefsDeep(args);\r\n const env = this.renderEnv(server.env);\r\n if (env) entry.env = env;\r\n return entry;\r\n }\r\n\r\n // http (and any other remote transport) — Codebuff registers a URL.\r\n const entry: CodebuffHttpServer = {\r\n type: \"http\",\r\n url: rewriteEnvRefsDeep(server.url ?? \"\"),\r\n };\r\n const headers = this.renderEnv(server.headers);\r\n if (headers) entry.headers = headers;\r\n return entry;\r\n }\r\n\r\n /**\r\n * Render env/header values. Codebuff supports native `$VAR` interpolation, so\r\n * rewrite `${env:VAR}` references to `$VAR` rather than resolving to literals.\r\n */\r\n private renderEnv(\r\n env: Record<string, string> | undefined,\r\n ): Record<string, string> | undefined {\r\n if (!env || Object.keys(env).length === 0) return undefined;\r\n return rewriteEnvRefsDeep({ ...env });\r\n }\r\n\r\n // ── Content surfaces: skills ──────────────────────────────────────────────\r\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\r\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\r\n // skip) via writeContentFile and reversible via removeContentFile. Honors\r\n // platforms[\"codebuff\"].skills === false to skip. Both user and project scope\r\n // are supported (configDir resolves per scope).\r\n //\r\n // Native location:\r\n // skill → <configDir>/skills/<name>/SKILL.md (+ resources)\r\n // configDir is .agents, so .agents/skills/<name>/SKILL.md. Verified\r\n // against codebuff source sdk/src/skills/load-skills.ts — the\r\n // frontmatter `name` MUST equal the dir name.\r\n\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n return join(this.getConfigDir(ctx), \"skills\", name);\r\n }\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codebuff\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n changes.push(\r\n this.writeContentFile(join(dir, \"SKILL.md\"), renderSkillMd(skill), ctx.dryRun),\r\n );\r\n // Bundle any resource files beside SKILL.md (relative path → contents).\r\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\r\n // (config-time validation already rejects these, but never trust input).\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n }\r\n return changes;\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n // Remove only the files we wrote (SKILL.md + declared resources), then the\r\n // skill dir itself when we own its full contents.\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue; // never delete outside the skill dir\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n // Only remove the skill dir when WE own its full contents — never rm -rf a\r\n // dir that still holds user-added / sibling-tool / shared files.\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n // ── Content surfaces: subagents ───────────────────────────────────────────\r\n // CONTENT-ONLY: pure native-file writers (no runtime dispatch, no home-bin\r\n // pointer, no telemetry wrap). Idempotent via writeContentFile, reversible via\r\n // removeContentFile. Honors platforms[\"codebuff\"].subagents === false.\r\n //\r\n // Native location: codebuff agents are executable TypeScript modules in the\r\n // PROJECT .agents/ dir — <projectDir>/.agents/<id>.ts (codebuff docs:\r\n // \"Create a new TypeScript file in .agents/\"). No user-scope agents dir is\r\n // documented, so user scope warn-skips (the warp/amp project-scoped precedent).\r\n\r\n /** Native subagent module path: <configDir>/<name>.ts (= .agents/<name>.ts). */\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.getConfigDir(ctx), `${name}.ts`);\r\n }\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[HOST]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for codebuff\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n // codebuff agents live in the PROJECT .agents/ dir; no user-scope agents dir\r\n // is documented, so user scope warn-skips (mirrors warp/amp project-scoped).\r\n if (ctx.scope !== \"project\") {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"warn\",\r\n detail:\r\n \"codebuff subagents are project-scoped only (.agents/*.ts; no documented \" +\r\n `user-scope agents dir); ${connector.subagents.length} skipped`,\r\n },\r\n ];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(\r\n this.subagentPath(ctx, agent.name),\r\n this.renderSubagent(agent),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n if (ctx.scope !== \"project\") {\r\n return [\r\n { platform: this.id, action: \"skip\", detail: \"codebuff subagents are project-scoped only\" },\r\n ];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /**\r\n * Render a subagent into a Codebuff `.agents/<id>.ts` AgentDefinition module:\r\n *\r\n * const definition = {\r\n * id: \"<name>\",\r\n * ...\r\n * };\r\n *\r\n * export default definition;\r\n *\r\n * Emitted WITHOUT the `import { AgentDefinition } from './types/agent-definition'`\r\n * line the docs show: that import is TYPE-ONLY (erased at runtime), so omitting\r\n * it avoids coupling the module to a generated types file that may not exist —\r\n * a bare object literal + default export is a complete, valid AgentDefinition.\r\n *\r\n * Field mapping (ONLY fields AC's SubagentDef can populate; nothing fabricated):\r\n * id ← name (already kebab-case → a valid codebuff id)\r\n * displayName ← name\r\n * spawnerPrompt ← description (the delegation hint)\r\n * model ← model (OMITTED when the connector declares none)\r\n * toolNames ← tools.allow (OMITTED when none declared)\r\n * instructionsPrompt ← prompt (the system prompt / instructions body)\r\n * SubagentDef.readonly is NOT mapped: Codebuff expresses tool access through the\r\n * `toolNames` allowlist and documents no read-only permission flag, and AC has no\r\n * verified read-only tool taxonomy to synthesize one — so a readonly hint is\r\n * carried only if the author restricts `tools.allow` themselves (or via `extra`).\r\n * `extra` is merged LAST as the documented escape hatch — the only way to reach\r\n * codebuff AgentDefinition fields AC does not model (version, outputMode,\r\n * spawnableAgents, inputSchema, …); its values come from the connector author,\r\n * never invented here.\r\n */\r\n private renderSubagent(agent: SubagentDef): string {\r\n const def: Record<string, unknown> = {\r\n id: agent.name,\r\n displayName: agent.name,\r\n spawnerPrompt: agent.description,\r\n };\r\n if (agent.model !== undefined) def.model = agent.model;\r\n const allow = agent.tools?.allow;\r\n if (allow && allow.length > 0) def.toolNames = [...allow];\r\n def.instructionsPrompt = agent.prompt;\r\n if (agent.extra) Object.assign(def, agent.extra);\r\n\r\n const body = Object.entries(def)\r\n .map(([k, v]) => renderAgentField(k, v))\r\n .join(\"\\n\");\r\n return `const definition = {\\n${body}\\n};\\n\\nexport default definition;\\n`;\r\n }\r\n\r\n // ── Hooks (unavailable — Codebuff is mcp-only) ────────────────────────────\r\n\r\n installHooks(_ctx: InstallContext): ChangeRecord[] {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"hooks unavailable (Codebuff is mcp-only)\",\r\n },\r\n ];\r\n }\r\n\r\n uninstallHooks(_ctx: InstallContext): ChangeRecord[] {\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n detail: \"hooks unavailable (Codebuff is mcp-only)\",\r\n },\r\n ];\r\n }\r\n\r\n // ── Diagnostics ──────────────────────────────────────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const mcpPath = this.getServerConfigPath(ctx);\r\n const connectorId = ctx.connector.id;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: mcp.json present`,\r\n check: () =>\r\n existsSync(mcpPath)\r\n ? { status: \"OK\", detail: mcpPath }\r\n : { status: \"FAIL\", detail: `not found: ${mcpPath}` },\r\n },\r\n {\r\n name: `${this.name}: server entry registered`,\r\n check: () => {\r\n // Only assert what the connector declares: a server-less connector\r\n // never writes a server entry, so its absence is healthy.\r\n if (!ctx.connector.server) {\r\n return { status: \"OK\", detail: \"no MCP server declared\" };\r\n }\r\n const cfg = this.readJson<{ [k: string]: Record<string, unknown> }>(mcpPath);\r\n const bucket = cfg?.[MCP_ROOT_KEY];\r\n if (!cfg || !bucket) {\r\n return { status: \"FAIL\", detail: `no ${MCP_ROOT_KEY} in ${mcpPath}` };\r\n }\r\n return connectorId in bucket\r\n ? { status: \"OK\", detail: `${MCP_ROOT_KEY}.${connectorId} present` }\r\n : {\r\n status: \"FAIL\",\r\n detail: `no ${MCP_ROOT_KEY}.${connectorId} in ${mcpPath}`,\r\n };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: assert presence only for the skills this connector\r\n // declares (a skill-less connector writes none, so absence is healthy).\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n // Subagent checks: codebuff agents are PROJECT-scoped .agents/*.ts modules,\r\n // so assert presence only at project scope (user scope warn-skips install).\r\n if (ctx.scope === \"project\") {\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n }\r\n return checks;\r\n }\r\n}\r\n\r\nexport const adapter = new CodebuffAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":["entry"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/usage/readers/codex.ts"],"sourcesContent":["/**\r\n * usage/readers/codex — Codex CLI native session-log reader.\r\n *\r\n * Faithful port of tokscale sessions/codex.rs (the hard, stateful reader). Reads\r\n * ~/.codex/sessions/**\\/*.jsonl (and the rare *.json headless variants; the\r\n * rollout-*.jsonl files are just a subset of *.jsonl and need no special-casing).\r\n *\r\n * Codex logs a cumulative token snapshot on every `token_count` event, so naive\r\n * summing double-counts every turn. This reader reproduces codex.rs exactly:\r\n *\r\n * - The per-turn increment comes from `payload.info.last_token_usage`\r\n * (the DELTA source). `total_token_usage` is a mutable cumulative snapshot\r\n * (compaction / context-window capping rewrites it) used ONLY for dedup and\r\n * monotonicity / stale-regression checks — never as a direct delta source\r\n * unless `last_token_usage` is absent.\r\n * - State is tracked PER SESSION (per file): `previous_totals` is the last\r\n * accepted cumulative baseline; each new snapshot must advance past it.\r\n * - When the new total equals the previous baseline → skip (duplicate snapshot).\r\n * - When the total regresses but `looks_like_stale_regression` holds (a small\r\n * out-of-order dip that resumes from the true watermark next row) → skip,\r\n * so `last_token_usage` is not counted twice.\r\n * - Forked-child sessions replay parent token rows before their first\r\n * `turn_context`; those inherited snapshots are skipped until totals move\r\n * past the inherited baseline.\r\n *\r\n * Token mapping (CodexTotals::into_tokens): cached = min(cached, input); the\r\n * reported `input` already INCLUDES cached, so net input = input - cached\r\n * (clamped ≥ 0). cache_read = clamped cached, cache_write = 0, reasoning as-is.\r\n * `cached` itself is max(cached_input_tokens, cache_read_input_tokens).\r\n *\r\n * Model: model_info.slug > model > model_name > info.model > info.model_name,\r\n * falling back to the session's current_model (from turn_context). Provider:\r\n * session_meta.model_provider, else inferred from the model, else \"openai\".\r\n * Session id: the file stem. Project: session_meta.cwd, only when it looks like\r\n * an explicit absolute/UNC/drive path. Confidence is \"host-reported\".\r\n *\r\n * Dedup key (set only when the row had a real RFC3339 timestamp, matching\r\n * codex.rs which skips the key on the mtime fallback):\r\n * codex:token_count:<ts>:<provider>:<model>:<in>:<out>:<cacheRead>:<cacheWrite>:<reasoning>\r\n *\r\n * Fail-open: no root → []; unreadable/malformed file or line → skipped.\r\n */\r\n\r\nimport { basename } from \"node:path\";\r\n\r\nimport type { TokenBreakdown, UsageReader, UsageRecord } from \"../types.js\";\r\nimport { emptyTokens } from \"../aggregate.js\";\r\nimport { fileMtimeMs, readJsonlLines } from \"../jsonl.js\";\r\nimport { inferProvider, normalizeWorkspaceKey, workspaceLabelFromKey } from \"../normalize.js\";\r\nimport { firstExistingRoot, walkFiles } from \"../paths.js\";\r\n\r\nconst PLATFORM_ID = \"codex\" as const;\r\nconst DEFAULT_MODEL = \"unknown\";\r\nconst DEFAULT_PROVIDER = \"openai\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Wire shapes (everything optional / unknown — narrowed at use)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface CodexTokenUsage {\r\n input_tokens?: unknown;\r\n output_tokens?: unknown;\r\n cached_input_tokens?: unknown;\r\n cache_read_input_tokens?: unknown;\r\n reasoning_output_tokens?: unknown;\r\n total_tokens?: unknown;\r\n}\r\n\r\ninterface CodexInfo {\r\n model?: unknown;\r\n model_name?: unknown;\r\n last_token_usage?: CodexTokenUsage | null;\r\n total_token_usage?: CodexTokenUsage | null;\r\n}\r\n\r\ninterface CodexModelInfo {\r\n slug?: unknown;\r\n}\r\n\r\ninterface CodexPayload {\r\n id?: unknown;\r\n forked_from_id?: unknown;\r\n type?: unknown;\r\n model?: unknown;\r\n model_name?: unknown;\r\n model_info?: CodexModelInfo | null;\r\n info?: CodexInfo | null;\r\n source?: unknown;\r\n cwd?: unknown;\r\n model_provider?: unknown;\r\n agent_nickname?: unknown;\r\n}\r\n\r\ninterface CodexEntry {\r\n type?: unknown;\r\n timestamp?: unknown;\r\n payload?: CodexPayload | null;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// CodexTotals — the four cumulative dimensions + delta / regression logic\r\n// (port of the Rust CodexTotals struct).\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface CodexTotals {\r\n input: number;\r\n output: number;\r\n cached: number;\r\n reasoning: number;\r\n}\r\n\r\n/** Coerce an unknown to a non-negative integer (0 on absence/garbage). */\r\nfunction toNonNegInt(v: unknown): number {\r\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\r\n if (!Number.isFinite(n)) return 0;\r\n return Math.max(0, Math.trunc(n));\r\n}\r\n\r\n/** Read a possibly-missing i64-ish field as an integer (may be negative). */\r\nfunction toIntOr(v: unknown, fallback: number): number {\r\n const n = typeof v === \"number\" ? v : typeof v === \"string\" ? Number(v) : NaN;\r\n if (!Number.isFinite(n)) return fallback;\r\n return Math.trunc(n);\r\n}\r\n\r\n/** CodexTotals::from_usage — clamp each field ≥ 0; cached = max of both fields. */\r\nfunction totalsFromUsage(usage: CodexTokenUsage): CodexTotals {\r\n const cached = Math.max(\r\n toIntOr(usage.cached_input_tokens, 0),\r\n toIntOr(usage.cache_read_input_tokens, 0),\r\n );\r\n return {\r\n input: Math.max(0, toIntOr(usage.input_tokens, 0)),\r\n output: Math.max(0, toIntOr(usage.output_tokens, 0)),\r\n cached: Math.max(0, cached),\r\n reasoning: Math.max(0, toIntOr(usage.reasoning_output_tokens, 0)),\r\n };\r\n}\r\n\r\nfunction totalsEqual(a: CodexTotals, b: CodexTotals): boolean {\r\n return a.input === b.input && a.output === b.output && a.cached === b.cached && a.reasoning === b.reasoning;\r\n}\r\n\r\n/** CodexTotals::delta_from — null when any dimension regressed. */\r\nfunction deltaFrom(self: CodexTotals, previous: CodexTotals): CodexTotals | null {\r\n if (\r\n self.input < previous.input ||\r\n self.output < previous.output ||\r\n self.cached < previous.cached ||\r\n self.reasoning < previous.reasoning\r\n ) {\r\n return null;\r\n }\r\n return {\r\n input: self.input - previous.input,\r\n output: self.output - previous.output,\r\n cached: self.cached - previous.cached,\r\n reasoning: self.reasoning - previous.reasoning,\r\n };\r\n}\r\n\r\n/** CodexTotals::saturating_add (plain add — values are well within Number range). */\r\nfunction saturatingAdd(self: CodexTotals, other: CodexTotals): CodexTotals {\r\n return {\r\n input: self.input + other.input,\r\n output: self.output + other.output,\r\n cached: self.cached + other.cached,\r\n reasoning: self.reasoning + other.reasoning,\r\n };\r\n}\r\n\r\nfunction totalsSum(t: CodexTotals): number {\r\n return t.input + t.output + t.cached + t.reasoning;\r\n}\r\n\r\n/** CodexTotals::is_within — every dimension ≤ baseline. */\r\nfunction isWithin(self: CodexTotals, baseline: CodexTotals): boolean {\r\n return (\r\n self.input <= baseline.input &&\r\n self.output <= baseline.output &&\r\n self.cached <= baseline.cached &&\r\n self.reasoning <= baseline.reasoning\r\n );\r\n}\r\n\r\n/**\r\n * CodexTotals::looks_like_stale_regression — some snapshots arrive slightly out\r\n * of order: the cumulative total dips by ~one recent increment then resumes from\r\n * the true higher watermark next row. Treat those as stale (skip) rather than a\r\n * hard reset, so last_token_usage is not counted twice.\r\n */\r\nfunction looksLikeStaleRegression(self: CodexTotals, previous: CodexTotals, last: CodexTotals): boolean {\r\n const previousTotal = totalsSum(previous);\r\n const currentTotal = totalsSum(self);\r\n const lastTotal = totalsSum(last);\r\n if (previousTotal <= 0 || currentTotal <= 0 || lastTotal <= 0) return false;\r\n return currentTotal * 100 >= previousTotal * 98 || currentTotal + lastTotal * 2 >= previousTotal;\r\n}\r\n\r\n/**\r\n * CodexTotals::into_tokens — clamp cached to ≤ input so malformed rows can't\r\n * inflate the total; net input = input - clamped_cached; cache_write = 0.\r\n */\r\nfunction intoTokens(t: CodexTotals): TokenBreakdown {\r\n const clampedCached = Math.max(0, Math.min(t.cached, t.input));\r\n const tokens = emptyTokens();\r\n tokens.input = Math.max(0, t.input - clampedCached);\r\n tokens.output = Math.max(0, t.output);\r\n tokens.cacheRead = clampedCached;\r\n tokens.cacheWrite = 0;\r\n tokens.reasoning = Math.max(0, t.reasoning);\r\n return tokens;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Per-file (per-session) parse state\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\ninterface CodexParseState {\r\n currentModel: string | undefined;\r\n previousTotals: CodexTotals | undefined;\r\n sessionIsHeadless: boolean;\r\n sessionProvider: string | undefined;\r\n sessionAgent: string | undefined;\r\n sessionWorkspaceKey: string | undefined;\r\n sessionWorkspaceLabel: string | undefined;\r\n forkedChildWaitingForTurnContext: boolean;\r\n forkedChildInheritedBaseline: CodexTotals | undefined;\r\n forkedChildInheritedReportedTotal: number | undefined;\r\n}\r\n\r\nfunction freshState(): CodexParseState {\r\n return {\r\n currentModel: undefined,\r\n previousTotals: undefined,\r\n sessionIsHeadless: false,\r\n sessionProvider: undefined,\r\n sessionAgent: undefined,\r\n sessionWorkspaceKey: undefined,\r\n sessionWorkspaceLabel: undefined,\r\n forkedChildWaitingForTurnContext: false,\r\n forkedChildInheritedBaseline: undefined,\r\n forkedChildInheritedReportedTotal: undefined,\r\n };\r\n}\r\n\r\n/**\r\n * A model-less token_count record buffered until a later turn resolves the\r\n * model (port of codex.rs `pending_model_messages`). codex.rs back-fills the\r\n * resolved model + dedup key onto these, and flushes any still-unresolved at EOF\r\n * as \"unknown\" — but STILL with a dedup key when the row had a real timestamp.\r\n * `usedFallbackTimestamp` mirrors `parsed_timestamp.is_none()`: when true the\r\n * dedup key is skipped on flush (the mtime fallback is not a stable identity).\r\n */\r\ninterface PendingCodexRecord {\r\n record: UsageRecord;\r\n tokens: TokenBreakdown;\r\n providerId: string;\r\n ts: number;\r\n usedFallbackTimestamp: boolean;\r\n}\r\n\r\n/**\r\n * Flush every buffered model-less record with a now-resolved model (port of\r\n * flush_pending_model_messages): back-fill modelId and — when the row carried a\r\n * real timestamp — the codex dedup key keyed on that model.\r\n */\r\nfunction flushPending(pending: PendingCodexRecord[], out: UsageRecord[], model: string): void {\r\n for (const p of pending) {\r\n p.record.modelId = model;\r\n if (!p.usedFallbackTimestamp) {\r\n p.record.dedupKey = codexDedupKey(p.ts, p.providerId, model, p.tokens);\r\n }\r\n out.push(p.record);\r\n }\r\n pending.length = 0;\r\n}\r\n\r\n/** Flush remaining buffered records as \"unknown\" (still keyed when timestamped). */\r\nfunction flushPendingAsUnknown(pending: PendingCodexRecord[], out: UsageRecord[]): void {\r\n if (pending.length === 0) return;\r\n flushPending(pending, out, DEFAULT_MODEL);\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Helpers\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nfunction nonEmptyString(v: unknown): string | undefined {\r\n return typeof v === \"string\" && v !== \"\" ? v : undefined;\r\n}\r\n\r\n/** session id from path file stem (port of session_id_from_path). */\r\nfunction sessionIdFromPath(path: string): string {\r\n const name = basename(path);\r\n const dot = name.lastIndexOf(\".\");\r\n const stem = dot > 0 ? name.slice(0, dot) : name;\r\n return stem === \"\" ? \"unknown\" : stem;\r\n}\r\n\r\n/** Parse an RFC3339 timestamp to epoch ms, or null (port of parse_codex_entry_timestamp). */\r\nfunction parseEntryTimestamp(v: unknown): number | null {\r\n if (typeof v !== \"string\" || v === \"\") return null;\r\n const ms = Date.parse(v);\r\n return Number.isNaN(ms) ? null : ms;\r\n}\r\n\r\n/**\r\n * extract_model — model_info.slug > model > model_name > info.model >\r\n * info.model_name (first non-empty).\r\n */\r\nfunction extractModel(payload: CodexPayload): string | undefined {\r\n return (\r\n nonEmptyString(payload.model_info?.slug) ??\r\n nonEmptyString(payload.model) ??\r\n nonEmptyString(payload.model_name) ??\r\n (payload.info ? extractModelFromInfo(payload.info) : undefined)\r\n );\r\n}\r\n\r\n/** extract_model_from_info — info.model > info.model_name. */\r\nfunction extractModelFromInfo(info: CodexInfo): string | undefined {\r\n return nonEmptyString(info.model) ?? nonEmptyString(info.model_name);\r\n}\r\n\r\n/** codex_source_is_exec — session_meta.source === \"exec\" marks a headless run. */\r\nfunction sourceIsExec(source: unknown): boolean {\r\n return source === \"exec\";\r\n}\r\n\r\n/** forked_from_id_from_source — source.subagent.thread_spawn.parent_thread_id. */\r\nfunction forkedFromIdFromSource(source: unknown): string | undefined {\r\n if (typeof source !== \"object\" || source === null) return undefined;\r\n const sub = (source as Record<string, unknown>).subagent;\r\n if (typeof sub !== \"object\" || sub === null) return undefined;\r\n const spawn = (sub as Record<string, unknown>).thread_spawn;\r\n if (typeof spawn !== \"object\" || spawn === null) return undefined;\r\n const parent = (spawn as Record<string, unknown>).parent_thread_id;\r\n return nonEmptyString(parent);\r\n}\r\n\r\n/**\r\n * codex_workspace_from_cwd — normalize the cwd, but only accept it when it looks\r\n * like an explicit absolute/UNC/drive path AND yields a label.\r\n */\r\nfunction workspaceFromCwd(cwd: string): { key?: string; label?: string } {\r\n const normalized = normalizeWorkspaceKey(cwd);\r\n if (normalized === undefined) return {};\r\n // Reject control characters.\r\n for (let i = 0; i < normalized.length; i++) {\r\n const c = normalized.charCodeAt(i);\r\n if (c < 0x20 || c === 0x7f) return {};\r\n }\r\n if (!looksLikeExplicitWorkspacePath(normalized)) return {};\r\n const label = workspaceLabelFromKey(normalized);\r\n if (label === undefined) return {};\r\n return { key: normalized, label };\r\n}\r\n\r\n/** looks_like_explicit_workspace_path — leading `/` or `//`, or `X:/` drive. */\r\nfunction looksLikeExplicitWorkspacePath(path: string): boolean {\r\n if (path.startsWith(\"//\") || path.startsWith(\"/\")) return true;\r\n if (path.length >= 3) {\r\n const c0 = path.charCodeAt(0);\r\n const isAlpha = (c0 >= 0x41 && c0 <= 0x5a) || (c0 >= 0x61 && c0 <= 0x7a);\r\n if (isAlpha && path[1] === \":\" && path[2] === \"/\") return true;\r\n }\r\n return false;\r\n}\r\n\r\n/** reported_total_tokens — info.total_token_usage.total_tokens when ≥ 0. */\r\nfunction reportedTotalTokens(usage: CodexTokenUsage): number | undefined {\r\n const v = toIntOr(usage.total_tokens, NaN);\r\n if (!Number.isFinite(v) || v < 0) return undefined;\r\n return v;\r\n}\r\n\r\nfunction rememberForkedChildInheritedBaseline(state: CodexParseState, info: CodexInfo): void {\r\n const totalUsage = info.total_token_usage;\r\n if (!totalUsage) return;\r\n const totals = totalsFromUsage(totalUsage);\r\n state.previousTotals = totals;\r\n state.forkedChildInheritedBaseline = totals;\r\n state.forkedChildInheritedReportedTotal = reportedTotalTokens(totalUsage);\r\n}\r\n\r\nfunction forkedChildShouldSkipInheritedSnapshot(\r\n state: CodexParseState,\r\n totalUsage: CodexTokenUsage | null | undefined,\r\n totals: CodexTotals | undefined,\r\n): boolean {\r\n if (totalUsage && state.forkedChildInheritedReportedTotal !== undefined) {\r\n const reported = reportedTotalTokens(totalUsage);\r\n if (reported !== undefined && reported <= state.forkedChildInheritedReportedTotal) {\r\n return true;\r\n }\r\n }\r\n if (totals !== undefined && state.forkedChildInheritedBaseline !== undefined) {\r\n return isWithin(totals, state.forkedChildInheritedBaseline);\r\n }\r\n return false;\r\n}\r\n\r\n/** The codex:token_count dedup key (port of codex_token_count_dedup_key). */\r\nfunction codexDedupKey(\r\n ts: number,\r\n provider: string,\r\n model: string,\r\n tokens: TokenBreakdown,\r\n): string {\r\n return `codex:token_count:${ts}:${provider}:${model}:${tokens.input}:${tokens.output}:${tokens.cacheRead}:${tokens.cacheWrite}:${tokens.reasoning}`;\r\n}\r\n\r\nfunction tokensAllZero(t: TokenBreakdown): boolean {\r\n return t.input === 0 && t.output === 0 && t.cacheRead === 0 && t.reasoning === 0;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// File parse (port of parse_codex_reader, stateless single-pass)\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nfunction parseCodexFile(path: string): UsageRecord[] {\r\n const lines = readJsonlLines(path);\r\n if (lines.length === 0) return [];\r\n\r\n const sessionId = sessionIdFromPath(path);\r\n const fallbackTs = fileMtimeMs(path);\r\n const state = freshState();\r\n const out: UsageRecord[] = [];\r\n // Model-less token_count rows are buffered here and back-filled once a later\r\n // turn resolves the model (else flushed as \"unknown\" WITH a dedup key at EOF).\r\n const pending: PendingCodexRecord[] = [];\r\n\r\n for (const raw of lines) {\r\n if (typeof raw !== \"object\" || raw === null) continue;\r\n const entry = raw as CodexEntry;\r\n const payload = entry.payload;\r\n if (payload === undefined || payload === null) continue;\r\n\r\n const entryType = typeof entry.type === \"string\" ? entry.type : \"\";\r\n const payloadType = typeof payload.type === \"string\" ? payload.type : undefined;\r\n const isTokenCount = entryType === \"event_msg\" && payloadType === \"token_count\";\r\n\r\n // ── Forked-child gate: replayed parent rows arrive before turn_context. ──\r\n if (state.forkedChildWaitingForTurnContext) {\r\n if (entryType === \"turn_context\") {\r\n state.forkedChildWaitingForTurnContext = false;\r\n state.currentModel = extractModel(payload);\r\n } else {\r\n if (isTokenCount && payload.info) {\r\n rememberForkedChildInheritedBaseline(state, payload.info);\r\n }\r\n continue;\r\n }\r\n }\r\n\r\n // ── session_meta: headless flag, fork detection, provider, cwd. ──\r\n if (entryType === \"session_meta\") {\r\n if (sourceIsExec(payload.source)) state.sessionIsHeadless = true;\r\n const forkedFromId =\r\n nonEmptyString(payload.forked_from_id) ?? forkedFromIdFromSource(payload.source);\r\n if (forkedFromId !== undefined) {\r\n state.forkedChildWaitingForTurnContext = true;\r\n state.forkedChildInheritedBaseline = undefined;\r\n state.forkedChildInheritedReportedTotal = undefined;\r\n }\r\n const provider = nonEmptyString(payload.model_provider);\r\n if (provider !== undefined) state.sessionProvider = provider;\r\n const nickname = nonEmptyString(payload.agent_nickname);\r\n if (nickname !== undefined) state.sessionAgent = nickname;\r\n if (typeof payload.cwd === \"string\") {\r\n const ws = workspaceFromCwd(payload.cwd);\r\n state.sessionWorkspaceKey = ws.key;\r\n state.sessionWorkspaceLabel = ws.label;\r\n }\r\n continue;\r\n }\r\n\r\n // ── turn_context: sets the current model for subsequent token rows. When\r\n // it resolves a model, flush any buffered model-less rows onto it. ──\r\n if (entryType === \"turn_context\") {\r\n state.currentModel = extractModel(payload);\r\n if (state.currentModel !== undefined) {\r\n flushPending(pending, out, state.currentModel);\r\n }\r\n continue;\r\n }\r\n\r\n if (!isTokenCount) continue;\r\n\r\n const info = payload.info;\r\n if (info === undefined || info === null) continue;\r\n\r\n // Resolve model: payload model > info model > current session model.\r\n const payloadModel = extractModel(payload);\r\n const infoModel = extractModelFromInfo(info);\r\n const model = payloadModel ?? infoModel ?? state.currentModel;\r\n if (model !== undefined) {\r\n state.currentModel = model;\r\n // A resolved model back-fills any earlier model-less rows (codex.rs flushes\r\n // pending_model_messages here before building the current record).\r\n flushPending(pending, out, model);\r\n }\r\n\r\n const totalUsageRaw = info.total_token_usage ?? undefined;\r\n const lastUsageRaw = info.last_token_usage ?? undefined;\r\n const totalUsage = totalUsageRaw ? totalsFromUsage(totalUsageRaw) : undefined;\r\n const lastUsage = lastUsageRaw ? totalsFromUsage(lastUsageRaw) : undefined;\r\n\r\n // Forked child may replay >1 parent token row after the first turn_context.\r\n if (forkedChildShouldSkipInheritedSnapshot(state, totalUsageRaw, totalUsage)) {\r\n continue;\r\n }\r\n state.forkedChildInheritedBaseline = undefined;\r\n state.forkedChildInheritedReportedTotal = undefined;\r\n\r\n // ── Delta selection (exact port of the Rust match arms). ──\r\n let tokensTotals: CodexTotals | undefined;\r\n let nextTotals: CodexTotals | undefined;\r\n const previous = state.previousTotals;\r\n\r\n if (totalUsage !== undefined && lastUsage !== undefined && previous !== undefined) {\r\n // Both present with previous baseline (standard path).\r\n if (totalsEqual(totalUsage, previous)) continue;\r\n if (deltaFrom(totalUsage, previous) === null && looksLikeStaleRegression(totalUsage, previous, lastUsage)) {\r\n continue;\r\n }\r\n tokensTotals = lastUsage;\r\n nextTotals = totalUsage;\r\n } else if (totalUsage !== undefined && lastUsage !== undefined && previous === undefined) {\r\n // Both present, first event — use last (not full total).\r\n tokensTotals = lastUsage;\r\n nextTotals = totalUsage;\r\n } else if (totalUsage !== undefined && lastUsage === undefined && previous !== undefined) {\r\n // Only total, have previous (defensive).\r\n if (totalsEqual(totalUsage, previous)) continue;\r\n const delta = deltaFrom(totalUsage, previous);\r\n if (delta !== null) {\r\n tokensTotals = delta;\r\n nextTotals = totalUsage;\r\n } else {\r\n state.previousTotals = totalUsage;\r\n continue;\r\n }\r\n } else if (totalUsage !== undefined && lastUsage === undefined && previous === undefined) {\r\n // Only total, first event, no last — legacy/degraded path.\r\n tokensTotals = totalUsage;\r\n nextTotals = totalUsage;\r\n } else if (totalUsage === undefined && lastUsage !== undefined && previous !== undefined) {\r\n // Only last, have previous.\r\n tokensTotals = lastUsage;\r\n nextTotals = saturatingAdd(previous, lastUsage);\r\n } else if (totalUsage === undefined && lastUsage !== undefined && previous === undefined) {\r\n // Only last, no previous.\r\n tokensTotals = lastUsage;\r\n nextTotals = undefined;\r\n } else {\r\n // Neither.\r\n continue;\r\n }\r\n\r\n const tokens = intoTokens(tokensTotals);\r\n\r\n // Skip zero-token snapshots WITHOUT advancing the baseline, so post-compaction\r\n // zeros don't inflate later deltas.\r\n if (tokensAllZero(tokens)) continue;\r\n\r\n state.previousTotals = nextTotals;\r\n\r\n const parsedTs = parseEntryTimestamp(entry.timestamp);\r\n const ts = parsedTs ?? fallbackTs;\r\n\r\n const modelId = model ?? DEFAULT_MODEL;\r\n const providerId = state.sessionProvider ?? inferProvider(modelId) ?? DEFAULT_PROVIDER;\r\n const agent = state.sessionIsHeadless ? \"headless\" : state.sessionAgent;\r\n\r\n const record: UsageRecord = {\r\n platformId: PLATFORM_ID,\r\n modelId,\r\n providerId,\r\n sessionId,\r\n tokens,\r\n ts,\r\n messageCount: 1,\r\n confidence: \"host-reported\",\r\n };\r\n if (state.sessionWorkspaceKey !== undefined) record.projectKey = state.sessionWorkspaceKey;\r\n if (state.sessionWorkspaceLabel !== undefined) record.projectLabel = state.sessionWorkspaceLabel;\r\n if (agent !== undefined) record.agent = agent;\r\n\r\n if (model === undefined) {\r\n // Model not yet resolved: buffer the record and defer modelId + dedupKey\r\n // until a later turn resolves the model (codex.rs pending_model_messages).\r\n // At EOF it flushes as \"unknown\" but STILL with a dedup key when the row\r\n // carried a real timestamp — so it can dedup against cross-source overlap.\r\n pending.push({\r\n record,\r\n tokens,\r\n providerId,\r\n ts,\r\n usedFallbackTimestamp: parsedTs === null,\r\n });\r\n continue;\r\n }\r\n\r\n // Dedup key only when a real timestamp was parsed (mtime fallback skips it,\r\n // matching codex.rs which sets the key only when parsed_timestamp.is_some()).\r\n if (parsedTs !== null) {\r\n record.dedupKey = codexDedupKey(ts, providerId, model, tokens);\r\n }\r\n out.push(record);\r\n }\r\n\r\n // EOF: any token_count rows whose model never resolved are emitted as\r\n // \"unknown\" — keeping a dedup key when their timestamp was real (codex.rs\r\n // flush_pending_model_messages_as_unknown at end of file).\r\n flushPendingAsUnknown(pending, out);\r\n\r\n return out;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Reader\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** The Codex CLI usage reader singleton. */\r\nconst codexReader: UsageReader = {\r\n platformId: PLATFORM_ID,\r\n kind: \"local\",\r\n async read({ sinceMs }: { sinceMs?: number }): Promise<UsageRecord[]> {\r\n const root = firstExistingRoot(PLATFORM_ID);\r\n if (root === undefined) return []; // no ~/.codex/sessions → fail-open\r\n\r\n // ~/.codex/sessions/**/*.jsonl (+ *.json headless). rollout-*.jsonl is a\r\n // subset of *.jsonl and is matched by the same predicate.\r\n const files = walkFiles(root, (name) => name.endsWith(\".jsonl\") || name.endsWith(\".json\"));\r\n\r\n const records: UsageRecord[] = [];\r\n for (const file of files) {\r\n const rows = parseCodexFile(file);\r\n for (const row of rows) {\r\n if (sinceMs !== undefined && row.ts < sinceMs) continue;\r\n records.push(row);\r\n }\r\n }\r\n return records;\r\n },\r\n};\r\n\r\nexport default codexReader;\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/codex/index.ts"],"sourcesContent":["/**\r\n * adapters/codex — Codex CLI platform adapter for agent-connector.\r\n *\r\n * Codex CLI hook paradigm is \"json-stdio\": the host pipes a JSON payload to a\r\n * command on stdin and reads JSON/exit-code back — the same wire protocol as\r\n * Claude Code (PascalCase fields, `hookSpecificOutput` reply wrapper).\r\n *\r\n * Two native config files live under the Codex config dir\r\n * (`$CODEX_HOME` || `~/.codex`, mirrored to `<projectDir>/.codex` for project\r\n * scope):\r\n * - config.toml → `[mcp_servers.<id>]` MCP registration (TOML, NO native\r\n * interpolation, so env-refs are resolved to literals at install time).\r\n * - hooks.json → Claude-compatible hook registration ({ matcher, hooks }).\r\n *\r\n * Grounded in context-mode's proven Codex adapter (configs/codex/{config.toml,\r\n * hooks.json}, src/adapters/codex/*) — exact TOML MCP shape + hook JSON schema.\r\n *\r\n * Codex capabilities (upstream, verified against openai/codex source at the\r\n * stable release tags noted):\r\n * - PreToolUse `updatedInput` rewrite IS honored (PR #20527, commit d08906a9,\r\n * stable since codex 0.131.0; applied in the shell/mcp/apply_patch tool\r\n * handlers, confirmed present through 0.141.0) — hence canModifyArgs is now\r\n * TRUE. Codex's output_parser.rs requires the rewrite to be paired with\r\n * `permissionDecision:\"allow\"` (an allow WITHOUT updatedInput, and an\r\n * updatedInput WITHOUT allow, are both rejected as invalid), so \"modify\"\r\n * emits the allow+updatedInput envelope together. The still-open tracking\r\n * issue openai/codex#18491 is now scoped to a NARROWER gap — read_file/grep\r\n * have no PreToolUse handler yet — not to updatedInput itself, which works\r\n * for every tool that fires PreToolUse (shell/Bash, apply_patch, MCP).\r\n * - PostToolUse `updatedMCPToolOutput` is still explicitly rejected as\r\n * \"unsupported\" by output_parser.rs (no output-rewrite field on\r\n * PostToolUseOutput at 0.141.0) — hence canModifyOutput stays FALSE.\r\n *\r\n * E1 extension events (verified against developers.openai.com/codex/hooks):\r\n * - PermissionRequest — native, decision-capable via the nested\r\n * hookSpecificOutput.decision{behavior:\"allow\"|\"deny\", message?} envelope.\r\n * Codex docs: updatedInput / updatedPermissions / interrupt FAIL CLOSED on\r\n * this event, so they are never emitted here.\r\n * - SubagentStart — native; hookSpecificOutput.additionalContext is injected\r\n * as developer context for the subagent (not blockable).\r\n * - SubagentStop — native; the documented continuation shape is the TOP-LEVEL\r\n * {\"decision\":\"block\",\"reason\"} (Stop semantics: keeps the subagent going).\r\n * - PostToolUseFailure — NO Codex analog (PostToolUse only); declared hooks\r\n * for it warn-skip at install and the capability flag stays unset.\r\n * - PostCompact — native (Codex's hook system fires both PreCompact and\r\n * PostCompact); observe-only, normalizing the `trigger` (manual|auto)\r\n * exactly like PreCompact, with a passthrough formatReply.\r\n */\r\n\r\nimport { existsSync, readFileSync, writeFileSync } from \"node:fs\";\r\nimport { homedir } from \"node:os\";\r\nimport { dirname, join } from \"node:path\";\r\n\r\nimport TOML from \"@iarna/toml\";\r\n\r\nimport type {\r\n ChangeRecord,\r\n DetectedPlatform,\r\n HealthCheck,\r\n HookEventName,\r\n HookParadigm,\r\n HookResponse,\r\n PlatformCapabilities,\r\n PlatformId,\r\n ServerDef,\r\n SkillDef,\r\n SubagentDef,\r\n} from \"../../core/types.js\";\r\nimport { ensureDir } from \"../../core/paths.js\";\r\nimport { codexConfigHome } from \"../../core/host-paths.js\";\r\nimport { resolveEnvRefsDeep } from \"../../core/interpolate.js\";\r\nimport {\r\n removeFromObjectMap,\r\n upsertInObjectMap,\r\n type ObjectMapCodec,\r\n} from \"../../core/object-map.js\";\r\nimport { writeTomlString } from \"../../core/toml.js\";\r\nimport {\r\n buildHomeBinHookCommand,\r\n buildWrappedStdio,\r\n} from \"../../core/spawn.js\";\r\nimport { renderCommandMd, renderSkillMd } from \"../claude-code/render.js\";\r\nimport { normalizeSessionSource } from \"../claude-code/wire.js\";\r\nimport { BaseAdapter, type HookMergeDescriptor } from \"../base.js\";\r\nimport type {\r\n HookReply,\r\n InstallContext,\r\n MemoryTarget,\r\n NormalizedEvent,\r\n} from \"../spi.js\";\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Native shapes\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\n/** Raw Codex hook payload (PascalCase event, snake_case fields — Claude-style). */\r\ninterface CodexHookInput {\r\n tool_name?: string;\r\n tool_input?: Record<string, unknown>;\r\n // PostToolUse only. The host serializes this as serde_json::Value (any JSON):\r\n // a BARE STRING for shell/apply_patch (e.g. json!(\"shell output\")) but an\r\n // OBJECT for MCP/structured tools (the serialized CallToolResult, e.g.\r\n // json!({content,structuredContent,isError})) — NOT always a string. Typed\r\n // `unknown` so PostToolUse coerces it for the string-typed toolOutput.\r\n // Primary source: openai/codex codex-rs/hooks/src/schema.rs PostToolUseCommandInput\r\n // `tool_response: Value` + core/src/tools/handlers/{mcp.rs object, shell_tests.rs string}.\r\n tool_response?: unknown;\r\n session_id?: string;\r\n cwd?: string;\r\n hook_event_name?: string;\r\n source?: string;\r\n prompt?: string;\r\n // NO is_error: Codex's PostToolUseCommandInput struct (#[serde(deny_unknown_fields)])\r\n // never serializes a top-level is_error — the error signal for MCP tools lives\r\n // INSIDE tool_response as the CallToolResult `isError`. The field was removed;\r\n // see derivePostToolUseIsError below. (openai/codex codex-rs/hooks/src/schema.rs:317-337)\r\n stop_hook_active?: boolean;\r\n trigger?: string;\r\n message?: string;\r\n // PostToolUseFailure-style failure field. Codex has NO failure event today;\r\n // parsed defensively only (the Claude-compatible wire would carry it).\r\n error?: string;\r\n // SubagentStart / SubagentStop (agent_type is the matcher subject).\r\n agent_id?: string;\r\n agent_type?: string;\r\n // SubagentStop only — the subagent's own transcript + final message.\r\n agent_transcript_path?: string;\r\n last_assistant_message?: string;\r\n}\r\n\r\n/** One hook entry inside hooks.json (Claude-compatible). */\r\ninterface CodexHookEntry {\r\n matcher?: string;\r\n hooks: Array<{ type: \"command\"; command: string }>;\r\n}\r\n\r\n/** Rendered `[mcp_servers.<id>]` table — string env table, no interpolation. */\r\ninterface CodexMcpEntry {\r\n // stdio transport\r\n command?: string;\r\n args?: string[];\r\n env?: Record<string, string>;\r\n // streamable HTTP transport (remote): codex infers the transport from `url`\r\n // (no explicit transport key). Verified against codex-cli 0.139.0.\r\n url?: string;\r\n bearer_token_env_var?: string;\r\n http_headers?: Record<string, string>;\r\n}\r\n\r\n/**\r\n * Codex hook events agent-connector registers, in the canonical → native order.\r\n * Codex uses the same PascalCase event names as Claude Code; the home-binary\r\n * hook command receives the lowercased event token.\r\n */\r\nconst CODEX_HOOK_EVENTS = [\r\n \"SessionStart\",\r\n \"PreToolUse\",\r\n \"PostToolUse\",\r\n \"PreCompact\",\r\n \"UserPromptSubmit\",\r\n \"Stop\",\r\n \"PermissionRequest\",\r\n \"SubagentStart\",\r\n \"SubagentStop\",\r\n \"PostCompact\",\r\n] as const;\r\n\r\ntype CodexHookEventName = (typeof CODEX_HOOK_EVENTS)[number];\r\n\r\n/**\r\n * Newer E1 canonical events with NO Codex analog: Codex ships PostToolUse only —\r\n * there is no failure event on the live hooks page. Declared hooks for these\r\n * warn-skip (action `warn`, exit-1) — the established convention. The legacy\r\n * SessionEnd / Notification, which Codex also cannot fire, are reported as a\r\n * VISIBLE `skip` instead (exit-0 preserving) — see the hook descriptor's\r\n * `unmappedAction`. Nothing Codex cannot fire is ever silently dropped.\r\n */\r\nconst WARN_SKIP_EVENTS: ReadonlySet<HookEventName> = new Set([\"PostToolUseFailure\"]);\r\n\r\n/**\r\n * PreToolUse matcher — canonical Codex tool names + bare MCP tool names +\r\n * external MCP catch-all literal. Charset-clean ([A-Za-z0-9_|] only) so Codex's\r\n * Rust `regex` exact-matcher short-circuits (no look-around, which Codex\r\n * rejects at boot). Copied from context-mode's proven matcher.\r\n */\r\nconst PRE_TOOL_USE_MATCHER =\r\n \"local_shell|shell|shell_command|exec_command|Bash|Shell|apply_patch|Edit|Write|grep_files|mcp__\";\r\n\r\n/**\r\n * Coerce Codex's PostToolUse `tool_response` (serde_json::Value — bare string\r\n * for shell/apply_patch, OBJECT for MCP/structured tools) to a string for the\r\n * string-typed `toolOutput`. A string passes through verbatim; everything else\r\n * (object/array/number/bool) is JSON-stringified; undefined/null → undefined\r\n * (leave `toolOutput` unset).\r\n *\r\n * Source: openai/codex codex-rs/hooks/src/schema.rs PostToolUseCommandInput\r\n * `tool_response: Value`; core/src/tools/handlers/shell_tests.rs emits\r\n * `json!(\"shell output\")` (string), mcp.rs emits `json!({...})` (object).\r\n */\r\nfunction coerceToolResponse(value: unknown): string | undefined {\r\n if (value === undefined || value === null) return undefined;\r\n if (typeof value === \"string\") return value;\r\n try {\r\n return JSON.stringify(value);\r\n } catch {\r\n return String(value);\r\n }\r\n}\r\n\r\n/**\r\n * Derive PostToolUse `isError`. Codex's PostToolUseCommandInput\r\n * (`#[serde(deny_unknown_fields)]`) has NO top-level is_error field, so the only\r\n * machine-readable error signal is the MCP CallToolResult `isError` nested in\r\n * the `tool_response` object (serialized camelCase by rmcp). For shell/\r\n * apply_patch tool_response is a bare string carrying no boolean, so we report\r\n * false. Returns false when no such signal exists (never invents one).\r\n *\r\n * Source: openai/codex codex-rs/hooks/src/schema.rs:317-337 (no is_error field);\r\n * codex-rs/core/src/tools/handlers/mcp.rs (tool_response = serialized\r\n * CallToolResult → `isError` when the MCP call failed).\r\n */\r\nfunction derivePostToolUseIsError(toolResponse: unknown): boolean {\r\n if (toolResponse !== null && typeof toolResponse === \"object\") {\r\n const flag = (toolResponse as Record<string, unknown>).isError;\r\n if (typeof flag === \"boolean\") return flag;\r\n }\r\n return false;\r\n}\r\n\r\n// ─────────────────────────────────────────────────────────────────────────\r\n// Adapter\r\n// ─────────────────────────────────────────────────────────────────────────\r\n\r\nexport class CodexAdapter extends BaseAdapter {\r\n readonly id: PlatformId = \"codex\";\r\n readonly name = \"Codex CLI\";\r\n readonly paradigm: HookParadigm = \"json-stdio\";\r\n\r\n readonly capabilities: PlatformCapabilities = {\r\n // Memory surface: AGENTS.md-first managed block. memoryTargets below probes\r\n // AGENTS.override.md first (it shadows AGENTS.md per directory on codex).\r\n supportsMemory: true,\r\n preToolUse: true,\r\n postToolUse: true,\r\n preCompact: true,\r\n sessionStart: true,\r\n sessionEnd: false,\r\n userPromptSubmit: true,\r\n stop: true,\r\n notification: false,\r\n // E1 events: PermissionRequest (decision-capable) + SubagentStart/Stop are\r\n // Codex-native. postToolUseFailure stays unset — Codex has no failure event,\r\n // so a declared hook for it warn-skips at install.\r\n permissionRequest: true,\r\n subagentStart: true,\r\n subagentStop: true,\r\n // PostCompact: Codex's hook system fires both PreCompact and PostCompact\r\n // (developers.openai.com/codex/hooks). Observational only — the reply\r\n // contract mirrors PreCompact (cannot block/modify a completed compaction).\r\n postCompact: true,\r\n // PreToolUse updatedInput rewrite is honored upstream (paired with\r\n // permissionDecision:\"allow\"); PostToolUse output rewrite is not (see header).\r\n canModifyArgs: true,\r\n canModifyOutput: false,\r\n canInjectSessionContext: true,\r\n transports: [\"stdio\", \"http\"],\r\n // Content surfaces: Codex implements all three.\r\n // command → ~/.codex/prompts/<name>.md (md+frontmatter, USER SCOPE ONLY)\r\n // skill → project: .codex/skills/<name>/SKILL.md · user: ~/.agents/skills/<name>/SKILL.md\r\n // subagent → <codexDir>/agents/<name>.toml (TOML)\r\n supportsCommands: true,\r\n supportsSkills: true,\r\n supportsSubagents: true,\r\n };\r\n\r\n // ── Detection ──────────────────────────────────────────────────────────\r\n\r\n detectInstalled(projectDir: string): DetectedPlatform {\r\n const userDir = this.userConfigDir();\r\n const projDir = join(projectDir, \".codex\");\r\n const userCfg = join(userDir, \"config.toml\");\r\n const projCfg = join(projDir, \"config.toml\");\r\n\r\n const userInstalled = existsSync(userDir) || existsSync(userCfg);\r\n const projInstalled = existsSync(projDir) || existsSync(projCfg);\r\n const installed = userInstalled || projInstalled;\r\n const scope = projInstalled && !userInstalled ? \"project\" : \"user\";\r\n const configPath = scope === \"project\" ? projCfg : userCfg;\r\n\r\n return {\r\n id: this.id,\r\n name: this.name,\r\n installed,\r\n paradigm: this.paradigm,\r\n capabilities: this.capabilities,\r\n configPath,\r\n scope,\r\n reason: installed\r\n ? `Found Codex config dir (${scope})`\r\n : `No .codex config dir at ${userDir} or ${projDir}`,\r\n confidence: installed ? \"high\" : \"low\",\r\n };\r\n }\r\n\r\n // ── Native paths ───────────────────────────────────────────────────────\r\n\r\n override getConfigDir(ctx: InstallContext): string {\r\n if (ctx.scope === \"project\") return join(ctx.projectDir, \".codex\");\r\n return this.userConfigDir();\r\n }\r\n\r\n override getServerConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"config.toml\");\r\n }\r\n\r\n override getHookConfigPath(ctx: InstallContext): string {\r\n return join(this.getConfigDir(ctx), \"hooks.json\");\r\n }\r\n\r\n // ── Memory surface: AGENTS.override.md probe + 32 KiB doc-cap budget ─────\r\n // Codex reads AGENTS.override.md > AGENTS.md per directory (one file per\r\n // directory), so when the override file exists OUR block must live there or\r\n // it is never loaded. Combined project docs are capped at 32 KiB\r\n // (`project_doc_max_bytes`), hence the ~28 KiB per-file budget warn.\r\n protected override memoryTargets(ctx: InstallContext): MemoryTarget[] {\r\n // An explicit path override keeps the base resolution (escape hatch wins).\r\n if (this.memoryOverride(ctx)?.path) return super.memoryTargets(ctx);\r\n if (ctx.scope !== \"project\" && ctx.scope !== \"user\") return [];\r\n const budgetBytes = 28 * 1024;\r\n const dir = ctx.scope === \"project\" ? ctx.projectDir : this.userConfigDir();\r\n const overrideMd = join(dir, \"AGENTS.override.md\");\r\n if (existsSync(overrideMd)) {\r\n return [\r\n {\r\n path: overrideMd,\r\n reason: \"AGENTS.override.md shadows AGENTS.md on codex (one doc per directory)\",\r\n budgetBytes,\r\n },\r\n ];\r\n }\r\n return [\r\n {\r\n path: join(dir, \"AGENTS.md\"),\r\n reason:\r\n ctx.scope === \"project\"\r\n ? \"AGENTS.md standard (project root; codex is the format's originator)\"\r\n : \"codex global guidance ($CODEX_HOME/AGENTS.md)\",\r\n budgetBytes,\r\n },\r\n ];\r\n }\r\n\r\n /** `$CODEX_HOME` (tilde-expanded, then resolved) || `~/.codex` for user\r\n * scope. Shared with marketplace detection via `codexConfigHome` so the\r\n * config writer and the install probe never target different dirs. */\r\n private userConfigDir(): string {\r\n return codexConfigHome();\r\n }\r\n\r\n // ── TOML config IO (override JSON helpers — config.toml is TOML) ─────────\r\n\r\n private readToml(path: string): Record<string, unknown> {\r\n if (!existsSync(path)) return {};\r\n try {\r\n return TOML.parse(readFileSync(path, \"utf8\")) as Record<string, unknown>;\r\n } catch {\r\n return {};\r\n }\r\n }\r\n\r\n private writeToml(path: string, data: Record<string, unknown>, dryRun: boolean): void {\r\n if (dryRun) return;\r\n ensureDir(dirname(path));\r\n // @iarna/toml's stringify type wants its JsonMap; our object is structurally compatible.\r\n writeFileSync(path, TOML.stringify(data as never), \"utf8\");\r\n }\r\n\r\n /** An ObjectMapCodec over config.toml for the core/object-map engine.\r\n * `isPresentButUnparseable` is `() => false`: readToml fail-softs to {} and the\r\n * server path has historically coerced/overwritten rather than warn-skip on an\r\n * unparseable file — preserved here for byte-identical behavior. */\r\n private tomlObjectMapCodec(): ObjectMapCodec {\r\n return {\r\n parse: (path) => this.readToml(path),\r\n serialize: (path, data, dryRun) => this.writeToml(path, data, dryRun),\r\n isPresentButUnparseable: () => false,\r\n };\r\n }\r\n\r\n // ── Install server (config.toml → [mcp_servers.<id>]) ───────────────────\r\n\r\n override installServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector, dryRun } = ctx;\r\n const server = this.effectiveServer(ctx);\r\n const path = this.getServerConfigPath(ctx);\r\n\r\n if (!server) {\r\n return [{ platform: this.id, action: \"skip\", path, detail: \"no server declared\" }];\r\n }\r\n const isStdio = server.transport === \"stdio\" && !!server.command;\r\n const isHttp = server.transport === \"http\" && !!server.url;\r\n if (!isStdio && !isHttp) {\r\n // Codex config.toml [mcp_servers] supports stdio (command) + streamable\r\n // HTTP (url). Other remote transports (sse/ws) have no codex analog.\r\n return [\r\n {\r\n platform: this.id,\r\n action: \"skip\",\r\n path,\r\n detail: `transport \"${server.transport}\" not registrable in config.toml (stdio + streamable-http only)`,\r\n },\r\n ];\r\n }\r\n\r\n const symlink = this.symlinkPathWarning(path);\r\n if (symlink) return [symlink];\r\n\r\n const entry = this.renderMcpEntry(ctx, server);\r\n\r\n return [\r\n upsertInObjectMap({\r\n codec: this.tomlObjectMapCodec(),\r\n rootKey: \"mcp_servers\",\r\n policy: \"coerce\",\r\n platform: this.id,\r\n configPath: path,\r\n entryId: connector.id,\r\n entry,\r\n dryRun,\r\n }),\r\n ];\r\n }\r\n\r\n override uninstallServer(ctx: InstallContext): ChangeRecord[] {\r\n const { connector, dryRun } = ctx;\r\n const path = this.getServerConfigPath(ctx);\r\n const symlink = this.symlinkPathWarning(path);\r\n if (symlink) return [symlink];\r\n\r\n return [\r\n removeFromObjectMap({\r\n codec: this.tomlObjectMapCodec(),\r\n rootKey: \"mcp_servers\",\r\n policy: \"coerce\",\r\n platform: this.id,\r\n configPath: path,\r\n entryId: connector.id,\r\n dryRun,\r\n }),\r\n ];\r\n }\r\n\r\n // ── Install hooks (hooks.json) ──────────────────────────────────────────\r\n\r\n override installHooks(ctx: InstallContext): ChangeRecord[] {\r\n const path = this.getHookConfigPath(ctx);\r\n const hooksOff = ctx.connector.platforms[this.id]?.hooks === false;\r\n const declared = hooksOff ? [] : ctx.connector.hookEvents;\r\n\r\n if (declared.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", path, detail: \"no hooks declared\" }];\r\n }\r\n\r\n // HOST-ORDERED pending: the unsupported events (mapEvent → undefined →\r\n // warn/skip via the descriptor) FIRST, then the supported events in\r\n // CODEX_HOOK_EVENTS order. EVERY declared event is enqueued — an event with\r\n // no Codex analog is reported VISIBLY (warn for the E1 newer events, a `skip`\r\n // for the legacy SessionEnd/Notification whose drop predates the convention),\r\n // never silently dropped. matcher is \"\" for every item; renderEntry derives\r\n // the real matcher from the event (PreToolUse/PermissionRequest).\r\n const supported = (e: HookEventName) =>\r\n (CODEX_HOOK_EVENTS as readonly string[]).includes(e);\r\n const pending = [\r\n ...declared.filter((e) => !supported(e)).map((event) => ({ event: event as string, matcher: \"\" })),\r\n ...declared.filter(supported).map((event) => ({ event: event as string, matcher: \"\" })),\r\n ];\r\n return this.upsertHookEntries(ctx, path, pending, this.hookDescriptor(ctx));\r\n }\r\n\r\n override uninstallHooks(ctx: InstallContext): ChangeRecord[] {\r\n return this.removeHookEntries(ctx, this.getHookConfigPath(ctx), this.hookDescriptor(ctx));\r\n }\r\n\r\n /**\r\n * Codex hook-merge policy for the shared object-map engine. EVENT-SPECIFIC by\r\n * construction: every observable (coerce root + bucket, the path-normalized\r\n * per-event ownership find, the event-derived matcher with `hooks`-then-\r\n * `matcher` key order, the BARE `hooks.<event>` skip/remove details with NO\r\n * count, the warn wording, and the absent/no-match skips) is carried here so\r\n * the engine reproduces the prior in-adapter loop byte-for-byte.\r\n */\r\n private hookDescriptor(_ctx: InstallContext): HookMergeDescriptor<CodexHookEntry> {\r\n return {\r\n // Codex's server path coerces a malformed root; the hook path matches it.\r\n malformedPolicy: \"coerce\",\r\n // Supported event → identity; any other canonical event → undefined → the\r\n // engine reports it (never silent), at the severity unmappedAction picks.\r\n mapEvent: (e) =>\r\n (CODEX_HOOK_EVENTS as readonly string[]).includes(e) ? e : undefined,\r\n unmappedWarnDetail: (e) => `${e} has no Codex hook equivalent — skipped`,\r\n // E1 newer events (PostToolUseFailure) keep the established `warn` (exit-1);\r\n // the legacy SessionEnd / Notification — silently dropped before this fix —\r\n // become a VISIBLE `skip` so the install exit code is unchanged for them.\r\n unmappedAction: (e) =>\r\n WARN_SKIP_EVENTS.has(e as HookEventName) ? \"warn\" : \"skip\",\r\n renderEntry: (event, _matcher, command) => {\r\n const entry: CodexHookEntry = { hooks: [{ type: \"command\", command }] };\r\n // KEY ORDER: hooks THEN matcher. Matcher is EVENT-derived, not from the\r\n // connector's declared matcher: PermissionRequest matches tool names like\r\n // PreToolUse (charset-clean), everything else registers \"\" (all).\r\n entry.matcher =\r\n event === \"PreToolUse\" || event === \"PermissionRequest\" ? PRE_TOOL_USE_MATCHER : \"\";\r\n return entry;\r\n },\r\n // Idempotency find for the CANONICAL event the engine built `command` from —\r\n // path-normalized, exact-command, the body of isOurEntry's command check.\r\n entryOwnsCommand: (entry, command) =>\r\n Array.isArray(entry.hooks) &&\r\n entry.hooks.some(\r\n (h) => (h.command ?? \"\").replace(/\\\\/g, \"/\") === command.replace(/\\\\/g, \"/\"),\r\n ),\r\n // FLAT whole-entry removal, EVENT-SPECIFIC: isOurEntry rebuilds our command\r\n // from the event key being stripped, so a SubagentStop entry is never matched\r\n // while iterating the PreToolUse bucket.\r\n ownsEntryForRemove: (c, event) => (entry) =>\r\n this.isOurEntry(c, event as CodexHookEventName, entry),\r\n skipDetail: (e) => `hooks.${e}`,\r\n removeDetail: (e, _n) => `hooks.${e}`,\r\n absentDetail: \"no hooks.json\",\r\n noMatchDetail: \"no agent-connector hooks present\",\r\n // Uninstall scans EXACTLY codex's fixed event set (not Object.keys), so a\r\n // home-bin command hand-placed under a foreign event key is left untouched —\r\n // byte-identical to the prior `for (const event of CODEX_HOOK_EVENTS)` loop.\r\n removeEventKeys: CODEX_HOOK_EVENTS,\r\n };\r\n }\r\n\r\n // ── Health checks (default doctor renders these) ────────────────────────\r\n\r\n override getHealthChecks(ctx: InstallContext): readonly HealthCheck[] {\r\n const path = this.getServerConfigPath(ctx);\r\n const id = ctx.connector.id;\r\n const checks: HealthCheck[] = [\r\n {\r\n name: `${this.name}: config.toml exists`,\r\n check: () =>\r\n existsSync(path)\r\n ? { status: \"OK\", detail: path }\r\n : { status: \"FAIL\", detail: `not found: ${path}` },\r\n },\r\n {\r\n name: `${this.name}: mcp_servers.${id} registered`,\r\n check: () => {\r\n // Only assert what the connector declares (same rule as the\r\n // content-surface checks below): a server-less connector — e.g. a\r\n // catalog-only bundle of agents/skills/commands — never writes an\r\n // [mcp_servers.<id>] table, so its absence is healthy.\r\n if (!ctx.connector.server) {\r\n return { status: \"OK\", detail: \"no MCP server declared\" };\r\n }\r\n const cfg = this.readToml(path);\r\n const bucket = cfg[\"mcp_servers\"];\r\n const present =\r\n typeof bucket === \"object\" &&\r\n bucket !== null &&\r\n id in (bucket as Record<string, unknown>);\r\n return present\r\n ? { status: \"OK\", detail: `mcp_servers.${id}` }\r\n : { status: \"FAIL\", detail: `mcp_servers.${id} not found in ${path}` };\r\n },\r\n },\r\n ];\r\n\r\n // Content-surface checks: assert presence only for surfaces this connector\r\n // declares. Codex commands are user-scope only, so a project-scope install\r\n // won't have written them — only check command files in user scope.\r\n if (ctx.scope !== \"project\") {\r\n for (const cmd of ctx.connector.commands) {\r\n const p = this.commandPath(cmd.name);\r\n checks.push({\r\n name: `${this.name}: command ${cmd.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n }\r\n for (const skill of ctx.connector.skills) {\r\n const p = join(this.skillDir(ctx, skill.name), \"SKILL.md\");\r\n checks.push({\r\n name: `${this.name}: skill ${skill.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n for (const agent of ctx.connector.subagents) {\r\n const p = this.subagentPath(ctx, agent.name);\r\n checks.push({\r\n name: `${this.name}: subagent ${agent.name} present`,\r\n check: () =>\r\n existsSync(p) ? { status: \"OK\", detail: p } : { status: \"FAIL\", detail: `not found: ${p}` },\r\n });\r\n }\r\n return checks;\r\n }\r\n\r\n // ── Content surfaces: commands / skills / subagents ──────────────────────\r\n // CONTENT-ONLY: pure native-file writers. No runtime dispatch, no home-bin\r\n // pointer, no telemetry wrap. Each method is idempotent (byte-identical →\r\n // skip) via writeContentFile and reversible via removeContentFile. Honors\r\n // platforms[\"codex\"] per-surface false to skip.\r\n //\r\n // Native locations:\r\n // command → ~/.codex/prompts/<name>.md md+frontmatter(description,argument-hint)\r\n // USER SCOPE ONLY — project scope yields a single \"warn\".\r\n // skill → project: <projectDir>/.codex/skills/<name>/SKILL.md (+ resources)\r\n // user: ~/.agents/skills/<name>/SKILL.md (~/.codex/skills is deprecated)\r\n // subagent → <codexDir>/agents/<name>.toml TOML via writeTomlString\r\n\r\n /** Command files always live under the USER codex dir: ~/.codex/prompts. */\r\n private commandPath(name: string): string {\r\n return join(this.userConfigDir(), \"prompts\", `${name}.md`);\r\n }\r\n private skillDir(ctx: InstallContext, name: string): string {\r\n // Project scope: <projectDir>/.codex/skills/<name> — the Project config-layer\r\n // skills root (codex-rs/core-skills/src/loader.rs, ConfigLayerSource::Project),\r\n // NOT deprecated. User scope: $HOME/.agents/skills/<name> — codex's CURRENT\r\n // user skills root. The older $CODEX_HOME/skills (~/.codex/skills) is still\r\n // read but the loader labels it a \"Deprecated user skills location, kept for\r\n // backward compatibility\". .agents is anchored to the OS home (home_dir), NOT\r\n // $CODEX_HOME — so use homedir() here, never userConfigDir() (which honors\r\n // CODEX_HOME).\r\n if (ctx.scope === \"project\") return join(this.getConfigDir(ctx), \"skills\", name);\r\n return join(homedir(), \".agents\", \"skills\", name);\r\n }\r\n private subagentPath(ctx: InstallContext, name: string): string {\r\n return join(this.getConfigDir(ctx), \"agents\", `${name}.toml`);\r\n }\r\n\r\n // ── Commands (USER SCOPE ONLY) ───────────────────────────────────────────\r\n\r\n override installCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[this.id]?.commands === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"commands disabled for codex\" }];\r\n }\r\n if (ctx.scope === \"project\") {\r\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.writeContentFile(\r\n this.commandPath(cmd.name),\r\n renderCommandMd(cmd, { includeToolsAndModel: false }),\r\n ctx.dryRun,\r\n ),\r\n );\r\n }\r\n\r\n override uninstallCommands(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (ctx.scope === \"project\") {\r\n return [{ platform: this.id, action: \"warn\", detail: \"codex commands are user-scope only\" }];\r\n }\r\n if (connector.commands.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no commands\" }];\r\n }\r\n return connector.commands.map((cmd) =>\r\n this.removeContentFile(this.commandPath(cmd.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n // ── Skills ───────────────────────────────────────────────────────────────\r\n\r\n override installSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[this.id]?.skills === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"skills disabled for codex\" }];\r\n }\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n const rendered = renderSkillMd(skill);\r\n changes.push(this.writeContentFile(join(dir, \"SKILL.md\"), rendered, ctx.dryRun));\r\n // Bundle any resource files beside SKILL.md (relative path → contents).\r\n // Defense-in-depth: skip+warn on any key that escapes the skill dir\r\n // (config-time validation already rejects these, but never trust input).\r\n for (const [rel, contents] of Object.entries(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) {\r\n changes.push({\r\n platform: this.id,\r\n action: \"warn\",\r\n detail: `skill resource \"${rel}\" escapes the skill dir; skipped`,\r\n });\r\n continue;\r\n }\r\n changes.push(this.writeContentFile(target, contents, ctx.dryRun));\r\n }\r\n // Migrate away an AC-owned copy at the deprecated user skills root so the\r\n // skill is not double-registered after the move to ~/.agents/skills.\r\n changes.push(...this.migrateDeprecatedUserSkill(ctx, skill, rendered));\r\n }\r\n return changes;\r\n }\r\n\r\n /**\r\n * One-time, opt-out-safe migration: prior AC versions wrote user-scope skills\r\n * to the now-deprecated $CODEX_HOME/skills/<name> root, which codex STILL reads\r\n * (kept for backward compatibility). Once we write the same skill to the current\r\n * ~/.agents/skills root, codex would register it TWICE (same frontmatter name,\r\n * two User-scope roots). If a SKILL.md exists at the deprecated path AND is\r\n * byte-identical to what we render — i.e. AC-owned, not hand-authored — remove\r\n * it (and its now-empty dir). The content-equality guard guarantees we never\r\n * delete a skill a user placed there by hand. No-op for project scope (where\r\n * .codex/skills is the valid, non-deprecated Project config-layer path) and when\r\n * a custom CODEX_HOME would make the deprecated path coincide with the new one.\r\n */\r\n private migrateDeprecatedUserSkill(\r\n ctx: InstallContext,\r\n skill: SkillDef,\r\n rendered: string,\r\n ): ChangeRecord[] {\r\n if (ctx.scope === \"project\") return [];\r\n const deprecated = join(this.userConfigDir(), \"skills\", skill.name, \"SKILL.md\");\r\n // Never touch the file we just wrote (pathological CODEX_HOME === ~/.agents).\r\n if (deprecated === join(this.skillDir(ctx, skill.name), \"SKILL.md\")) return [];\r\n if (!existsSync(deprecated)) return [];\r\n if (readFileSync(deprecated, \"utf8\") !== rendered) return []; // hand-authored — leave it\r\n return [\r\n this.removeContentFile(deprecated, ctx.dryRun),\r\n this.removeDirIfEmpty(dirname(deprecated), ctx.dryRun),\r\n ];\r\n }\r\n\r\n override uninstallSkills(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.skills.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no skills\" }];\r\n }\r\n const changes: ChangeRecord[] = [];\r\n for (const skill of connector.skills) {\r\n const dir = this.skillDir(ctx, skill.name);\r\n // Remove only the files we wrote (SKILL.md + declared resources), then the\r\n // skill dir itself when we own its full contents.\r\n changes.push(this.removeContentFile(join(dir, \"SKILL.md\"), ctx.dryRun));\r\n for (const rel of Object.keys(skill.resources ?? {})) {\r\n const target = this.resolveWithin(dir, rel);\r\n if (target === null) continue; // never delete outside the skill dir\r\n changes.push(this.removeContentFile(target, ctx.dryRun));\r\n }\r\n // Only remove the skill dir when WE own its full contents — never rm -rf a\r\n // dir that still holds user-added / sibling-tool / shared files.\r\n changes.push(this.removeDirIfEmpty(dir, ctx.dryRun));\r\n }\r\n return changes;\r\n }\r\n\r\n // ── Subagents (TOML) ─────────────────────────────────────────────────────\r\n\r\n override installSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.platforms[this.id]?.subagents === false) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"subagents disabled for codex\" }];\r\n }\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.writeContentFile(this.subagentPath(ctx, agent.name), this.renderSubagent(agent), ctx.dryRun),\r\n );\r\n }\r\n\r\n override uninstallSubagents(ctx: InstallContext): ChangeRecord[] {\r\n const { connector } = ctx;\r\n if (connector.subagents.length === 0) {\r\n return [{ platform: this.id, action: \"skip\", detail: \"connector declares no subagents\" }];\r\n }\r\n return connector.subagents.map((agent) =>\r\n this.removeContentFile(this.subagentPath(ctx, agent.name), ctx.dryRun),\r\n );\r\n }\r\n\r\n /**\r\n * Render a subagent to a Codex agent TOML file:\r\n * { name, description, developer_instructions: prompt, model }.\r\n * model is omitted when undefined so Codex applies its default.\r\n *\r\n * Codex custom agent files are config layers, not a closed four-field\r\n * manifest. The Codex manual documents required custom-agent keys, plus\r\n * optional config keys such as nickname_candidates, model_reasoning_effort,\r\n * sandbox_mode, mcp_servers, and skills.config. Keep `extra` as the\r\n * author-controlled escape hatch for that native surface.\r\n */\r\n private renderSubagent(agent: SubagentDef): string {\r\n const table: Record<string, unknown> = {\r\n name: agent.name,\r\n description: agent.description,\r\n developer_instructions: agent.prompt,\r\n };\r\n if (agent.model !== undefined) table.model = agent.model;\r\n if (agent.extra) Object.assign(table, agent.extra);\r\n return writeTomlString(table);\r\n }\r\n\r\n // ── Runtime dispatch ────────────────────────────────────────────────────\r\n\r\n parseEvent(event: HookEventName, raw: unknown): NormalizedEvent {\r\n const input = (raw ?? {}) as CodexHookInput;\r\n const base = {\r\n hostPlatform: this.id,\r\n connectorId: \"\",\r\n sessionId: input.session_id ?? `pid-${process.ppid}`,\r\n projectDir: input.cwd ?? process.env.CODEX_PROJECT_DIR ?? process.cwd(),\r\n raw,\r\n };\r\n\r\n switch (event) {\r\n case \"PreToolUse\":\r\n return {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n case \"PostToolUse\":\r\n return {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n // tool_response is a bare string for shell/apply_patch but an OBJECT\r\n // for MCP tools — coerce non-strings to JSON so the string-typed\r\n // toolOutput never receives a raw object.\r\n toolOutput: coerceToolResponse(input.tool_response),\r\n // Codex never serializes a top-level is_error (deny_unknown_fields);\r\n // the true error signal is the CallToolResult.isError nested inside\r\n // tool_response for MCP tools. Derive it from there.\r\n isError: derivePostToolUseIsError(input.tool_response),\r\n };\r\n case \"SessionStart\":\r\n return { ...base, source: normalizeSessionSource(input.source) };\r\n case \"SessionEnd\":\r\n return { ...base, reason: input.message };\r\n case \"UserPromptSubmit\":\r\n return { ...base, prompt: input.prompt ?? \"\" };\r\n case \"PreCompact\":\r\n return { ...base, trigger: input.trigger === \"manual\" ? \"manual\" : \"auto\" };\r\n case \"PostCompact\":\r\n // Post-compaction sibling of PreCompact — same `trigger` normalization\r\n // (manual|auto), observe-only. Codex's PostCompact payload mirrors\r\n // PreCompact's; everything else rides on `raw`.\r\n return { ...base, trigger: input.trigger === \"manual\" ? \"manual\" : \"auto\" };\r\n case \"Stop\":\r\n return { ...base, stopHookActive: input.stop_hook_active ?? false };\r\n case \"Notification\":\r\n return { ...base, message: input.message ?? \"\" };\r\n case \"PermissionRequest\":\r\n // Codex documents tool_name/tool_input (+tool_input.description); it has\r\n // no permission_suggestions field, so the normalized optional stays unset.\r\n return {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n };\r\n case \"PostToolUseFailure\":\r\n // No Codex analog — never fired natively. Parsed defensively (Claude-\r\n // compatible wire) so a manual `hook codex PostToolUseFailure` invocation\r\n // still normalizes instead of throwing.\r\n return {\r\n ...base,\r\n toolName: input.tool_name ?? \"\",\r\n toolInput: input.tool_input ?? {},\r\n error: input.error ?? \"\",\r\n };\r\n case \"SubagentStart\":\r\n return {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\r\n };\r\n case \"SubagentStop\":\r\n // agent_id/agent_type stay optional — never depend on hosts populating\r\n // them on stop (the Claude-family SDK quirk).\r\n return {\r\n ...base,\r\n ...(typeof input.agent_id === \"string\" ? { agentId: input.agent_id } : {}),\r\n ...(typeof input.agent_type === \"string\" ? { agentType: input.agent_type } : {}),\r\n ...(typeof input.agent_transcript_path === \"string\"\r\n ? { agentTranscriptPath: input.agent_transcript_path }\r\n : {}),\r\n ...(typeof input.last_assistant_message === \"string\"\r\n ? { lastAssistantMessage: input.last_assistant_message }\r\n : {}),\r\n ...(typeof input.stop_hook_active === \"boolean\"\r\n ? { stopHookActive: input.stop_hook_active }\r\n : {}),\r\n };\r\n }\r\n }\r\n\r\n formatReply(event: HookEventName, response: HookResponse): HookReply {\r\n // Codex (like Claude Code) reads a `hookSpecificOutput` JSON wrapper from\r\n // stdout; exit code 0 = allow. Fields the host cannot honor are dropped.\r\n\r\n // PermissionRequest uses Codex's nested decision{behavior} envelope and is\r\n // the ONE event where an EXPLICIT \"allow\" is an ACTIVE grant (suppresses the\r\n // approval prompt). ask/context/void → NO decision output: fall through to\r\n // the normal approval flow (the prompt IS the ask). Codex docs: updatedInput\r\n // / updatedPermissions / interrupt FAIL CLOSED on this event, so \"modify\"\r\n // also falls through — emitting a bare allow would grant the ORIGINAL input\r\n // the handler wanted rewritten.\r\n if (event === \"PermissionRequest\") {\r\n if (response.decision === \"deny\") {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"PermissionRequest\",\r\n decision: {\r\n behavior: \"deny\",\r\n message: response.reason ?? \"Blocked by hook\",\r\n },\r\n },\r\n }),\r\n };\r\n }\r\n if (response.decision === \"allow\") {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"PermissionRequest\",\r\n decision: { behavior: \"allow\" },\r\n },\r\n }),\r\n };\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // SubagentStart is observe/context-only on Codex (continue:false is parsed\r\n // but does not stop the subagent): \"context\" injects additionalContext as\r\n // developer context for the SUBAGENT, and a \"deny\" DEGRADES to the same\r\n // shape carrying the reason.\r\n if (event === \"SubagentStart\") {\r\n const context =\r\n response.decision === \"context\"\r\n ? response.additionalContext\r\n : response.decision === \"deny\"\r\n ? response.reason ?? response.additionalContext\r\n : undefined;\r\n if (context) {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"SubagentStart\",\r\n additionalContext: context,\r\n },\r\n }),\r\n };\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n if (response.decision === \"deny\") {\r\n // PreToolUse deny is honored; other events fail-open to allow.\r\n if (event === \"PreToolUse\") {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"PreToolUse\",\r\n permissionDecision: \"deny\",\r\n permissionDecisionReason: response.reason ?? \"Blocked by hook\",\r\n },\r\n }),\r\n };\r\n }\r\n // SubagentStop deny = Stop semantics: the documented continuation shape is\r\n // the TOP-LEVEL {\"decision\":\"block\",\"reason\"} (keeps the subagent going\r\n // with `reason` as its next instruction).\r\n if (event === \"SubagentStop\") {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n decision: \"block\",\r\n reason: response.reason ?? \"Blocked by hook\",\r\n }),\r\n };\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // modify → rewrite PreToolUse tool input. Codex applies `updatedInput`\r\n // (PR #20527, stable since 0.131.0) but its output_parser.rs only accepts it\r\n // when paired with permissionDecision:\"allow\" — emitting updatedInput alone\r\n // (the Claude Code shape) is rejected as \"updatedInput without\r\n // permissionDecision:allow\", and an allow alone is rejected too, so the pair\r\n // is emitted together. Other events fail open (no updatedInput surface).\r\n if (response.decision === \"modify\") {\r\n if (event === \"PreToolUse\" && response.updatedInput) {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: \"PreToolUse\",\r\n permissionDecision: \"allow\",\r\n updatedInput: response.updatedInput,\r\n },\r\n }),\r\n };\r\n }\r\n return { exitCode: 0 };\r\n }\r\n\r\n // Context injection: honored on SessionStart, PostToolUse, and PreToolUse\r\n // (additionalContext — PreToolUse support shipped via PR #20692, stable since\r\n // codex 0.130.0; injected independent of any permission decision).\r\n // (SubagentStop accepts only the common output fields — no additionalContext.)\r\n if (\r\n response.additionalContext &&\r\n (event === \"SessionStart\" || event === \"PostToolUse\" || event === \"PreToolUse\")\r\n ) {\r\n return {\r\n exitCode: 0,\r\n stdout: JSON.stringify({\r\n hookSpecificOutput: {\r\n hookEventName: event,\r\n additionalContext: response.additionalContext,\r\n },\r\n }),\r\n };\r\n }\r\n\r\n // \"allow\" / unsupported-on-Codex (ask) → passthrough.\r\n return { exitCode: 0 };\r\n }\r\n\r\n // ── Internal helpers ────────────────────────────────────────────────────\r\n\r\n /** Resolve the per-platform server override into an effective ServerDef. */\r\n private effectiveServer(ctx: InstallContext): ServerDef | undefined {\r\n const override = ctx.connector.platforms[this.id]?.server;\r\n if (override === false) return undefined;\r\n const base = ctx.connector.server;\r\n if (!base) return undefined;\r\n return override ? { ...base, ...override } : base;\r\n }\r\n\r\n /**\r\n * Render the `[mcp_servers.<id>]` table. TOML has NO interpolation, so every\r\n * `${env:VAR}` is resolved to a literal at install time. The env table is a\r\n * plain string→string map. Honors the telemetry serve-wrapper.\r\n */\r\n private renderMcpEntry(ctx: InstallContext, server: ServerDef): CodexMcpEntry {\r\n // Streamable HTTP server: codex infers the transport from `url` (no explicit\r\n // transport key). VERIFIED against codex-cli 0.139.0 — `codex mcp add <id>\r\n // --url <U> --bearer-token-env-var <E>` writes:\r\n // [mcp_servers.<id>]\r\n // url = \"…\"\r\n // bearer_token_env_var = \"…\" (only with bearerEnv auth)\r\n // Telemetry serve-wrapping is stdio-only (remote cannot be intercepted).\r\n // installServer's guard only lets stdio+command or http+url reach here, so\r\n // this branch is exactly the streamable-HTTP case (lock-step with the guard).\r\n if (server.transport === \"http\") {\r\n const remote: CodexMcpEntry = { url: resolveEnvRefsDeep(server.url ?? \"\") };\r\n if (server.auth?.type === \"bearerEnv\" && server.auth.bearerEnvVar) {\r\n remote.bearer_token_env_var = server.auth.bearerEnvVar;\r\n }\r\n if (server.headers && Object.keys(server.headers).length > 0) {\r\n const headers: Record<string, string> = {};\r\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.headers))) {\r\n headers[k] = String(v);\r\n }\r\n remote.http_headers = headers;\r\n }\r\n return remote;\r\n }\r\n let command = server.command as string;\r\n let args = [...(server.args ?? [])];\r\n\r\n ({ command, args } = buildWrappedStdio(ctx, server, this.id, command, args));\r\n\r\n // Resolve env-refs to literals (TOML cannot interpolate).\r\n command = resolveEnvRefsDeep(command);\r\n args = resolveEnvRefsDeep(args);\r\n\r\n const entry: CodexMcpEntry = { command };\r\n if (args.length > 0) entry.args = args;\r\n\r\n if (server.env && Object.keys(server.env).length > 0) {\r\n const env: Record<string, string> = {};\r\n for (const [k, v] of Object.entries(resolveEnvRefsDeep(server.env))) {\r\n env[k] = String(v);\r\n }\r\n entry.env = env;\r\n }\r\n return entry;\r\n }\r\n\r\n /**\r\n * Does this hooks.json entry belong to this connector for `event`? EVENT-\r\n * SPECIFIC + path-normalized exact-command match. The engine binds this per\r\n * event in the uninstall (whole-entry FLAT removal) and the install idempotency\r\n * find reuses its command body via the descriptor's entryOwnsCommand.\r\n */\r\n private isOurEntry(ctx: InstallContext, event: CodexHookEventName, entry: CodexHookEntry): boolean {\r\n if (!entry || typeof entry !== \"object\" || !Array.isArray(entry.hooks)) return false;\r\n const ours = buildHomeBinHookCommand(ctx.homeBinPath, \"codex\", event, ctx.connector.id);\r\n const needle = ours.replace(/\\\\/g, \"/\");\r\n return entry.hooks.some((h) => (h.command ?? \"\").replace(/\\\\/g, \"/\") === needle);\r\n }\r\n}\r\n\r\nexport const adapter = new CodexAdapter();\r\nexport default adapter;\r\n"],"mappings":"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","names":[]}
|