@iloom/cli 0.11.1 → 0.12.1
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 +1 -1
- package/README.md +153 -13
- package/dist/BitBucketApiClient-J2ZSCS5N.js +10 -0
- package/dist/BitBucketVCSProvider-5X64IXXW.js +12 -0
- package/dist/{BranchNamingService-XBCO747L.js → BranchNamingService-MEK2WZUD.js} +4 -4
- package/dist/ClaudeContextManager-IENAE2CP.js +14 -0
- package/dist/ClaudeService-YIJCZUUB.js +13 -0
- package/dist/GitHubService-UTAYZXL3.js +12 -0
- package/dist/IssueTrackerFactory-2OI7YIN6.js +15 -0
- package/dist/{LoomLauncher-5AZU2F5I.js → LoomLauncher-3TSFW7QP.js} +10 -10
- package/dist/MetadataManager-V4LSJ2PB.js +10 -0
- package/dist/ProjectCapabilityDetector-I4J66WKF.js +11 -0
- package/dist/{PromptTemplateManager-T5VTLJP3.js → PromptTemplateManager-I75WKXM4.js} +3 -3
- package/dist/README.md +153 -13
- package/dist/{SettingsManager-WQ5NSGAH.js → SettingsManager-BMQCAXPP.js} +13 -5
- package/dist/SettingsMigrationManager-ZPARZ5KH.js +10 -0
- package/dist/agents/iloom-code-reviewer.md +2 -1
- package/dist/agents/iloom-framework-detector.md +0 -1
- package/dist/agents/iloom-issue-analyze-and-plan.md +4 -1
- package/dist/agents/iloom-issue-analyzer.md +4 -1
- package/dist/agents/iloom-issue-complexity-evaluator.md +4 -1
- package/dist/agents/iloom-issue-enhancer.md +4 -1
- package/dist/agents/iloom-issue-implementer.md +5 -2
- package/dist/agents/iloom-issue-planner.md +4 -1
- package/dist/agents/iloom-wave-verifier.md +186 -0
- package/dist/browser-VZY7F2DF.js +10 -0
- package/dist/build-DMWSIME6.js +27 -0
- package/dist/{chunk-UHIBKD73.js → chunk-35CBWAJL.js} +13 -32
- package/dist/{chunk-UHIBKD73.js.map → chunk-35CBWAJL.js.map} +1 -1
- package/dist/{chunk-YRCEOQPX.js → chunk-4JZEQBWV.js} +4 -3
- package/dist/chunk-4JZEQBWV.js.map +1 -0
- package/dist/{chunk-ET6A2JR4.js → chunk-653XBU3L.js} +111 -18
- package/dist/chunk-653XBU3L.js.map +1 -0
- package/dist/{chunk-G2MNSPA4.js → chunk-772N5WCA.js} +2 -2
- package/dist/{chunk-WG4MLJ6J.js → chunk-7RCUWU3I.js} +2 -2
- package/dist/chunk-7RCUWU3I.js.map +1 -0
- package/dist/{chunk-NOMQ5RFG.js → chunk-7UBEHQTP.js} +2 -2
- package/dist/{chunk-7NFCGKZT.js → chunk-AQUSMNBF.js} +3 -3
- package/dist/{chunk-IDCE26KD.js → chunk-AUYSAMXV.js} +3 -3
- package/dist/chunk-AYLC633W.js +406 -0
- package/dist/chunk-AYLC633W.js.map +1 -0
- package/dist/{chunk-HLDY5S4C.js → chunk-BFF27W3S.js} +3 -3
- package/dist/{chunk-QVAA5KHK.js → chunk-BZ7KTXPB.js} +16 -8
- package/dist/chunk-BZ7KTXPB.js.map +1 -0
- package/dist/{chunk-K7R5QY6C.js → chunk-CE676WCN.js} +2 -2
- package/dist/{chunk-5UFGO4ZT.js → chunk-CQHHEW2M.js} +6 -3
- package/dist/chunk-CQHHEW2M.js.map +1 -0
- package/dist/{chunk-LHDD4JHC.js → chunk-D4Q7T5KD.js} +4 -4
- package/dist/{chunk-RBYTXYGD.js → chunk-D75KSI3V.js} +2 -2
- package/dist/{chunk-Y3RX7LZT.js → chunk-DDHWZNGL.js} +18 -12
- package/dist/chunk-DDHWZNGL.js.map +1 -0
- package/dist/{chunk-5LTID2AF.js → chunk-DMSL5BAP.js} +35 -6
- package/dist/{chunk-5LTID2AF.js.map → chunk-DMSL5BAP.js.map} +1 -1
- package/dist/{chunk-TEJAGQX2.js → chunk-DY6MUWQW.js} +36 -36
- package/dist/chunk-DY6MUWQW.js.map +1 -0
- package/dist/{chunk-SQYHPBFP.js → chunk-EGNUOALL.js} +2 -2
- package/dist/{chunk-LL6TOX3G.js → chunk-EQIII6GI.js} +10 -10
- package/dist/chunk-EQIII6GI.js.map +1 -0
- package/dist/{chunk-ZAXRQLK3.js → chunk-FTYWGQFM.js} +2 -2
- package/dist/{chunk-LE2NOUTN.js → chunk-FV4KXBGO.js} +3 -3
- package/dist/{chunk-XFQGI2E3.js → chunk-GWJWECZB.js} +51 -45
- package/dist/chunk-GWJWECZB.js.map +1 -0
- package/dist/{chunk-QNHZM5ZV.js → chunk-HIGWKLQR.js} +3 -3
- package/dist/{chunk-VMZG66UV.js → chunk-HKEXRZMU.js} +3 -3
- package/dist/{chunk-V4STTBQD.js → chunk-IHSA7VGI.js} +9 -9
- package/dist/{chunk-NCPZYQ4B.js → chunk-K3QGG4O2.js} +2 -2
- package/dist/{chunk-QR4FU53I.js → chunk-KCZSUJUR.js} +22 -12
- package/dist/chunk-KCZSUJUR.js.map +1 -0
- package/dist/{chunk-NH3QZYE5.js → chunk-KV4NU3RP.js} +2 -2
- package/dist/{chunk-NDSGJZI2.js → chunk-LOAYWTJJ.js} +2 -2
- package/dist/{chunk-ABVMUNCD.js → chunk-M3FBM4T3.js} +64 -10
- package/dist/chunk-M3FBM4T3.js.map +1 -0
- package/dist/{chunk-GMDSYLI6.js → chunk-MY2Q3FJ3.js} +2 -2
- package/dist/{chunk-CV47VCMQ.js → chunk-NPVA65KS.js} +2 -2
- package/dist/{chunk-7OCGBJLR.js → chunk-OIVFHJOA.js} +2 -2
- package/dist/{chunk-7FIXNAUO.js → chunk-OKB2NEDQ.js} +66 -43
- package/dist/chunk-OKB2NEDQ.js.map +1 -0
- package/dist/{chunk-3RXYOBME.js → chunk-OPQC4OWM.js} +5 -5
- package/dist/{chunk-3RXYOBME.js.map → chunk-OPQC4OWM.js.map} +1 -1
- package/dist/chunk-P5MXXHXQ.js +284 -0
- package/dist/chunk-P5MXXHXQ.js.map +1 -0
- package/dist/{chunk-NN5RYWXA.js → chunk-PH65MFQM.js} +6 -6
- package/dist/{chunk-TZNNJLGT.js → chunk-PMB6TYV4.js} +6 -6
- package/dist/chunk-QC65IOV3.js +304 -0
- package/dist/chunk-QC65IOV3.js.map +1 -0
- package/dist/{chunk-6YVJVUR4.js → chunk-QF2DROQR.js} +3 -3
- package/dist/{chunk-XXFSOVL3.js → chunk-QFDM23CO.js} +4 -4
- package/dist/{chunk-RMLADZRY.js → chunk-R7DGN73N.js} +5 -5
- package/dist/{chunk-IR74O2F6.js → chunk-UVXB6O24.js} +245 -187
- package/dist/chunk-UVXB6O24.js.map +1 -0
- package/dist/{chunk-5PNZBH6V.js → chunk-V5IYLWRA.js} +2 -2
- package/dist/{chunk-KQFIGI37.js → chunk-VA6CWUAE.js} +7 -7
- package/dist/{chunk-3GTUXW26.js → chunk-VIQOQ463.js} +19 -3
- package/dist/chunk-VIQOQ463.js.map +1 -0
- package/dist/{chunk-H2SSF24U.js → chunk-VRPPI6GU.js} +17 -6
- package/dist/{chunk-H2SSF24U.js.map → chunk-VRPPI6GU.js.map} +1 -1
- package/dist/{chunk-YETJNRQM.js → chunk-WEBMMJKL.js} +2 -1
- package/dist/{chunk-VUUN3KE4.js → chunk-XVCGPTEQ.js} +8 -8
- package/dist/chunk-XVCGPTEQ.js.map +1 -0
- package/dist/{chunk-VNYWBHKR.js → chunk-Y2MVSEJK.js} +33 -3
- package/dist/chunk-Y2MVSEJK.js.map +1 -0
- package/dist/chunk-YWNF5755.js +696 -0
- package/dist/chunk-YWNF5755.js.map +1 -0
- package/dist/{chunk-UDCI3QTS.js → chunk-ZM2AYHMO.js} +2 -2
- package/dist/{claude-ONQTDWV3.js → claude-ACL7G4CF.js} +4 -4
- package/dist/{cleanup-YOM6PQCN.js → cleanup-RLBLNQZN.js} +37 -34
- package/dist/{cleanup-YOM6PQCN.js.map → cleanup-RLBLNQZN.js.map} +1 -1
- package/dist/cli.js +290 -141
- package/dist/cli.js.map +1 -1
- package/dist/{color-VQD52LOI.js → color-AC6F2QE7.js} +3 -3
- package/dist/{commit-DC2Q5CDY.js → commit-RILBXFWO.js} +15 -15
- package/dist/{compile-4NCQECKE.js → compile-QEL5724K.js} +11 -11
- package/dist/{contribute-M5UWXCAV.js → contribute-EHWLYOMZ.js} +11 -11
- package/dist/{contribute-M5UWXCAV.js.map → contribute-EHWLYOMZ.js.map} +1 -1
- package/dist/{mcp/darwin-3JFFE3W2.js → darwin-5K3I4FTH.js} +2 -2
- package/dist/{dev-server-CYRP6M73.js → dev-server-2WSWZXJG.js} +35 -21
- package/dist/dev-server-2WSWZXJG.js.map +1 -0
- package/dist/{feedback-BMAZGKRW.js → feedback-RFWGB4I5.js} +17 -17
- package/dist/{git-BXUD6CL5.js → git-I3PO6FY7.js} +6 -6
- package/dist/ignite-X2NNTNUN.js +35 -0
- package/dist/index.d.ts +200 -16
- package/dist/index.js +164 -55
- package/dist/index.js.map +1 -1
- package/dist/{init-CI43GJHV.js → init-LWU2M53W.js} +18 -18
- package/dist/{install-deps-SRTM5U7D.js → install-deps-HXP2TM7G.js} +11 -11
- package/dist/{installation-detector-HF6QN7KP.js → installation-detector-PYAZ2O6U.js} +3 -3
- package/dist/{issues-DMRQJH7E.js → issues-SUFQJY6O.js} +69 -56
- package/dist/issues-SUFQJY6O.js.map +1 -0
- package/dist/lint-FDZC77GL.js +27 -0
- package/dist/{linux-RYLOP2LY.js → linux-WUGRYCJY.js} +2 -2
- package/dist/mcp/{chunk-PIIRD4LO.js → chunk-4HZMW2V3.js} +1 -1
- package/dist/mcp/{chunk-PIIRD4LO.js.map → chunk-4HZMW2V3.js.map} +1 -1
- package/dist/{darwin-5BHWRJ7D.js → mcp/darwin-U25WIGH6.js} +2 -2
- package/dist/mcp/issue-management-server.js +900 -20
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/{linux-JBVS4R3A.js → linux-5BXVBGSY.js} +2 -2
- package/dist/mcp/recap-server.js +24 -22
- package/dist/mcp/recap-server.js.map +1 -1
- package/dist/mcp/{tmux-RYBLEHUZ.js → tmux-CU26ZTNM.js} +2 -2
- package/dist/mcp/{wsl-4QZIQLLE.js → wsl-KI25UDOF.js} +2 -2
- package/dist/neon-helpers-LCZAN4U4.js +11 -0
- package/dist/{open-2Y7GSUTJ.js → open-US4XACLW.js} +36 -21
- package/dist/open-US4XACLW.js.map +1 -0
- package/dist/{plan-SWFPLNJE.js → plan-5S6355GF.js} +68 -75
- package/dist/plan-5S6355GF.js.map +1 -0
- package/dist/{projects-IUSUXD5D.js → projects-L5AHUBGA.js} +6 -6
- package/dist/{prompt-7LZB4PAT.js → prompt-FUU5NMJQ.js} +3 -3
- package/dist/prompt-FUU5NMJQ.js.map +1 -0
- package/dist/prompts/init-prompt.txt +160 -23
- package/dist/prompts/issue-prompt.txt +93 -157
- package/dist/prompts/plan-prompt.txt +86 -6
- package/dist/prompts/swarm-orchestrator-prompt.txt +78 -21
- package/dist/{rebase-S6OHAOOF.js → rebase-JA3RW2XO.js} +12 -12
- package/dist/{recap-GGVCG5VH.js → recap-5TO42HN2.js} +9 -9
- package/dist/{remote-MZTFHHTU.js → remote-RO4LZKT2.js} +3 -3
- package/dist/remote-RO4LZKT2.js.map +1 -0
- package/dist/{run-ST3FR75O.js → run-KKCRBRLW.js} +36 -21
- package/dist/run-KKCRBRLW.js.map +1 -0
- package/dist/schema/settings.schema.json +147 -11
- package/dist/{shell-W4SBQPTE.js → shell-GAB2FCXH.js} +8 -8
- package/dist/{summary-P2JCIIJO.js → summary-P7QE3TNW.js} +21 -19
- package/dist/summary-P7QE3TNW.js.map +1 -0
- package/dist/test-6LFB5WOO.js +27 -0
- package/dist/{test-git-2KFFAQ6B.js → test-git-PYJOYSED.js} +6 -6
- package/dist/{test-jira-FKDKG6CD.js → test-jira-SM7IU5HW.js} +8 -8
- package/dist/{test-prefix-GP2DAX37.js → test-prefix-HIRZBXTM.js} +6 -6
- package/dist/{test-tabs-YDWMWTVA.js → test-tabs-NGPTFD5T.js} +2 -2
- package/dist/{test-webserver-QI3QQFZ3.js → test-webserver-43PVP2JL.js} +8 -8
- package/dist/{tmux-7ZTA3BDI.js → tmux-6LRFH3DM.js} +2 -2
- package/dist/{update-XLW7R7FL.js → update-AD3GE5C4.js} +4 -4
- package/dist/{update-notifier-EYLAXZAA.js → update-notifier-VYDTDMSJ.js} +3 -3
- package/dist/update-notifier-VYDTDMSJ.js.map +1 -0
- package/dist/{vscode-TOGE5N67.js → vscode-HXIXRZ3A.js} +12 -12
- package/dist/{vscode-announcement-NIX7O2MG.js → vscode-announcement-AL3EHORH.js} +3 -3
- package/dist/{wsl-Y4GUTOQ7.js → wsl-4VMVT2PO.js} +2 -2
- package/package.json +1 -1
- package/dist/ClaudeContextManager-SXDCWDJA.js +0 -14
- package/dist/ClaudeService-6E6MCGJE.js +0 -13
- package/dist/GitHubService-2R5GQG4K.js +0 -12
- package/dist/IssueTrackerFactory-XN6MQ4UN.js +0 -14
- package/dist/MetadataManager-CMQQTFLQ.js +0 -10
- package/dist/ProjectCapabilityDetector-IC6NAFGY.js +0 -11
- package/dist/SettingsMigrationManager-S6J7OHUH.js +0 -10
- package/dist/build-OLS6J5KZ.js +0 -27
- package/dist/chunk-3GTUXW26.js.map +0 -1
- package/dist/chunk-5UFGO4ZT.js.map +0 -1
- package/dist/chunk-7FIXNAUO.js.map +0 -1
- package/dist/chunk-ABVMUNCD.js.map +0 -1
- package/dist/chunk-ET6A2JR4.js.map +0 -1
- package/dist/chunk-IR74O2F6.js.map +0 -1
- package/dist/chunk-LL6TOX3G.js.map +0 -1
- package/dist/chunk-QR4FU53I.js.map +0 -1
- package/dist/chunk-QVAA5KHK.js.map +0 -1
- package/dist/chunk-RVI6C2H5.js +0 -220
- package/dist/chunk-RVI6C2H5.js.map +0 -1
- package/dist/chunk-TEJAGQX2.js.map +0 -1
- package/dist/chunk-VNYWBHKR.js.map +0 -1
- package/dist/chunk-VUUN3KE4.js.map +0 -1
- package/dist/chunk-WG4MLJ6J.js.map +0 -1
- package/dist/chunk-XFQGI2E3.js.map +0 -1
- package/dist/chunk-Y3RX7LZT.js.map +0 -1
- package/dist/chunk-YRCEOQPX.js.map +0 -1
- package/dist/dev-server-CYRP6M73.js.map +0 -1
- package/dist/ignite-IO4LXVXJ.js +0 -35
- package/dist/issues-DMRQJH7E.js.map +0 -1
- package/dist/lint-BSWRMGPZ.js +0 -27
- package/dist/neon-helpers-HWIYRKOW.js +0 -11
- package/dist/open-2Y7GSUTJ.js.map +0 -1
- package/dist/plan-SWFPLNJE.js.map +0 -1
- package/dist/run-ST3FR75O.js.map +0 -1
- package/dist/summary-P2JCIIJO.js.map +0 -1
- package/dist/test-6JH4FE2X.js +0 -27
- /package/dist/{BranchNamingService-XBCO747L.js.map → BitBucketApiClient-J2ZSCS5N.js.map} +0 -0
- /package/dist/{ClaudeContextManager-SXDCWDJA.js.map → BitBucketVCSProvider-5X64IXXW.js.map} +0 -0
- /package/dist/{ClaudeService-6E6MCGJE.js.map → BranchNamingService-MEK2WZUD.js.map} +0 -0
- /package/dist/{GitHubService-2R5GQG4K.js.map → ClaudeContextManager-IENAE2CP.js.map} +0 -0
- /package/dist/{IssueTrackerFactory-XN6MQ4UN.js.map → ClaudeService-YIJCZUUB.js.map} +0 -0
- /package/dist/{MetadataManager-CMQQTFLQ.js.map → GitHubService-UTAYZXL3.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-IC6NAFGY.js.map → IssueTrackerFactory-2OI7YIN6.js.map} +0 -0
- /package/dist/{LoomLauncher-5AZU2F5I.js.map → LoomLauncher-3TSFW7QP.js.map} +0 -0
- /package/dist/{PromptTemplateManager-T5VTLJP3.js.map → MetadataManager-V4LSJ2PB.js.map} +0 -0
- /package/dist/{SettingsManager-WQ5NSGAH.js.map → ProjectCapabilityDetector-I4J66WKF.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-S6J7OHUH.js.map → PromptTemplateManager-I75WKXM4.js.map} +0 -0
- /package/dist/{claude-ONQTDWV3.js.map → SettingsManager-BMQCAXPP.js.map} +0 -0
- /package/dist/{color-VQD52LOI.js.map → SettingsMigrationManager-ZPARZ5KH.js.map} +0 -0
- /package/dist/{darwin-5BHWRJ7D.js.map → browser-VZY7F2DF.js.map} +0 -0
- /package/dist/{build-OLS6J5KZ.js.map → build-DMWSIME6.js.map} +0 -0
- /package/dist/{chunk-G2MNSPA4.js.map → chunk-772N5WCA.js.map} +0 -0
- /package/dist/{chunk-NOMQ5RFG.js.map → chunk-7UBEHQTP.js.map} +0 -0
- /package/dist/{chunk-7NFCGKZT.js.map → chunk-AQUSMNBF.js.map} +0 -0
- /package/dist/{chunk-IDCE26KD.js.map → chunk-AUYSAMXV.js.map} +0 -0
- /package/dist/{chunk-HLDY5S4C.js.map → chunk-BFF27W3S.js.map} +0 -0
- /package/dist/{chunk-K7R5QY6C.js.map → chunk-CE676WCN.js.map} +0 -0
- /package/dist/{chunk-LHDD4JHC.js.map → chunk-D4Q7T5KD.js.map} +0 -0
- /package/dist/{chunk-RBYTXYGD.js.map → chunk-D75KSI3V.js.map} +0 -0
- /package/dist/{chunk-SQYHPBFP.js.map → chunk-EGNUOALL.js.map} +0 -0
- /package/dist/{chunk-ZAXRQLK3.js.map → chunk-FTYWGQFM.js.map} +0 -0
- /package/dist/{chunk-LE2NOUTN.js.map → chunk-FV4KXBGO.js.map} +0 -0
- /package/dist/{chunk-QNHZM5ZV.js.map → chunk-HIGWKLQR.js.map} +0 -0
- /package/dist/{chunk-VMZG66UV.js.map → chunk-HKEXRZMU.js.map} +0 -0
- /package/dist/{chunk-V4STTBQD.js.map → chunk-IHSA7VGI.js.map} +0 -0
- /package/dist/{chunk-NCPZYQ4B.js.map → chunk-K3QGG4O2.js.map} +0 -0
- /package/dist/{chunk-NH3QZYE5.js.map → chunk-KV4NU3RP.js.map} +0 -0
- /package/dist/{chunk-NDSGJZI2.js.map → chunk-LOAYWTJJ.js.map} +0 -0
- /package/dist/{chunk-GMDSYLI6.js.map → chunk-MY2Q3FJ3.js.map} +0 -0
- /package/dist/{chunk-CV47VCMQ.js.map → chunk-NPVA65KS.js.map} +0 -0
- /package/dist/{chunk-7OCGBJLR.js.map → chunk-OIVFHJOA.js.map} +0 -0
- /package/dist/{chunk-NN5RYWXA.js.map → chunk-PH65MFQM.js.map} +0 -0
- /package/dist/{chunk-TZNNJLGT.js.map → chunk-PMB6TYV4.js.map} +0 -0
- /package/dist/{chunk-6YVJVUR4.js.map → chunk-QF2DROQR.js.map} +0 -0
- /package/dist/{chunk-XXFSOVL3.js.map → chunk-QFDM23CO.js.map} +0 -0
- /package/dist/{chunk-RMLADZRY.js.map → chunk-R7DGN73N.js.map} +0 -0
- /package/dist/{chunk-5PNZBH6V.js.map → chunk-V5IYLWRA.js.map} +0 -0
- /package/dist/{chunk-KQFIGI37.js.map → chunk-VA6CWUAE.js.map} +0 -0
- /package/dist/{chunk-YETJNRQM.js.map → chunk-WEBMMJKL.js.map} +0 -0
- /package/dist/{chunk-UDCI3QTS.js.map → chunk-ZM2AYHMO.js.map} +0 -0
- /package/dist/{git-BXUD6CL5.js.map → claude-ACL7G4CF.js.map} +0 -0
- /package/dist/{ignite-IO4LXVXJ.js.map → color-AC6F2QE7.js.map} +0 -0
- /package/dist/{commit-DC2Q5CDY.js.map → commit-RILBXFWO.js.map} +0 -0
- /package/dist/{compile-4NCQECKE.js.map → compile-QEL5724K.js.map} +0 -0
- /package/dist/{installation-detector-HF6QN7KP.js.map → darwin-5K3I4FTH.js.map} +0 -0
- /package/dist/{feedback-BMAZGKRW.js.map → feedback-RFWGB4I5.js.map} +0 -0
- /package/dist/{mcp/darwin-3JFFE3W2.js.map → git-I3PO6FY7.js.map} +0 -0
- /package/dist/{neon-helpers-HWIYRKOW.js.map → ignite-X2NNTNUN.js.map} +0 -0
- /package/dist/{init-CI43GJHV.js.map → init-LWU2M53W.js.map} +0 -0
- /package/dist/{install-deps-SRTM5U7D.js.map → install-deps-HXP2TM7G.js.map} +0 -0
- /package/dist/{prompt-7LZB4PAT.js.map → installation-detector-PYAZ2O6U.js.map} +0 -0
- /package/dist/{lint-BSWRMGPZ.js.map → lint-FDZC77GL.js.map} +0 -0
- /package/dist/{linux-RYLOP2LY.js.map → linux-WUGRYCJY.js.map} +0 -0
- /package/dist/{remote-MZTFHHTU.js.map → mcp/darwin-U25WIGH6.js.map} +0 -0
- /package/dist/mcp/{linux-JBVS4R3A.js.map → linux-5BXVBGSY.js.map} +0 -0
- /package/dist/mcp/{tmux-RYBLEHUZ.js.map → tmux-CU26ZTNM.js.map} +0 -0
- /package/dist/mcp/{wsl-4QZIQLLE.js.map → wsl-KI25UDOF.js.map} +0 -0
- /package/dist/{update-notifier-EYLAXZAA.js.map → neon-helpers-LCZAN4U4.js.map} +0 -0
- /package/dist/{projects-IUSUXD5D.js.map → projects-L5AHUBGA.js.map} +0 -0
- /package/dist/{rebase-S6OHAOOF.js.map → rebase-JA3RW2XO.js.map} +0 -0
- /package/dist/{recap-GGVCG5VH.js.map → recap-5TO42HN2.js.map} +0 -0
- /package/dist/{shell-W4SBQPTE.js.map → shell-GAB2FCXH.js.map} +0 -0
- /package/dist/{test-6JH4FE2X.js.map → test-6LFB5WOO.js.map} +0 -0
- /package/dist/{test-git-2KFFAQ6B.js.map → test-git-PYJOYSED.js.map} +0 -0
- /package/dist/{test-jira-FKDKG6CD.js.map → test-jira-SM7IU5HW.js.map} +0 -0
- /package/dist/{test-prefix-GP2DAX37.js.map → test-prefix-HIRZBXTM.js.map} +0 -0
- /package/dist/{test-tabs-YDWMWTVA.js.map → test-tabs-NGPTFD5T.js.map} +0 -0
- /package/dist/{test-webserver-QI3QQFZ3.js.map → test-webserver-43PVP2JL.js.map} +0 -0
- /package/dist/{tmux-7ZTA3BDI.js.map → tmux-6LRFH3DM.js.map} +0 -0
- /package/dist/{update-XLW7R7FL.js.map → update-AD3GE5C4.js.map} +0 -0
- /package/dist/{vscode-TOGE5N67.js.map → vscode-HXIXRZ3A.js.map} +0 -0
- /package/dist/{vscode-announcement-NIX7O2MG.js.map → vscode-announcement-AL3EHORH.js.map} +0 -0
- /package/dist/{wsl-Y4GUTOQ7.js.map → wsl-4VMVT2PO.js.map} +0 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
getLogger
|
|
4
|
+
} from "./chunk-FTYWGQFM.js";
|
|
5
|
+
|
|
6
|
+
// src/lib/providers/bitbucket/BitBucketApiClient.ts
|
|
7
|
+
import https from "https";
|
|
8
|
+
var BitBucketApiClient = class {
|
|
9
|
+
constructor(config) {
|
|
10
|
+
this.baseUrl = "https://api.bitbucket.org/2.0";
|
|
11
|
+
const credentials = Buffer.from(`${config.username}:${config.apiToken}`).toString("base64");
|
|
12
|
+
this.authHeader = `Basic ${credentials}`;
|
|
13
|
+
this.workspace = config.workspace;
|
|
14
|
+
this.repoSlug = config.repoSlug;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Make an HTTP request to BitBucket API
|
|
18
|
+
*/
|
|
19
|
+
async request(method, endpoint, body) {
|
|
20
|
+
const url = endpoint.startsWith("http://") || endpoint.startsWith("https://") ? new URL(endpoint) : new URL(`${this.baseUrl}${endpoint}`);
|
|
21
|
+
if ((endpoint.startsWith("http://") || endpoint.startsWith("https://")) && url.hostname !== "api.bitbucket.org") {
|
|
22
|
+
throw new Error(`Refusing to send authenticated request to unexpected host: ${url.hostname} (expected api.bitbucket.org)`);
|
|
23
|
+
}
|
|
24
|
+
getLogger().debug(`BitBucket API ${method} request`, { url: url.toString() });
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const options = {
|
|
27
|
+
hostname: url.hostname,
|
|
28
|
+
port: url.port || 443,
|
|
29
|
+
path: url.pathname + url.search,
|
|
30
|
+
method,
|
|
31
|
+
headers: {
|
|
32
|
+
"Authorization": this.authHeader,
|
|
33
|
+
"Accept": "application/json",
|
|
34
|
+
"Content-Type": "application/json"
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const req = https.request(options, (res) => {
|
|
38
|
+
let data = "";
|
|
39
|
+
res.on("data", (chunk) => {
|
|
40
|
+
data += chunk;
|
|
41
|
+
});
|
|
42
|
+
res.on("end", () => {
|
|
43
|
+
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
|
|
44
|
+
reject(new Error(`BitBucket API error (${res.statusCode}): ${data}`));
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (res.statusCode === 204 || !data) {
|
|
48
|
+
resolve({});
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
resolve(JSON.parse(data));
|
|
53
|
+
} catch (error) {
|
|
54
|
+
reject(new Error(`Failed to parse BitBucket API response: ${error}`));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
req.on("error", (error) => {
|
|
59
|
+
reject(new Error(`BitBucket API request failed: ${error.message}`));
|
|
60
|
+
});
|
|
61
|
+
if (body) {
|
|
62
|
+
req.write(JSON.stringify(body));
|
|
63
|
+
}
|
|
64
|
+
req.end();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Make a GET request to BitBucket API
|
|
69
|
+
*/
|
|
70
|
+
async get(endpoint) {
|
|
71
|
+
return this.request("GET", endpoint);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Make a POST request to BitBucket API
|
|
75
|
+
*/
|
|
76
|
+
async post(endpoint, body) {
|
|
77
|
+
return this.request("POST", endpoint, body);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Make a PUT request to BitBucket API
|
|
81
|
+
*/
|
|
82
|
+
async put(endpoint, body) {
|
|
83
|
+
return this.request("PUT", endpoint, body);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get repository information
|
|
87
|
+
*/
|
|
88
|
+
async getRepository(workspace, repoSlug) {
|
|
89
|
+
return this.get(`/repositories/${workspace}/${repoSlug}`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get a pull request by ID
|
|
93
|
+
*/
|
|
94
|
+
async getPullRequest(workspace, repoSlug, prId) {
|
|
95
|
+
return this.get(
|
|
96
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* List open pull requests for a branch
|
|
101
|
+
*
|
|
102
|
+
* Note: BitBucket uses BBQL (BitBucket Query Language) for filtering.
|
|
103
|
+
* The q parameter must use the format: q=source.branch.name="branch-name"
|
|
104
|
+
* When using BBQL, we include state filter in the query to ensure it's applied.
|
|
105
|
+
* See: https://developer.atlassian.com/cloud/bitbucket/rest/intro/#filtering
|
|
106
|
+
*/
|
|
107
|
+
async listPullRequests(workspace, repoSlug, sourceBranch) {
|
|
108
|
+
let endpoint = `/repositories/${workspace}/${repoSlug}/pullrequests`;
|
|
109
|
+
if (sourceBranch) {
|
|
110
|
+
const safeBranch = sourceBranch.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
111
|
+
const query = `state="OPEN" AND source.branch.name="${safeBranch}"`;
|
|
112
|
+
endpoint += `?q=${encodeURIComponent(query)}`;
|
|
113
|
+
} else {
|
|
114
|
+
endpoint += `?state=OPEN`;
|
|
115
|
+
}
|
|
116
|
+
const response = await this.get(endpoint);
|
|
117
|
+
return response.values;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Create a pull request
|
|
121
|
+
*/
|
|
122
|
+
async createPullRequest(workspace, repoSlug, title, description, sourceBranch, destinationBranch, reviewerAccountIds) {
|
|
123
|
+
const payload = {
|
|
124
|
+
title,
|
|
125
|
+
description,
|
|
126
|
+
source: {
|
|
127
|
+
branch: {
|
|
128
|
+
name: sourceBranch
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
destination: {
|
|
132
|
+
branch: {
|
|
133
|
+
name: destinationBranch
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
if (reviewerAccountIds && reviewerAccountIds.length > 0) {
|
|
138
|
+
payload.reviewers = reviewerAccountIds.map((id) => ({ account_id: id }));
|
|
139
|
+
}
|
|
140
|
+
return this.post(
|
|
141
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests`,
|
|
142
|
+
payload
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Add a comment to a pull request
|
|
147
|
+
*/
|
|
148
|
+
async addPRComment(workspace, repoSlug, prId, content) {
|
|
149
|
+
return this.post(
|
|
150
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,
|
|
151
|
+
{
|
|
152
|
+
content: {
|
|
153
|
+
raw: content
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Update an existing comment on a pull request
|
|
160
|
+
*/
|
|
161
|
+
async updatePRComment(workspace, repoSlug, prId, commentId, content) {
|
|
162
|
+
return this.put(
|
|
163
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments/${commentId}`,
|
|
164
|
+
{
|
|
165
|
+
content: {
|
|
166
|
+
raw: content
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* List all comments on a pull request with pagination
|
|
173
|
+
*/
|
|
174
|
+
async listPRComments(workspace, repoSlug, prId) {
|
|
175
|
+
const MAX_PAGES = 50;
|
|
176
|
+
const allComments = [];
|
|
177
|
+
let nextUrl = `/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`;
|
|
178
|
+
let pageCount = 0;
|
|
179
|
+
while (nextUrl) {
|
|
180
|
+
pageCount++;
|
|
181
|
+
if (pageCount > MAX_PAGES) {
|
|
182
|
+
console.error(`BitBucket listPRComments: exceeded maximum pagination limit of ${MAX_PAGES} pages, returning ${allComments.length} comments collected so far`);
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
const response = await this.get(nextUrl);
|
|
186
|
+
allComments.push(...response.values);
|
|
187
|
+
nextUrl = response.next ?? null;
|
|
188
|
+
}
|
|
189
|
+
getLogger().debug(`Fetched ${allComments.length} PR comments from BitBucket`);
|
|
190
|
+
return allComments;
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Add an inline comment to a specific file and line in a pull request
|
|
194
|
+
*/
|
|
195
|
+
async addInlinePRComment(workspace, repoSlug, prId, content, filePath, line) {
|
|
196
|
+
return this.post(
|
|
197
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,
|
|
198
|
+
{
|
|
199
|
+
content: {
|
|
200
|
+
raw: content
|
|
201
|
+
},
|
|
202
|
+
inline: {
|
|
203
|
+
to: line,
|
|
204
|
+
path: filePath
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Find workspace members by usernames
|
|
211
|
+
* Returns a map of username -> account_id for resolved users
|
|
212
|
+
* Handles pagination to fetch all workspace members
|
|
213
|
+
*/
|
|
214
|
+
async findUsersByUsername(workspace, usernames) {
|
|
215
|
+
const result = /* @__PURE__ */ new Map();
|
|
216
|
+
const allMembers = await this.getAllWorkspaceMembers(workspace);
|
|
217
|
+
getLogger().debug(`Resolving ${usernames.length} usernames against ${allMembers.length} workspace members`);
|
|
218
|
+
for (const username of usernames) {
|
|
219
|
+
const usernameLower = username.toLowerCase();
|
|
220
|
+
const member = allMembers.find(
|
|
221
|
+
(m) => {
|
|
222
|
+
var _a;
|
|
223
|
+
return ((_a = m.user.nickname) == null ? void 0 : _a.toLowerCase()) === usernameLower || m.user.display_name.toLowerCase() === usernameLower;
|
|
224
|
+
}
|
|
225
|
+
);
|
|
226
|
+
if (member) {
|
|
227
|
+
result.set(username, member.user.account_id);
|
|
228
|
+
getLogger().debug(`Resolved reviewer ${username} to account ID ${member.user.account_id}`);
|
|
229
|
+
} else {
|
|
230
|
+
getLogger().warn(`Could not resolve reviewer ${username} to a BitBucket account ID`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Fetch all workspace members with pagination
|
|
237
|
+
*/
|
|
238
|
+
async getAllWorkspaceMembers(workspace) {
|
|
239
|
+
const allMembers = [];
|
|
240
|
+
let nextUrl = `/workspaces/${workspace}/members`;
|
|
241
|
+
while (nextUrl) {
|
|
242
|
+
const response = await this.get(nextUrl);
|
|
243
|
+
allMembers.push(...response.values);
|
|
244
|
+
nextUrl = response.next ?? null;
|
|
245
|
+
}
|
|
246
|
+
getLogger().debug(`Fetched ${allMembers.length} workspace members from BitBucket`);
|
|
247
|
+
return allMembers;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Get the currently authenticated user
|
|
251
|
+
*/
|
|
252
|
+
async getCurrentUser() {
|
|
253
|
+
return this.get("/user");
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Test connection to BitBucket API
|
|
257
|
+
*/
|
|
258
|
+
async testConnection() {
|
|
259
|
+
try {
|
|
260
|
+
await this.getCurrentUser();
|
|
261
|
+
return true;
|
|
262
|
+
} catch (error) {
|
|
263
|
+
getLogger().error("BitBucket connection test failed", { error });
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get configured workspace
|
|
269
|
+
*/
|
|
270
|
+
getWorkspace() {
|
|
271
|
+
return this.workspace;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Get configured repository slug
|
|
275
|
+
*/
|
|
276
|
+
getRepoSlug() {
|
|
277
|
+
return this.repoSlug;
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export {
|
|
282
|
+
BitBucketApiClient
|
|
283
|
+
};
|
|
284
|
+
//# sourceMappingURL=chunk-P5MXXHXQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/providers/bitbucket/BitBucketApiClient.ts"],"sourcesContent":["// BitBucketApiClient - REST API wrapper for BitBucket operations\n// Handles authentication and common API request patterns\n\nimport https from 'node:https'\nimport { getLogger } from '../../../utils/logger-context.js'\n\n/**\n * BitBucket API configuration\n */\nexport interface BitBucketConfig {\n\tusername: string\n\tapiToken: string // API token from BitBucket settings\n\tworkspace?: string // Optional, can be auto-detected from git remote\n\trepoSlug?: string // Optional, can be auto-detected from git remote\n}\n\n/**\n * BitBucket pull request response from API\n */\nexport interface BitBucketPullRequest {\n\tid: number\n\ttitle: string\n\tdescription: string\n\tstate: 'OPEN' | 'MERGED' | 'DECLINED' | 'SUPERSEDED'\n\tauthor: {\n\t\tdisplay_name: string\n\t\tuuid: string\n\t}\n\tsource: {\n\t\tbranch: {\n\t\t\tname: string\n\t\t}\n\t}\n\tdestination: {\n\t\tbranch: {\n\t\t\tname: string\n\t\t}\n\t}\n\tcreated_on: string\n\tupdated_on: string\n\tlinks: {\n\t\thtml: {\n\t\t\thref: string\n\t\t}\n\t}\n\t[key: string]: unknown\n}\n\n/**\n * BitBucket workspace member response from API\n * Used for resolving usernames to account IDs\n */\nexport interface BitBucketWorkspaceMember {\n\tuser: {\n\t\taccount_id: string\n\t\tdisplay_name: string\n\t\tuuid: string\n\t\tnickname?: string\n\t}\n}\n\n/**\n * BitBucket repository response from API\n */\nexport interface BitBucketRepository {\n\tslug: string\n\tname: string\n\tfull_name: string\n\tworkspace: {\n\t\tslug: string\n\t}\n\tlinks: {\n\t\thtml: {\n\t\t\thref: string\n\t\t}\n\t}\n\t[key: string]: unknown\n}\n\ninterface BitBucketWorkspaceMembersResponse { values: BitBucketWorkspaceMember[]; next?: string }\n\n/**\n * BitBucket current user response from /user endpoint\n */\nexport interface BitBucketCurrentUser {\n\taccount_id: string\n\tdisplay_name: string\n\tnickname?: string\n}\n\n/**\n * BitBucket PR comment response from API\n */\nexport interface BitBucketComment {\n\tid: number\n\tcontent: { raw: string }\n\tinline?: { from: number | null; to: number | null; path: string }\n\tlinks: { html: { href: string } }\n\tuser?: { display_name: string; uuid: string }\n\tcreated_on?: string\n\tupdated_on?: string\n}\n\n/**\n * BitBucketApiClient provides low-level REST API access to BitBucket\n * \n * Authentication: Basic Auth with username and API token\n * API Reference: https://developer.atlassian.com/cloud/bitbucket/rest/intro/\n * \n * Note: As of September 9, 2025, BitBucket app passwords can no longer be created.\n * Use API tokens with scopes instead. All existing app passwords will be disabled on June 9, 2026.\n */\nexport class BitBucketApiClient {\n\tprivate readonly baseUrl = 'https://api.bitbucket.org/2.0'\n\tprivate readonly authHeader: string\n\tprivate readonly workspace: string | undefined\n\tprivate readonly repoSlug: string | undefined\n\n\tconstructor(config: BitBucketConfig) {\n\t\t// Create Basic Auth header with API token\n\t\tconst credentials = Buffer.from(`${config.username}:${config.apiToken}`).toString('base64')\n\t\tthis.authHeader = `Basic ${credentials}`\n\t\t\n\t\tthis.workspace = config.workspace\n\t\tthis.repoSlug = config.repoSlug\n\t}\n\n\t/**\n\t * Make an HTTP request to BitBucket API\n\t */\n\tprivate async request<T>(\n\t\tmethod: 'GET' | 'POST' | 'PUT',\n\t\tendpoint: string,\n\t\tbody?: unknown\n\t): Promise<T> {\n\t\t// If endpoint is already a full URL, use it directly; otherwise prepend baseUrl\n\t\tconst url = endpoint.startsWith('http://') || endpoint.startsWith('https://')\n\t\t\t? new URL(endpoint)\n\t\t\t: new URL(`${this.baseUrl}${endpoint}`)\n\n\t\t// Validate hostname for full URLs to prevent sending auth credentials to unexpected hosts\n\t\tif ((endpoint.startsWith('http://') || endpoint.startsWith('https://')) && url.hostname !== 'api.bitbucket.org') {\n\t\t\tthrow new Error(`Refusing to send authenticated request to unexpected host: ${url.hostname} (expected api.bitbucket.org)`)\n\t\t}\n\t\tgetLogger().debug(`BitBucket API ${method} request`, { url: url.toString() })\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst options: https.RequestOptions = {\n\t\t\t\thostname: url.hostname,\n\t\t\t\tport: url.port || 443,\n\t\t\t\tpath: url.pathname + url.search,\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\t'Authorization': this.authHeader,\n\t\t\t\t\t'Accept': 'application/json',\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tconst req = https.request(options, (res) => {\n\t\t\t\tlet data = ''\n\n\t\t\t\tres.on('data', (chunk) => {\n\t\t\t\t\tdata += chunk\n\t\t\t\t})\n\n\t\t\t\tres.on('end', () => {\n\t\t\t\t\tif (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {\n\t\t\t\t\t\treject(new Error(`BitBucket API error (${res.statusCode}): ${data}`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle empty response\n\t\t\t\t\tif (res.statusCode === 204 || !data) {\n\t\t\t\t\t\tresolve({} as T)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(data) as T)\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treject(new Error(`Failed to parse BitBucket API response: ${error}`))\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\n\t\t\treq.on('error', (error) => {\n\t\t\t\treject(new Error(`BitBucket API request failed: ${error.message}`))\n\t\t\t})\n\n\t\t\tif (body) {\n\t\t\t\treq.write(JSON.stringify(body))\n\t\t\t}\n\n\t\t\treq.end()\n\t\t})\n\t}\n\n\t/**\n\t * Make a GET request to BitBucket API\n\t */\n\tprivate async get<T>(endpoint: string): Promise<T> {\n\t\treturn this.request<T>('GET', endpoint)\n\t}\n\n\t/**\n\t * Make a POST request to BitBucket API\n\t */\n\tprivate async post<T>(endpoint: string, body: unknown): Promise<T> {\n\t\treturn this.request<T>('POST', endpoint, body)\n\t}\n\n\t/**\n\t * Make a PUT request to BitBucket API\n\t */\n\tprivate async put<T>(endpoint: string, body: unknown): Promise<T> {\n\t\treturn this.request<T>('PUT', endpoint, body)\n\t}\n\n\t/**\n\t * Get repository information\n\t */\n\tasync getRepository(workspace: string, repoSlug: string): Promise<BitBucketRepository> {\n\t\treturn this.get<BitBucketRepository>(`/repositories/${workspace}/${repoSlug}`)\n\t}\n\n\t/**\n\t * Get a pull request by ID\n\t */\n\tasync getPullRequest(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tprId: number\n\t): Promise<BitBucketPullRequest> {\n\t\treturn this.get<BitBucketPullRequest>(\n\t\t\t`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}`\n\t\t)\n\t}\n\n\t/**\n\t * List open pull requests for a branch\n\t *\n\t * Note: BitBucket uses BBQL (BitBucket Query Language) for filtering.\n\t * The q parameter must use the format: q=source.branch.name=\"branch-name\"\n\t * When using BBQL, we include state filter in the query to ensure it's applied.\n\t * See: https://developer.atlassian.com/cloud/bitbucket/rest/intro/#filtering\n\t */\n\tasync listPullRequests(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tsourceBranch?: string\n\t): Promise<BitBucketPullRequest[]> {\n\t\tlet endpoint = `/repositories/${workspace}/${repoSlug}/pullrequests`\n\n\t\tif (sourceBranch) {\n\t\t\t// Use BBQL query syntax for filtering by source branch AND state\n\t\t\t// Include state=\"OPEN\" in the query to exclude DECLINED/MERGED/SUPERSEDED PRs\n\t\t\tconst safeBranch = sourceBranch.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"')\n\t\t\tconst query = `state=\"OPEN\" AND source.branch.name=\"${safeBranch}\"`\n\t\t\tendpoint += `?q=${encodeURIComponent(query)}`\n\t\t} else {\n\t\t\t// No branch filter, just filter by state\n\t\t\tendpoint += `?state=OPEN`\n\t\t}\n\n\t\tconst response = await this.get<{ values: BitBucketPullRequest[] }>(endpoint)\n\t\treturn response.values\n\t}\n\n\t/**\n\t * Create a pull request\n\t */\n\tasync createPullRequest(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\ttitle: string,\n\t\tdescription: string,\n\t\tsourceBranch: string,\n\t\tdestinationBranch: string,\n\t\treviewerAccountIds?: string[]\n\t): Promise<BitBucketPullRequest> {\n\t\tconst payload: Record<string, unknown> = {\n\t\t\ttitle,\n\t\t\tdescription,\n\t\t\tsource: {\n\t\t\t\tbranch: {\n\t\t\t\t\tname: sourceBranch,\n\t\t\t\t},\n\t\t\t},\n\t\t\tdestination: {\n\t\t\t\tbranch: {\n\t\t\t\t\tname: destinationBranch,\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\t// Add reviewers if provided\n\t\tif (reviewerAccountIds && reviewerAccountIds.length > 0) {\n\t\t\tpayload.reviewers = reviewerAccountIds.map(id => ({ account_id: id }))\n\t\t}\n\n\t\treturn this.post<BitBucketPullRequest>(\n\t\t\t`/repositories/${workspace}/${repoSlug}/pullrequests`,\n\t\t\tpayload\n\t\t)\n\t}\n\n\t/**\n\t * Add a comment to a pull request\n\t */\n\tasync addPRComment(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tprId: number,\n\t\tcontent: string\n\t): Promise<BitBucketComment> {\n\t\treturn this.post<BitBucketComment>(\n\t\t\t`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\traw: content,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t}\n\n\t/**\n\t * Update an existing comment on a pull request\n\t */\n\tasync updatePRComment(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tprId: number,\n\t\tcommentId: number,\n\t\tcontent: string\n\t): Promise<BitBucketComment> {\n\t\treturn this.put<BitBucketComment>(\n\t\t\t`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments/${commentId}`,\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\traw: content,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t}\n\n\t/**\n\t * List all comments on a pull request with pagination\n\t */\n\tasync listPRComments(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tprId: number\n\t): Promise<BitBucketComment[]> {\n\t\tconst MAX_PAGES = 50\n\t\tconst allComments: BitBucketComment[] = []\n\t\tlet nextUrl: string | null = `/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`\n\t\tlet pageCount = 0\n\n\t\twhile (nextUrl) {\n\t\t\tpageCount++\n\t\t\tif (pageCount > MAX_PAGES) {\n\t\t\t\tconsole.error(`BitBucket listPRComments: exceeded maximum pagination limit of ${MAX_PAGES} pages, returning ${allComments.length} comments collected so far`)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconst response: { values: BitBucketComment[]; next?: string } =\n\t\t\t\tawait this.get(nextUrl)\n\n\t\t\tallComments.push(...response.values)\n\n\t\t\t// BitBucket pagination uses 'next' field with full URL\n\t\t\tnextUrl = response.next ?? null\n\t\t}\n\n\t\tgetLogger().debug(`Fetched ${allComments.length} PR comments from BitBucket`)\n\t\treturn allComments\n\t}\n\n\t/**\n\t * Add an inline comment to a specific file and line in a pull request\n\t */\n\tasync addInlinePRComment(\n\t\tworkspace: string,\n\t\trepoSlug: string,\n\t\tprId: number,\n\t\tcontent: string,\n\t\tfilePath: string,\n\t\tline: number\n\t): Promise<BitBucketComment> {\n\t\treturn this.post<BitBucketComment>(\n\t\t\t`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,\n\t\t\t{\n\t\t\t\tcontent: {\n\t\t\t\t\traw: content,\n\t\t\t\t},\n\t\t\t\tinline: {\n\t\t\t\t\tto: line,\n\t\t\t\t\tpath: filePath,\n\t\t\t\t},\n\t\t\t}\n\t\t)\n\t}\n\n\t/**\n\t * Find workspace members by usernames\n\t * Returns a map of username -> account_id for resolved users\n\t * Handles pagination to fetch all workspace members\n\t */\n\tasync findUsersByUsername(\n\t\tworkspace: string,\n\t\tusernames: string[]\n\t): Promise<Map<string, string>> {\n\t\tconst result = new Map<string, string>()\n\n\t\t// Fetch all workspace members with pagination\n\t\tconst allMembers = await this.getAllWorkspaceMembers(workspace)\n\n\t\tgetLogger().debug(`Resolving ${usernames.length} usernames against ${allMembers.length} workspace members`)\n\n\t\t// Match usernames against fetched members\n\t\tfor (const username of usernames) {\n\t\t\tconst usernameLower = username.toLowerCase()\n\t\t\tconst member = allMembers.find(m =>\n\t\t\t\tm.user.nickname?.toLowerCase() === usernameLower ||\n\t\t\t\tm.user.display_name.toLowerCase() === usernameLower\n\t\t\t)\n\n\t\t\tif (member) {\n\t\t\t\tresult.set(username, member.user.account_id)\n\t\t\t\tgetLogger().debug(`Resolved reviewer ${username} to account ID ${member.user.account_id}`)\n\t\t\t} else {\n\t\t\t\tgetLogger().warn(`Could not resolve reviewer ${username} to a BitBucket account ID`)\n\t\t\t}\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * Fetch all workspace members with pagination\n\t */\n\tprivate async getAllWorkspaceMembers(workspace: string): Promise<BitBucketWorkspaceMember[]> {\n\t\tconst allMembers: BitBucketWorkspaceMember[] = []\n\t\tlet nextUrl: string | null = `/workspaces/${workspace}/members`\n\n\t\twhile (nextUrl) {\n\t\t\tconst response: BitBucketWorkspaceMembersResponse =\n\t\t\t\tawait this.get(nextUrl)\n\n\t\t\tallMembers.push(...response.values)\n\n\t\t\t// BitBucket pagination uses 'next' field with full URL\n\t\t\t// Use it directly since request() now handles full URLs\n\t\t\tnextUrl = response.next ?? null\n\t\t}\n\n\t\tgetLogger().debug(`Fetched ${allMembers.length} workspace members from BitBucket`)\n\t\treturn allMembers\n\t}\n\n\t/**\n\t * Get the currently authenticated user\n\t */\n\tasync getCurrentUser(): Promise<BitBucketCurrentUser> {\n\t\treturn this.get<BitBucketCurrentUser>('/user')\n\t}\n\n\t/**\n\t * Test connection to BitBucket API\n\t */\n\tasync testConnection(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.getCurrentUser()\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tgetLogger().error('BitBucket connection test failed', { error })\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Get configured workspace\n\t */\n\tgetWorkspace(): string | undefined {\n\t\treturn this.workspace\n\t}\n\n\t/**\n\t * Get configured repository slug\n\t */\n\tgetRepoSlug(): string | undefined {\n\t\treturn this.repoSlug\n\t}\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
generateIssueManagementMcpConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CQHHEW2M.js";
|
|
5
5
|
import {
|
|
6
6
|
openBrowser
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WEBMMJKL.js";
|
|
8
8
|
import {
|
|
9
9
|
waitForKeypress
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NPVA65KS.js";
|
|
11
11
|
import {
|
|
12
12
|
launchClaude
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-DDHWZNGL.js";
|
|
14
14
|
import {
|
|
15
15
|
getLogger
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-FTYWGQFM.js";
|
|
17
17
|
|
|
18
18
|
// src/lib/IssueEnhancementService.ts
|
|
19
19
|
var IssueEnhancementService = class {
|
|
@@ -243,4 +243,4 @@ IMPORTANT: When you create your analysis comment, tag @${author} in the "Questio
|
|
|
243
243
|
export {
|
|
244
244
|
IssueEnhancementService
|
|
245
245
|
};
|
|
246
|
-
//# sourceMappingURL=chunk-
|
|
246
|
+
//# sourceMappingURL=chunk-PH65MFQM.js.map
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
IssueTrackerFactory
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-35CBWAJL.js";
|
|
5
5
|
import {
|
|
6
6
|
getLinearIssueDependencies
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DMSL5BAP.js";
|
|
8
8
|
import {
|
|
9
9
|
getIssueDependencies
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KV4NU3RP.js";
|
|
11
11
|
import {
|
|
12
12
|
getLogger
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-FTYWGQFM.js";
|
|
14
14
|
import {
|
|
15
15
|
logger
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-VRPPI6GU.js";
|
|
17
17
|
|
|
18
18
|
// src/utils/list-children.ts
|
|
19
19
|
async function fetchChildIssues(parentIssueNumber, issueTracker, repo) {
|
|
@@ -204,4 +204,4 @@ export {
|
|
|
204
204
|
fetchChildIssueDetails,
|
|
205
205
|
buildDependencyMap
|
|
206
206
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
207
|
+
//# sourceMappingURL=chunk-PMB6TYV4.js.map
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
BitBucketApiClient
|
|
4
|
+
} from "./chunk-P5MXXHXQ.js";
|
|
5
|
+
import {
|
|
6
|
+
parseGitRemotes
|
|
7
|
+
} from "./chunk-BZ7KTXPB.js";
|
|
8
|
+
import {
|
|
9
|
+
getLogger
|
|
10
|
+
} from "./chunk-FTYWGQFM.js";
|
|
11
|
+
|
|
12
|
+
// src/lib/providers/bitbucket/BitBucketVCSProvider.ts
|
|
13
|
+
var BitBucketVCSProvider = class _BitBucketVCSProvider {
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.providerName = "bitbucket";
|
|
16
|
+
this.supportsForks = true;
|
|
17
|
+
this.supportsDraftPRs = false;
|
|
18
|
+
this.client = new BitBucketApiClient(config);
|
|
19
|
+
if (config.reviewers) {
|
|
20
|
+
this.reviewerUsernames = config.reviewers;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a BitBucketVCSProvider from IloomSettings
|
|
25
|
+
* Extracts and validates BitBucket config from settings
|
|
26
|
+
*/
|
|
27
|
+
static fromSettings(settings) {
|
|
28
|
+
var _a;
|
|
29
|
+
const bbSettings = (_a = settings.versionControl) == null ? void 0 : _a.bitbucket;
|
|
30
|
+
if (!(bbSettings == null ? void 0 : bbSettings.username)) {
|
|
31
|
+
throw new Error("BitBucket username is required. Configure versionControl.bitbucket.username in .iloom/settings.json");
|
|
32
|
+
}
|
|
33
|
+
if (!(bbSettings == null ? void 0 : bbSettings.apiToken)) {
|
|
34
|
+
throw new Error("BitBucket API token is required. Configure versionControl.bitbucket.apiToken in .iloom/settings.local.json");
|
|
35
|
+
}
|
|
36
|
+
const config = {
|
|
37
|
+
username: bbSettings.username,
|
|
38
|
+
apiToken: bbSettings.apiToken
|
|
39
|
+
};
|
|
40
|
+
if (bbSettings.workspace) {
|
|
41
|
+
config.workspace = bbSettings.workspace;
|
|
42
|
+
}
|
|
43
|
+
if (bbSettings.repoSlug) {
|
|
44
|
+
config.repoSlug = bbSettings.repoSlug;
|
|
45
|
+
}
|
|
46
|
+
if (bbSettings.reviewers) {
|
|
47
|
+
config.reviewers = bbSettings.reviewers;
|
|
48
|
+
}
|
|
49
|
+
return new _BitBucketVCSProvider(config);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check if a PR already exists for the given branch
|
|
53
|
+
*/
|
|
54
|
+
async checkForExistingPR(branchName, cwd) {
|
|
55
|
+
try {
|
|
56
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
57
|
+
const prs = await this.client.listPullRequests(workspace, repoSlug, branchName);
|
|
58
|
+
if (prs.length > 0 && prs[0]) {
|
|
59
|
+
const pr = prs[0];
|
|
60
|
+
return {
|
|
61
|
+
number: pr.id,
|
|
62
|
+
url: pr.links.html.href
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if (error instanceof Error) {
|
|
68
|
+
const statusMatch = error.message.match(/BitBucket API error \((\d+)\)/);
|
|
69
|
+
if (statusMatch == null ? void 0 : statusMatch[1]) {
|
|
70
|
+
const statusCode = parseInt(statusMatch[1], 10);
|
|
71
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
getLogger().debug("Error checking for existing PR", { error });
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Create a pull request
|
|
82
|
+
*/
|
|
83
|
+
async createPR(branchName, title, body, baseBranch, cwd) {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
86
|
+
getLogger().info(`Creating BitBucket PR in ${workspace}/${repoSlug}`);
|
|
87
|
+
getLogger().debug("PR details", { branchName, title, baseBranch });
|
|
88
|
+
let reviewerIds;
|
|
89
|
+
if (this.reviewerUsernames && this.reviewerUsernames.length > 0) {
|
|
90
|
+
reviewerIds = await this.resolveReviewerUsernames(workspace, this.reviewerUsernames);
|
|
91
|
+
if (reviewerIds.length > 0) {
|
|
92
|
+
const currentUser = await this.client.getCurrentUser();
|
|
93
|
+
const originalCount = reviewerIds.length;
|
|
94
|
+
reviewerIds = reviewerIds.filter((id) => id !== currentUser.account_id);
|
|
95
|
+
if (reviewerIds.length < originalCount) {
|
|
96
|
+
getLogger().debug(
|
|
97
|
+
`Removed current user (${currentUser.display_name}) from reviewers list - PR author cannot be a reviewer`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const pr = await this.client.createPullRequest(
|
|
103
|
+
workspace,
|
|
104
|
+
repoSlug,
|
|
105
|
+
title,
|
|
106
|
+
body,
|
|
107
|
+
branchName,
|
|
108
|
+
baseBranch,
|
|
109
|
+
reviewerIds
|
|
110
|
+
);
|
|
111
|
+
if (!(pr == null ? void 0 : pr.id) || !((_b = (_a = pr == null ? void 0 : pr.links) == null ? void 0 : _a.html) == null ? void 0 : _b.href)) {
|
|
112
|
+
getLogger().error("Invalid BitBucket API response", { pr });
|
|
113
|
+
throw new Error(
|
|
114
|
+
`BitBucket API returned invalid PR response. Expected PR with id and links.html.href, got: ${JSON.stringify(pr)}`
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
getLogger().info(`BitBucket PR #${pr.id} created successfully`);
|
|
118
|
+
return { url: pr.links.html.href, number: pr.id, wasExisting: false };
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Fetch PR details
|
|
122
|
+
*/
|
|
123
|
+
async fetchPR(prNumber, cwd) {
|
|
124
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
125
|
+
const bbPR = await this.client.getPullRequest(workspace, repoSlug, prNumber);
|
|
126
|
+
return this.mapBitBucketPRToPullRequest(bbPR);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get PR URL
|
|
130
|
+
*/
|
|
131
|
+
async getPRUrl(prNumber, cwd) {
|
|
132
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
133
|
+
const bbPR = await this.client.getPullRequest(workspace, repoSlug, prNumber);
|
|
134
|
+
return bbPR.links.html.href;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Create a comment on a PR
|
|
138
|
+
*/
|
|
139
|
+
async createPRComment(prNumber, body, cwd) {
|
|
140
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
141
|
+
getLogger().debug("Creating BitBucket PR comment", { workspace, repoSlug, prNumber });
|
|
142
|
+
const comment = await this.client.addPRComment(workspace, repoSlug, prNumber, body);
|
|
143
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Update an existing comment on a PR
|
|
147
|
+
*/
|
|
148
|
+
async updatePRComment(prNumber, commentId, body, cwd) {
|
|
149
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
150
|
+
getLogger().debug("Updating BitBucket PR comment", { workspace, repoSlug, prNumber, commentId });
|
|
151
|
+
const numericCommentId = parseInt(commentId, 10);
|
|
152
|
+
if (isNaN(numericCommentId)) {
|
|
153
|
+
throw new Error(`Invalid comment ID "${commentId}": expected a numeric value`);
|
|
154
|
+
}
|
|
155
|
+
const comment = await this.client.updatePRComment(workspace, repoSlug, prNumber, numericCommentId, body);
|
|
156
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get inline review comments on a PR
|
|
160
|
+
* Fetches all comments and filters for those with inline metadata
|
|
161
|
+
*/
|
|
162
|
+
async getReviewComments(prNumber, cwd) {
|
|
163
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
164
|
+
getLogger().debug("Fetching BitBucket PR review comments", { workspace, repoSlug, prNumber });
|
|
165
|
+
const allComments = await this.client.listPRComments(workspace, repoSlug, prNumber);
|
|
166
|
+
const inlineComments = [];
|
|
167
|
+
for (const c of allComments) {
|
|
168
|
+
if (c.inline == null) continue;
|
|
169
|
+
inlineComments.push({
|
|
170
|
+
id: String(c.id),
|
|
171
|
+
body: c.content.raw,
|
|
172
|
+
path: c.inline.path,
|
|
173
|
+
line: c.inline.to ?? c.inline.from ?? null,
|
|
174
|
+
side: null,
|
|
175
|
+
// BitBucket doesn't have a "side" concept like GitHub
|
|
176
|
+
author: c.user ? { id: c.user.uuid, displayName: c.user.display_name } : null,
|
|
177
|
+
createdAt: c.created_on ?? "",
|
|
178
|
+
updatedAt: c.updated_on ?? null,
|
|
179
|
+
inReplyToId: null
|
|
180
|
+
// BitBucket uses nested comments, not reply chains
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
return inlineComments;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Create an inline review comment on a specific file and line in a PR
|
|
187
|
+
*/
|
|
188
|
+
async createReviewComment(prNumber, path, line, body, cwd) {
|
|
189
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
190
|
+
getLogger().debug("Creating BitBucket inline PR comment", { workspace, repoSlug, prNumber, path, line });
|
|
191
|
+
const comment = await this.client.addInlinePRComment(workspace, repoSlug, prNumber, body, path, line);
|
|
192
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* List open pull requests for the repository
|
|
196
|
+
* Uses getWorkspaceAndRepo for auto-detection from git remotes
|
|
197
|
+
*/
|
|
198
|
+
async listPullRequests(cwd) {
|
|
199
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
200
|
+
return this.client.listPullRequests(workspace, repoSlug);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Detect repository from git remote
|
|
204
|
+
*/
|
|
205
|
+
async detectRepository(cwd) {
|
|
206
|
+
try {
|
|
207
|
+
const remotes = await parseGitRemotes(cwd);
|
|
208
|
+
const bbRemote = remotes.find(
|
|
209
|
+
(r) => r.url.includes("bitbucket.org")
|
|
210
|
+
);
|
|
211
|
+
if (!bbRemote) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return {
|
|
215
|
+
owner: bbRemote.owner,
|
|
216
|
+
// workspace
|
|
217
|
+
repo: bbRemote.repo
|
|
218
|
+
};
|
|
219
|
+
} catch (error) {
|
|
220
|
+
getLogger().error("Failed to detect BitBucket repository", { error });
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Get target remote for PR operations
|
|
226
|
+
*/
|
|
227
|
+
async getTargetRemote(_cwd) {
|
|
228
|
+
return "origin";
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get workspace and repository slug from config or git remote
|
|
232
|
+
*/
|
|
233
|
+
async getWorkspaceAndRepo(cwd) {
|
|
234
|
+
let workspace = this.client.getWorkspace();
|
|
235
|
+
let repoSlug = this.client.getRepoSlug();
|
|
236
|
+
if (!workspace || !repoSlug) {
|
|
237
|
+
const detected = await this.detectRepository(cwd);
|
|
238
|
+
if (!detected) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
"Could not determine BitBucket workspace/repository. Either configure them in settings or ensure git remote points to bitbucket.org"
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
workspace = workspace ?? detected.owner;
|
|
244
|
+
repoSlug = repoSlug ?? detected.repo;
|
|
245
|
+
}
|
|
246
|
+
return { workspace, repoSlug };
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Resolve reviewer usernames to BitBucket account IDs
|
|
250
|
+
* Warns for any usernames that cannot be resolved but continues with partial list
|
|
251
|
+
*/
|
|
252
|
+
async resolveReviewerUsernames(workspace, usernames) {
|
|
253
|
+
getLogger().debug(`Resolving ${usernames.length} reviewer username(s) to BitBucket account IDs`);
|
|
254
|
+
const usernameToAccountId = await this.client.findUsersByUsername(workspace, usernames);
|
|
255
|
+
const resolvedIds = [];
|
|
256
|
+
const unresolvedUsernames = [];
|
|
257
|
+
for (const username of usernames) {
|
|
258
|
+
const accountId = usernameToAccountId.get(username);
|
|
259
|
+
if (accountId) {
|
|
260
|
+
resolvedIds.push(accountId);
|
|
261
|
+
} else {
|
|
262
|
+
unresolvedUsernames.push(username);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (unresolvedUsernames.length > 0) {
|
|
266
|
+
getLogger().warn(
|
|
267
|
+
`Could not resolve ${unresolvedUsernames.length} reviewer username(s) to BitBucket account IDs: ${unresolvedUsernames.join(", ")}. These reviewers will not be added to the PR.`
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
if (resolvedIds.length > 0) {
|
|
271
|
+
getLogger().info(`Resolved ${resolvedIds.length} reviewer(s) for PR`);
|
|
272
|
+
}
|
|
273
|
+
return resolvedIds;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Map BitBucket PR to generic PullRequest type
|
|
277
|
+
*/
|
|
278
|
+
mapBitBucketPRToPullRequest(bbPR) {
|
|
279
|
+
let state;
|
|
280
|
+
if (bbPR.state === "OPEN") {
|
|
281
|
+
state = "open";
|
|
282
|
+
} else if (bbPR.state === "MERGED") {
|
|
283
|
+
state = "merged";
|
|
284
|
+
} else {
|
|
285
|
+
state = "closed";
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
number: bbPR.id,
|
|
289
|
+
title: bbPR.title,
|
|
290
|
+
body: bbPR.description,
|
|
291
|
+
state,
|
|
292
|
+
branch: bbPR.source.branch.name,
|
|
293
|
+
baseBranch: bbPR.destination.branch.name,
|
|
294
|
+
url: bbPR.links.html.href,
|
|
295
|
+
isDraft: false
|
|
296
|
+
// BitBucket doesn't have draft PRs
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
export {
|
|
302
|
+
BitBucketVCSProvider
|
|
303
|
+
};
|
|
304
|
+
//# sourceMappingURL=chunk-QC65IOV3.js.map
|