@iloom/cli 0.11.1 → 0.13.0-beta.0
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 +170 -15
- 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-RRGREEZQ.js +14 -0
- package/dist/ClaudeService-LEPW6QAC.js +13 -0
- package/dist/GitHubService-UTAYZXL3.js +12 -0
- package/dist/IssueTrackerFactory-KE2BDCLC.js +15 -0
- package/dist/{LoomLauncher-5AZU2F5I.js → LoomLauncher-GKQMR5E6.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 +170 -15
- package/dist/{SettingsManager-WQ5NSGAH.js → SettingsManager-KQU7OX7G.js} +15 -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-V3KADFMO.js +27 -0
- package/dist/{chunk-XXFSOVL3.js → chunk-3XEXT35Z.js} +4 -4
- package/dist/{chunk-YRCEOQPX.js → chunk-4JZEQBWV.js} +4 -3
- package/dist/chunk-4JZEQBWV.js.map +1 -0
- package/dist/{chunk-LE2NOUTN.js → chunk-4VQXMEEP.js} +3 -3
- 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-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-SQYHPBFP.js → chunk-EGNUOALL.js} +2 -2
- package/dist/{chunk-ZAXRQLK3.js → chunk-FTYWGQFM.js} +2 -2
- package/dist/{chunk-5PNZBH6V.js → chunk-H3T3EPF3.js} +2 -2
- package/dist/{chunk-VNYWBHKR.js → chunk-JD3K2344.js} +3 -3
- package/dist/{chunk-6YVJVUR4.js → chunk-JDN4SPV3.js} +3 -3
- package/dist/{chunk-NCPZYQ4B.js → chunk-K3QGG4O2.js} +2 -2
- package/dist/{chunk-ABVMUNCD.js → chunk-KQSV7FOG.js} +64 -10
- package/dist/chunk-KQSV7FOG.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-GMDSYLI6.js → chunk-MY2Q3FJ3.js} +2 -2
- package/dist/{chunk-CV47VCMQ.js → chunk-NPVA65KS.js} +2 -2
- package/dist/{chunk-RMLADZRY.js → chunk-NTDY5AMO.js} +5 -5
- package/dist/{chunk-UHIBKD73.js → chunk-NUUFP53X.js} +13 -32
- package/dist/{chunk-UHIBKD73.js.map → chunk-NUUFP53X.js.map} +1 -1
- package/dist/{chunk-7OCGBJLR.js → chunk-OIVFHJOA.js} +2 -2
- package/dist/chunk-P5MXXHXQ.js +284 -0
- package/dist/chunk-P5MXXHXQ.js.map +1 -0
- package/dist/{chunk-TEJAGQX2.js → chunk-PD75ZCFT.js} +35 -35
- package/dist/chunk-PD75ZCFT.js.map +1 -0
- package/dist/{chunk-NN5RYWXA.js → chunk-PH65MFQM.js} +6 -6
- package/dist/{chunk-LL6TOX3G.js → chunk-Q7VXHJP6.js} +10 -10
- package/dist/chunk-Q7VXHJP6.js.map +1 -0
- package/dist/chunk-QC65IOV3.js +304 -0
- package/dist/chunk-QC65IOV3.js.map +1 -0
- package/dist/{chunk-V4STTBQD.js → chunk-QED2WB2D.js} +9 -9
- package/dist/{chunk-3RXYOBME.js → chunk-QNPJXO53.js} +5 -5
- package/dist/{chunk-3RXYOBME.js.map → chunk-QNPJXO53.js.map} +1 -1
- package/dist/chunk-QQULYI2S.js +696 -0
- package/dist/chunk-QQULYI2S.js.map +1 -0
- package/dist/{chunk-QNHZM5ZV.js → chunk-QXGM32TO.js} +3 -3
- package/dist/{chunk-TZNNJLGT.js → chunk-RFCAPHL5.js} +6 -6
- package/dist/{chunk-7FIXNAUO.js → chunk-SA446KA2.js} +66 -43
- package/dist/chunk-SA446KA2.js.map +1 -0
- package/dist/{chunk-UDCI3QTS.js → chunk-SN4S5CWL.js} +2 -2
- package/dist/{chunk-VUUN3KE4.js → chunk-TAEVA4QR.js} +8 -8
- package/dist/chunk-TAEVA4QR.js.map +1 -0
- package/dist/{chunk-IR74O2F6.js → chunk-TN2D2RX7.js} +253 -174
- package/dist/chunk-TN2D2RX7.js.map +1 -0
- 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-XFQGI2E3.js → chunk-VVQQIG64.js} +58 -53
- package/dist/chunk-VVQQIG64.js.map +1 -0
- package/dist/{chunk-YETJNRQM.js → chunk-WEBMMJKL.js} +2 -1
- package/dist/{chunk-ET6A2JR4.js → chunk-WGUGB54H.js} +120 -18
- package/dist/chunk-WGUGB54H.js.map +1 -0
- package/dist/{chunk-QR4FU53I.js → chunk-X5DRLONY.js} +22 -12
- package/dist/chunk-X5DRLONY.js.map +1 -0
- package/dist/{chunk-KQFIGI37.js → chunk-XCP2WDYA.js} +7 -7
- package/dist/{chunk-VMZG66UV.js → chunk-YUOVWWJX.js} +312 -7
- package/dist/chunk-YUOVWWJX.js.map +1 -0
- package/dist/{chunk-HLDY5S4C.js → chunk-ZUIFO7B4.js} +3 -3
- package/dist/{claude-ONQTDWV3.js → claude-ACL7G4CF.js} +4 -4
- package/dist/{cleanup-YOM6PQCN.js → cleanup-RJKLI47I.js} +40 -37
- package/dist/cleanup-RJKLI47I.js.map +1 -0
- package/dist/cli.js +322 -169
- package/dist/cli.js.map +1 -1
- package/dist/{color-VQD52LOI.js → color-AC6F2QE7.js} +3 -3
- package/dist/{commit-DC2Q5CDY.js → commit-SUHRUMDE.js} +15 -15
- package/dist/{compile-4NCQECKE.js → compile-2MD346PO.js} +11 -11
- package/dist/{contribute-M5UWXCAV.js → contribute-P4BMRY7C.js} +11 -11
- package/dist/{contribute-M5UWXCAV.js.map → contribute-P4BMRY7C.js.map} +1 -1
- package/dist/{mcp/darwin-3JFFE3W2.js → darwin-5K3I4FTH.js} +2 -2
- package/dist/database-helpers-PRDFNDRO.js +11 -0
- package/dist/{dev-server-CYRP6M73.js → dev-server-ZNTLWOL5.js} +35 -21
- package/dist/dev-server-ZNTLWOL5.js.map +1 -0
- package/dist/{feedback-BMAZGKRW.js → feedback-Q6WG2WX4.js} +17 -17
- package/dist/{git-BXUD6CL5.js → git-TX2IEMB3.js} +6 -6
- package/dist/ignite-P644W2PK.js +35 -0
- package/dist/index.d.ts +236 -18
- package/dist/index.js +180 -63
- package/dist/index.js.map +1 -1
- package/dist/{init-CI43GJHV.js → init-5HFY7JG6.js} +18 -18
- package/dist/{install-deps-SRTM5U7D.js → install-deps-J4ALTM27.js} +11 -11
- package/dist/{installation-detector-HF6QN7KP.js → installation-detector-PYAZ2O6U.js} +3 -3
- package/dist/{issues-DMRQJH7E.js → issues-LZMIF22U.js} +69 -56
- package/dist/issues-LZMIF22U.js.map +1 -0
- package/dist/lint-XIXKU22H.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 +908 -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/{open-2Y7GSUTJ.js → open-KUO35JIJ.js} +36 -21
- package/dist/open-KUO35JIJ.js.map +1 -0
- package/dist/{plan-SWFPLNJE.js → plan-7CF56OIR.js} +47 -43
- package/dist/{plan-SWFPLNJE.js.map → plan-7CF56OIR.js.map} +1 -1
- 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 +184 -23
- package/dist/prompts/issue-prompt.txt +94 -158
- package/dist/prompts/plan-prompt.txt +55 -0
- package/dist/prompts/regular-prompt.txt +1 -1
- package/dist/prompts/swarm-orchestrator-prompt.txt +78 -21
- package/dist/{rebase-S6OHAOOF.js → rebase-MAMWPA2L.js} +12 -12
- package/dist/{recap-GGVCG5VH.js → recap-IDBO3KM5.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-RGZHCQ6M.js} +36 -21
- package/dist/run-RGZHCQ6M.js.map +1 -0
- package/dist/schema/settings.schema.json +171 -11
- package/dist/{shell-W4SBQPTE.js → shell-7ADCDFIV.js} +8 -8
- package/dist/{summary-P2JCIIJO.js → summary-7J2HORFD.js} +21 -19
- package/dist/summary-7J2HORFD.js.map +1 -0
- package/dist/test-SRB7EWU6.js +27 -0
- package/dist/{test-git-2KFFAQ6B.js → test-git-G7ATVIXG.js} +6 -6
- package/dist/{test-jira-FKDKG6CD.js → test-jira-Q2HPA522.js} +8 -8
- package/dist/{test-prefix-GP2DAX37.js → test-prefix-JMDGXR5A.js} +6 -6
- package/dist/{test-tabs-YDWMWTVA.js → test-tabs-NGPTFD5T.js} +2 -2
- package/dist/{test-webserver-QI3QQFZ3.js → test-webserver-GZFVXBGD.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-3I7ISHUU.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-VMZG66UV.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/cleanup-YOM6PQCN.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/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-RRGREEZQ.js.map} +0 -0
- /package/dist/{IssueTrackerFactory-XN6MQ4UN.js.map → ClaudeService-LEPW6QAC.js.map} +0 -0
- /package/dist/{MetadataManager-CMQQTFLQ.js.map → GitHubService-UTAYZXL3.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-IC6NAFGY.js.map → IssueTrackerFactory-KE2BDCLC.js.map} +0 -0
- /package/dist/{LoomLauncher-5AZU2F5I.js.map → LoomLauncher-GKQMR5E6.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-KQU7OX7G.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-V3KADFMO.js.map} +0 -0
- /package/dist/{chunk-XXFSOVL3.js.map → chunk-3XEXT35Z.js.map} +0 -0
- /package/dist/{chunk-LE2NOUTN.js.map → chunk-4VQXMEEP.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-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-5PNZBH6V.js.map → chunk-H3T3EPF3.js.map} +0 -0
- /package/dist/{chunk-VNYWBHKR.js.map → chunk-JD3K2344.js.map} +0 -0
- /package/dist/{chunk-6YVJVUR4.js.map → chunk-JDN4SPV3.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-RMLADZRY.js.map → chunk-NTDY5AMO.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-V4STTBQD.js.map → chunk-QED2WB2D.js.map} +0 -0
- /package/dist/{chunk-QNHZM5ZV.js.map → chunk-QXGM32TO.js.map} +0 -0
- /package/dist/{chunk-TZNNJLGT.js.map → chunk-RFCAPHL5.js.map} +0 -0
- /package/dist/{chunk-UDCI3QTS.js.map → chunk-SN4S5CWL.js.map} +0 -0
- /package/dist/{chunk-YETJNRQM.js.map → chunk-WEBMMJKL.js.map} +0 -0
- /package/dist/{chunk-KQFIGI37.js.map → chunk-XCP2WDYA.js.map} +0 -0
- /package/dist/{chunk-HLDY5S4C.js.map → chunk-ZUIFO7B4.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-SUHRUMDE.js.map} +0 -0
- /package/dist/{compile-4NCQECKE.js.map → compile-2MD346PO.js.map} +0 -0
- /package/dist/{installation-detector-HF6QN7KP.js.map → darwin-5K3I4FTH.js.map} +0 -0
- /package/dist/{mcp/darwin-3JFFE3W2.js.map → database-helpers-PRDFNDRO.js.map} +0 -0
- /package/dist/{feedback-BMAZGKRW.js.map → feedback-Q6WG2WX4.js.map} +0 -0
- /package/dist/{neon-helpers-HWIYRKOW.js.map → git-TX2IEMB3.js.map} +0 -0
- /package/dist/{prompt-7LZB4PAT.js.map → ignite-P644W2PK.js.map} +0 -0
- /package/dist/{init-CI43GJHV.js.map → init-5HFY7JG6.js.map} +0 -0
- /package/dist/{install-deps-SRTM5U7D.js.map → install-deps-J4ALTM27.js.map} +0 -0
- /package/dist/{remote-MZTFHHTU.js.map → installation-detector-PYAZ2O6U.js.map} +0 -0
- /package/dist/{lint-BSWRMGPZ.js.map → lint-XIXKU22H.js.map} +0 -0
- /package/dist/{linux-RYLOP2LY.js.map → linux-WUGRYCJY.js.map} +0 -0
- /package/dist/{update-notifier-EYLAXZAA.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/{projects-IUSUXD5D.js.map → projects-L5AHUBGA.js.map} +0 -0
- /package/dist/{rebase-S6OHAOOF.js.map → rebase-MAMWPA2L.js.map} +0 -0
- /package/dist/{recap-GGVCG5VH.js.map → recap-IDBO3KM5.js.map} +0 -0
- /package/dist/{shell-W4SBQPTE.js.map → shell-7ADCDFIV.js.map} +0 -0
- /package/dist/{test-6JH4FE2X.js.map → test-SRB7EWU6.js.map} +0 -0
- /package/dist/{test-git-2KFFAQ6B.js.map → test-git-G7ATVIXG.js.map} +0 -0
- /package/dist/{test-jira-FKDKG6CD.js.map → test-jira-Q2HPA522.js.map} +0 -0
- /package/dist/{test-prefix-GP2DAX37.js.map → test-prefix-JMDGXR5A.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-GZFVXBGD.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-3I7ISHUU.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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
logger
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4HZMW2V3.js";
|
|
5
5
|
|
|
6
6
|
// src/mcp/issue-management-server.ts
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -2398,7 +2398,7 @@ async function promptConfirmation(message, defaultValue = false) {
|
|
|
2398
2398
|
}
|
|
2399
2399
|
|
|
2400
2400
|
// src/lib/providers/jira/JiraIssueTracker.ts
|
|
2401
|
-
var JiraIssueTracker = class {
|
|
2401
|
+
var JiraIssueTracker = class _JiraIssueTracker {
|
|
2402
2402
|
constructor(config, options) {
|
|
2403
2403
|
this.providerName = "jira";
|
|
2404
2404
|
this.supportsPullRequests = false;
|
|
@@ -2410,6 +2410,36 @@ var JiraIssueTracker = class {
|
|
|
2410
2410
|
});
|
|
2411
2411
|
this.prompter = (options == null ? void 0 : options.prompter) ?? promptConfirmation;
|
|
2412
2412
|
}
|
|
2413
|
+
/**
|
|
2414
|
+
* Create a JiraIssueTracker from IloomSettings
|
|
2415
|
+
* Extracts and validates Jira config from settings
|
|
2416
|
+
*/
|
|
2417
|
+
static fromSettings(settings2) {
|
|
2418
|
+
var _a;
|
|
2419
|
+
const jiraSettings = (_a = settings2.issueManagement) == null ? void 0 : _a.jira;
|
|
2420
|
+
if (!(jiraSettings == null ? void 0 : jiraSettings.host)) {
|
|
2421
|
+
throw new Error("Jira host is required. Configure issueManagement.jira.host in .iloom/settings.json");
|
|
2422
|
+
}
|
|
2423
|
+
if (!(jiraSettings == null ? void 0 : jiraSettings.username)) {
|
|
2424
|
+
throw new Error("Jira username is required. Configure issueManagement.jira.username in .iloom/settings.json");
|
|
2425
|
+
}
|
|
2426
|
+
if (!(jiraSettings == null ? void 0 : jiraSettings.apiToken)) {
|
|
2427
|
+
throw new Error("Jira API token is required. Configure issueManagement.jira.apiToken in .iloom/settings.local.json");
|
|
2428
|
+
}
|
|
2429
|
+
if (!(jiraSettings == null ? void 0 : jiraSettings.projectKey)) {
|
|
2430
|
+
throw new Error("Jira project key is required. Configure issueManagement.jira.projectKey in .iloom/settings.json");
|
|
2431
|
+
}
|
|
2432
|
+
const config = {
|
|
2433
|
+
host: jiraSettings.host,
|
|
2434
|
+
username: jiraSettings.username,
|
|
2435
|
+
apiToken: jiraSettings.apiToken,
|
|
2436
|
+
projectKey: jiraSettings.projectKey
|
|
2437
|
+
};
|
|
2438
|
+
if (jiraSettings.transitionMappings) {
|
|
2439
|
+
config.transitionMappings = jiraSettings.transitionMappings;
|
|
2440
|
+
}
|
|
2441
|
+
return new _JiraIssueTracker(config);
|
|
2442
|
+
}
|
|
2413
2443
|
/**
|
|
2414
2444
|
* Normalize identifier to canonical uppercase form
|
|
2415
2445
|
* Jira issue keys are case-sensitive in the API (must be uppercase)
|
|
@@ -2723,6 +2753,11 @@ import path2 from "path";
|
|
|
2723
2753
|
import os2 from "os";
|
|
2724
2754
|
import { z } from "zod";
|
|
2725
2755
|
import deepmerge from "deepmerge";
|
|
2756
|
+
var mergeModeValues = ["local", "pr", "draft-pr", "github-pr", "github-draft-pr", "bitbucket-pr"];
|
|
2757
|
+
var mergeModeTransform = (val) => {
|
|
2758
|
+
const map = { "github-pr": "pr", "github-draft-pr": "draft-pr", "bitbucket-pr": "pr" };
|
|
2759
|
+
return map[val] ?? val;
|
|
2760
|
+
};
|
|
2726
2761
|
var BaseAgentSettingsSchema = z.object({
|
|
2727
2762
|
model: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Claude model shorthand: sonnet, opus, or haiku"),
|
|
2728
2763
|
swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Model to use for this agent in swarm mode. Overrides the base model when running inside swarm workers."),
|
|
@@ -2734,9 +2769,7 @@ var BaseAgentSettingsSchema = z.object({
|
|
|
2734
2769
|
review: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed before posting (defaults to false)"),
|
|
2735
2770
|
swarmReview: z.boolean().optional().describe("Whether artifacts from this agent should be reviewed in swarm mode. Defaults to false if not set (review is off in swarm mode for speed and cost unless explicitly enabled).")
|
|
2736
2771
|
});
|
|
2737
|
-
var AgentSettingsSchema = BaseAgentSettingsSchema
|
|
2738
|
-
subAgentTimeout: z.number().min(1, "Sub-agent timeout must be at least 1 minute").max(120, "Sub-agent timeout cannot exceed 120 minutes").default(10).describe("Timeout in minutes for sub-agent claude -p invocations in swarm mode. Applies to each phase agent (evaluator, analyzer, planner, implementer) when invoked via the Bash tool. Default: 10 minutes. Only meaningful under the iloom-swarm-worker agent entry.")
|
|
2739
|
-
});
|
|
2772
|
+
var AgentSettingsSchema = BaseAgentSettingsSchema;
|
|
2740
2773
|
var SpinAgentSettingsSchema = z.object({
|
|
2741
2774
|
model: z.enum(["sonnet", "opus", "haiku"]).default("opus").describe("Claude model shorthand for spin orchestrator"),
|
|
2742
2775
|
swarmModel: z.enum(["sonnet", "opus", "haiku"]).optional().describe("Model for the spin orchestrator when running in swarm mode. Overrides spin.model for swarm workflows."),
|
|
@@ -2745,7 +2778,8 @@ var SpinAgentSettingsSchema = z.object({
|
|
|
2745
2778
|
var PlanCommandSettingsSchema = z.object({
|
|
2746
2779
|
model: z.enum(["sonnet", "opus", "haiku"]).default("opus").describe("Claude model shorthand for plan command"),
|
|
2747
2780
|
planner: z.enum(["claude", "gemini", "codex"]).default("claude").describe("AI provider for creating the plan"),
|
|
2748
|
-
reviewer: z.enum(["claude", "gemini", "codex", "none"]).default("none").describe("AI provider for reviewing the plan (none to skip review)")
|
|
2781
|
+
reviewer: z.enum(["claude", "gemini", "codex", "none"]).default("none").describe("AI provider for reviewing the plan (none to skip review)"),
|
|
2782
|
+
waveVerification: z.boolean().default(true).describe("When enabled, the planner generates verification child issues between dependency waves to catch integration issues early.")
|
|
2749
2783
|
});
|
|
2750
2784
|
var SummarySettingsSchema = z.object({
|
|
2751
2785
|
model: z.enum(["sonnet", "opus", "haiku"]).default("sonnet").describe("Claude model shorthand for session summary generation")
|
|
@@ -2780,7 +2814,12 @@ var WorkflowsSettingsSchemaNoDefaults = z.object({
|
|
|
2780
2814
|
}).optional();
|
|
2781
2815
|
var CapabilitiesSettingsSchema = z.object({
|
|
2782
2816
|
web: z.object({
|
|
2783
|
-
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)")
|
|
2817
|
+
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)"),
|
|
2818
|
+
devServer: z.enum(["process", "docker"]).default("process").describe('Dev server mode: "process" runs natively, "docker" runs inside a Docker container with port mapping'),
|
|
2819
|
+
dockerFile: z.string().default("./Dockerfile").describe('Path to Dockerfile relative to worktree root (only used when devServer is "docker")'),
|
|
2820
|
+
containerPort: z.number().min(1, "Container port must be >= 1").max(65535, "Container port must be <= 65535").optional().describe("Port the app runs on inside the Docker container (auto-detected from EXPOSE directive if not set)"),
|
|
2821
|
+
dockerBuildArgs: z.record(z.string()).optional().describe('Build arguments to pass to docker build (e.g., {"NODE_ENV": "development"})'),
|
|
2822
|
+
dockerRunArgs: z.array(z.string()).optional().describe('Additional arguments for docker run (e.g., ["-v", "./src:/app/src"] for volume mounts)')
|
|
2784
2823
|
}).optional().describe('Web dev server settings. To declare a project as a web project, add "web" to the capabilities array in .iloom/package.iloom.json or .iloom/package.iloom.local.json.'),
|
|
2785
2824
|
database: z.object({
|
|
2786
2825
|
databaseUrlEnvVarName: z.string().min(1, "Database URL variable name cannot be empty").regex(/^[A-Z_][A-Z0-9_]*$/, "Must be valid env var name (uppercase, underscores)").optional().default("DATABASE_URL").describe("Name of environment variable for database connection URL")
|
|
@@ -2788,19 +2827,71 @@ var CapabilitiesSettingsSchema = z.object({
|
|
|
2788
2827
|
}).optional();
|
|
2789
2828
|
var CapabilitiesSettingsSchemaNoDefaults = z.object({
|
|
2790
2829
|
web: z.object({
|
|
2791
|
-
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)")
|
|
2830
|
+
basePort: z.number().min(1, "Base port must be >= 1").max(65535, "Base port must be <= 65535").optional().describe("Base port for web workspace port calculations (default: 3000)"),
|
|
2831
|
+
devServer: z.enum(["process", "docker"]).optional().describe('Dev server mode: "process" runs natively, "docker" runs inside a Docker container with port mapping'),
|
|
2832
|
+
dockerFile: z.string().optional().describe('Path to Dockerfile relative to worktree root (only used when devServer is "docker")'),
|
|
2833
|
+
containerPort: z.number().min(1, "Container port must be >= 1").max(65535, "Container port must be <= 65535").optional().describe("Port the app runs on inside the Docker container (auto-detected from EXPOSE directive if not set)"),
|
|
2834
|
+
dockerBuildArgs: z.record(z.string()).optional().describe('Build arguments to pass to docker build (e.g., {"NODE_ENV": "development"})'),
|
|
2835
|
+
dockerRunArgs: z.array(z.string()).optional().describe('Additional arguments for docker run (e.g., ["-v", "./src:/app/src"] for volume mounts)')
|
|
2792
2836
|
}).optional().describe('Web dev server settings. To declare a project as a web project, add "web" to the capabilities array in .iloom/package.iloom.json or .iloom/package.iloom.local.json.'),
|
|
2793
2837
|
database: z.object({
|
|
2794
2838
|
databaseUrlEnvVarName: z.string().min(1, "Database URL variable name cannot be empty").regex(/^[A-Z_][A-Z0-9_]*$/, "Must be valid env var name (uppercase, underscores)").optional().describe("Name of environment variable for database connection URL")
|
|
2795
2839
|
}).optional()
|
|
2796
2840
|
}).optional();
|
|
2841
|
+
var DevServerSettingsSchema = z.object({
|
|
2842
|
+
mode: z.enum(["docker"]).default("docker").describe('Dev server mode. Currently only "docker" is supported.'),
|
|
2843
|
+
docker: z.object({
|
|
2844
|
+
dockerFile: z.string().default("./Dockerfile").refine(
|
|
2845
|
+
(val) => {
|
|
2846
|
+
if (path2.isAbsolute(val)) return false;
|
|
2847
|
+
const normalized = path2.normalize(val);
|
|
2848
|
+
if (normalized.startsWith("..")) return false;
|
|
2849
|
+
return true;
|
|
2850
|
+
},
|
|
2851
|
+
{
|
|
2852
|
+
message: 'dockerFile must be a relative path that does not traverse outside the project root (no leading "/" and no "../" escaping)'
|
|
2853
|
+
}
|
|
2854
|
+
).describe("Path to Dockerfile relative to worktree root"),
|
|
2855
|
+
containerPort: z.number().min(1, "Container port must be >= 1").max(65535, "Container port must be <= 65535").optional().describe("Port the app runs on inside the Docker container (auto-detected from EXPOSE directive if not set)"),
|
|
2856
|
+
buildArgs: z.record(z.string(), z.string()).optional().describe("Build arguments to pass to docker build"),
|
|
2857
|
+
runArgs: z.array(z.string()).optional().describe("Additional arguments for docker run")
|
|
2858
|
+
}).optional()
|
|
2859
|
+
});
|
|
2860
|
+
var DevServerSettingsSchemaNoDefaults = z.object({
|
|
2861
|
+
mode: z.enum(["docker"]).optional().describe('Dev server mode. Currently only "docker" is supported.'),
|
|
2862
|
+
docker: z.object({
|
|
2863
|
+
dockerFile: z.string().optional().refine(
|
|
2864
|
+
(val) => {
|
|
2865
|
+
if (val === void 0) return true;
|
|
2866
|
+
if (path2.isAbsolute(val)) return false;
|
|
2867
|
+
const normalized = path2.normalize(val);
|
|
2868
|
+
if (normalized.startsWith("..")) return false;
|
|
2869
|
+
return true;
|
|
2870
|
+
},
|
|
2871
|
+
{
|
|
2872
|
+
message: 'dockerFile must be a relative path that does not traverse outside the project root (no leading "/" and no "../" escaping)'
|
|
2873
|
+
}
|
|
2874
|
+
).describe("Path to Dockerfile relative to worktree root"),
|
|
2875
|
+
containerPort: z.number().min(1, "Container port must be >= 1").max(65535, "Container port must be <= 65535").optional().describe("Port the app runs on inside the Docker container (auto-detected from EXPOSE directive if not set)"),
|
|
2876
|
+
buildArgs: z.record(z.string(), z.string()).optional().describe("Build arguments to pass to docker build"),
|
|
2877
|
+
runArgs: z.array(z.string()).optional().describe("Additional arguments for docker run")
|
|
2878
|
+
}).optional()
|
|
2879
|
+
});
|
|
2797
2880
|
var NeonSettingsSchema = z.object({
|
|
2798
2881
|
projectId: z.string().min(1).regex(/^[a-zA-Z0-9-]+$/, "Neon project ID must contain only letters, numbers, and hyphens").describe('Neon project ID found in your project URL (e.g., "fantastic-fox-3566354")'),
|
|
2799
2882
|
parentBranch: z.string().min(1).describe("Branch from which new database branches are created")
|
|
2800
2883
|
});
|
|
2884
|
+
var SupabaseSettingsSchema = z.object({
|
|
2885
|
+
projectRef: z.string().min(1).describe('Supabase project reference ID (e.g., "abcdefghijklmnop")'),
|
|
2886
|
+
parentBranch: z.string().min(1).optional().describe("Reserved for future use. Supabase currently always branches from the default branch."),
|
|
2887
|
+
withData: z.boolean().optional().describe("Whether to include data when creating a new branch (defaults to true)")
|
|
2888
|
+
});
|
|
2801
2889
|
var DatabaseProvidersSettingsSchema = z.object({
|
|
2802
2890
|
neon: NeonSettingsSchema.optional().describe(
|
|
2803
2891
|
"Neon database configuration. Requires Neon CLI installed and authenticated for database branching."
|
|
2892
|
+
),
|
|
2893
|
+
supabase: SupabaseSettingsSchema.optional().describe(
|
|
2894
|
+
"Supabase database configuration. Requires Supabase CLI installed and authenticated for database branching."
|
|
2804
2895
|
)
|
|
2805
2896
|
}).optional();
|
|
2806
2897
|
var IloomSettingsSchema = z.object({
|
|
@@ -2845,6 +2936,7 @@ var IloomSettingsSchema = z.object({
|
|
|
2845
2936
|
"Session summary generation configuration. Model defaults to sonnet when not configured."
|
|
2846
2937
|
),
|
|
2847
2938
|
capabilities: CapabilitiesSettingsSchema.describe("Project capability configurations"),
|
|
2939
|
+
devServer: DevServerSettingsSchema.optional().describe("Docker-based dev server configuration"),
|
|
2848
2940
|
databaseProviders: DatabaseProvidersSettingsSchema.describe("Database provider configurations"),
|
|
2849
2941
|
issueManagement: z.object({
|
|
2850
2942
|
// SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
|
|
@@ -2869,17 +2961,28 @@ var IloomSettingsSchema = z.object({
|
|
|
2869
2961
|
doneStatuses: z.array(z.string()).optional().default(["Done"]).describe('Status names to exclude from issue lists (e.g., ["Done", "Closed", "Verify"])')
|
|
2870
2962
|
}).optional()
|
|
2871
2963
|
}).optional().describe("Issue management configuration"),
|
|
2964
|
+
versionControl: z.object({
|
|
2965
|
+
provider: z.enum(["github", "bitbucket"]).optional().default("github").describe("Version control provider (github, bitbucket)"),
|
|
2966
|
+
bitbucket: z.object({
|
|
2967
|
+
username: z.string().min(1, "BitBucket username cannot be empty").describe("BitBucket username"),
|
|
2968
|
+
apiToken: z.string().optional().describe("BitBucket API token. SECURITY: Store in settings.local.json only, never commit to source control. Generate at: https://bitbucket.org/account/settings/app-passwords/ (Note: App passwords deprecated Sep 2025, use API tokens)"),
|
|
2969
|
+
workspace: z.string().optional().describe("BitBucket workspace (optional, auto-detected from git remote if not provided)"),
|
|
2970
|
+
repoSlug: z.string().optional().describe("BitBucket repository slug (optional, auto-detected from git remote if not provided)"),
|
|
2971
|
+
reviewers: z.array(z.string().describe("Reviewer username")).optional().describe("List of usernames to add as PR reviewers. Usernames are resolved to Bitbucket account IDs at PR creation time.")
|
|
2972
|
+
}).optional()
|
|
2973
|
+
}).optional().describe("Version control provider configuration"),
|
|
2872
2974
|
mergeBehavior: z.object({
|
|
2873
2975
|
// SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
|
|
2874
|
-
mode: z.enum(
|
|
2976
|
+
mode: z.enum(mergeModeValues).default("local").transform(mergeModeTransform),
|
|
2875
2977
|
remote: z.string().optional(),
|
|
2876
2978
|
autoCommitPush: z.boolean().optional().describe(
|
|
2877
|
-
"Auto-commit and push after code review in draft PR mode. Defaults to true when mode is
|
|
2979
|
+
"Auto-commit and push after code review in draft PR mode. Defaults to true when mode is draft-pr."
|
|
2878
2980
|
),
|
|
2981
|
+
prTitlePrefix: z.boolean().default(false).optional().describe('Prefix PR titles with the issue number (e.g., "QLH-123: Title"). Default: false'),
|
|
2879
2982
|
openBrowserOnFinish: z.boolean().default(true).describe(
|
|
2880
|
-
"Open the PR in the default browser after finishing in
|
|
2983
|
+
"Open the PR in the default browser after finishing in pr or draft-pr mode. Use --no-browser flag to override."
|
|
2881
2984
|
)
|
|
2882
|
-
}).optional().describe("Merge behavior configuration: local (merge locally),
|
|
2985
|
+
}).optional().describe("Merge behavior configuration: local (merge locally), pr (create PR), or draft-pr (create draft PR at start, mark ready on finish)"),
|
|
2883
2986
|
ide: z.object({
|
|
2884
2987
|
// SYNC: If this default changes, update displayDefaultsBox() in src/utils/first-run-setup.ts
|
|
2885
2988
|
type: z.enum(["vscode", "cursor", "webstorm", "sublime", "intellij", "windsurf", "antigravity"]).default("vscode").describe(
|
|
@@ -2941,12 +3044,14 @@ var IloomSettingsSchemaNoDefaults = z.object({
|
|
|
2941
3044
|
plan: z.object({
|
|
2942
3045
|
model: z.enum(["sonnet", "opus", "haiku"]).optional(),
|
|
2943
3046
|
planner: z.enum(["claude", "gemini", "codex"]).optional(),
|
|
2944
|
-
reviewer: z.enum(["claude", "gemini", "codex", "none"]).optional()
|
|
3047
|
+
reviewer: z.enum(["claude", "gemini", "codex", "none"]).optional(),
|
|
3048
|
+
waveVerification: z.boolean().optional()
|
|
2945
3049
|
}).optional().describe("Plan command configuration"),
|
|
2946
3050
|
summary: z.object({
|
|
2947
3051
|
model: z.enum(["sonnet", "opus", "haiku"]).optional()
|
|
2948
3052
|
}).optional().describe("Session summary generation configuration"),
|
|
2949
3053
|
capabilities: CapabilitiesSettingsSchemaNoDefaults.describe("Project capability configurations"),
|
|
3054
|
+
devServer: DevServerSettingsSchemaNoDefaults.optional().describe("Docker-based dev server configuration"),
|
|
2950
3055
|
databaseProviders: DatabaseProvidersSettingsSchema.describe("Database provider configurations"),
|
|
2951
3056
|
issueManagement: z.object({
|
|
2952
3057
|
provider: z.enum(["github", "linear", "jira"]).optional().describe("Issue tracker provider (github, linear, jira)"),
|
|
@@ -2970,16 +3075,27 @@ var IloomSettingsSchemaNoDefaults = z.object({
|
|
|
2970
3075
|
doneStatuses: z.array(z.string()).optional().default(["Done"]).describe('Status names to exclude from issue lists (e.g., ["Done", "Closed", "Verify"])')
|
|
2971
3076
|
}).optional()
|
|
2972
3077
|
}).optional().describe("Issue management configuration"),
|
|
3078
|
+
versionControl: z.object({
|
|
3079
|
+
provider: z.enum(["github", "bitbucket"]).optional().describe("Version control provider (github, bitbucket)"),
|
|
3080
|
+
bitbucket: z.object({
|
|
3081
|
+
username: z.string().min(1, "BitBucket username cannot be empty").describe("BitBucket username"),
|
|
3082
|
+
apiToken: z.string().optional().describe("BitBucket API token. SECURITY: Store in settings.local.json only, never commit to source control. Generate at: https://bitbucket.org/account/settings/app-passwords/ (Note: App passwords deprecated Sep 2025, use API tokens)"),
|
|
3083
|
+
workspace: z.string().optional().describe("BitBucket workspace (optional, auto-detected from git remote if not provided)"),
|
|
3084
|
+
repoSlug: z.string().optional().describe("BitBucket repository slug (optional, auto-detected from git remote if not provided)"),
|
|
3085
|
+
reviewers: z.array(z.string().describe("Reviewer username")).optional().describe("List of usernames to add as PR reviewers. Usernames are resolved to Bitbucket account IDs at PR creation time.")
|
|
3086
|
+
}).optional()
|
|
3087
|
+
}).optional().describe("Version control provider configuration"),
|
|
2973
3088
|
mergeBehavior: z.object({
|
|
2974
|
-
mode: z.enum(
|
|
3089
|
+
mode: z.enum(mergeModeValues).transform(mergeModeTransform).optional(),
|
|
2975
3090
|
remote: z.string().optional(),
|
|
2976
3091
|
autoCommitPush: z.boolean().optional().describe(
|
|
2977
|
-
"Auto-commit and push after code review in draft PR mode. Defaults to true when mode is
|
|
3092
|
+
"Auto-commit and push after code review in draft PR mode. Defaults to true when mode is draft-pr."
|
|
2978
3093
|
),
|
|
3094
|
+
prTitlePrefix: z.boolean().optional(),
|
|
2979
3095
|
openBrowserOnFinish: z.boolean().optional().describe(
|
|
2980
|
-
"Open the PR in the default browser after finishing in
|
|
3096
|
+
"Open the PR in the default browser after finishing in pr or draft-pr mode. Use --no-browser flag to override."
|
|
2981
3097
|
)
|
|
2982
|
-
}).optional().describe("Merge behavior configuration: local (merge locally),
|
|
3098
|
+
}).optional().describe("Merge behavior configuration: local (merge locally), pr (create PR), or draft-pr (create draft PR at start, mark ready on finish)"),
|
|
2983
3099
|
ide: z.object({
|
|
2984
3100
|
type: z.enum(["vscode", "cursor", "webstorm", "sublime", "intellij", "windsurf", "antigravity"]).optional().describe(
|
|
2985
3101
|
"IDE to launch when starting a loom. Options: vscode (Visual Studio Code), cursor (Cursor AI editor), webstorm (JetBrains WebStorm), sublime (Sublime Text), intellij (JetBrains IntelliJ IDEA), windsurf (Windsurf editor), antigravity (Antigravity IDE)."
|
|
@@ -3004,7 +3120,7 @@ function redactSensitiveFields(obj) {
|
|
|
3004
3120
|
if (obj === null || obj === void 0) return obj;
|
|
3005
3121
|
if (typeof obj !== "object") return obj;
|
|
3006
3122
|
if (Array.isArray(obj)) return obj.map(redactSensitiveFields);
|
|
3007
|
-
const sensitiveKeys = ["apitoken", "token", "secret", "password"];
|
|
3123
|
+
const sensitiveKeys = ["apitoken", "token", "secret", "password", "credential"];
|
|
3008
3124
|
const result = {};
|
|
3009
3125
|
for (const [key, value] of Object.entries(obj)) {
|
|
3010
3126
|
const lowerKey = key.toLowerCase();
|
|
@@ -3269,6 +3385,17 @@ ${errorMessages.join("\n")}`
|
|
|
3269
3385
|
var _a;
|
|
3270
3386
|
return ((_a = settings2 == null ? void 0 : settings2.plan) == null ? void 0 : _a.reviewer) ?? "none";
|
|
3271
3387
|
}
|
|
3388
|
+
/**
|
|
3389
|
+
* Get the plan command waveVerification setting with default applied
|
|
3390
|
+
* Default is true (verification tasks are generated)
|
|
3391
|
+
*
|
|
3392
|
+
* @param settings - Pre-loaded settings object
|
|
3393
|
+
* @returns Whether wave verification is enabled
|
|
3394
|
+
*/
|
|
3395
|
+
getPlanWaveVerification(settings2) {
|
|
3396
|
+
var _a;
|
|
3397
|
+
return ((_a = settings2 == null ? void 0 : settings2.plan) == null ? void 0 : _a.waveVerification) !== false;
|
|
3398
|
+
}
|
|
3272
3399
|
/**
|
|
3273
3400
|
* Get the session summary model with default applied
|
|
3274
3401
|
* Default is defined in SummarySettingsSchema
|
|
@@ -3730,8 +3857,672 @@ var JiraWikiSanitizer = class {
|
|
|
3730
3857
|
}
|
|
3731
3858
|
};
|
|
3732
3859
|
|
|
3860
|
+
// src/lib/providers/bitbucket/BitBucketApiClient.ts
|
|
3861
|
+
import https2 from "https";
|
|
3862
|
+
var BitBucketApiClient = class {
|
|
3863
|
+
constructor(config) {
|
|
3864
|
+
this.baseUrl = "https://api.bitbucket.org/2.0";
|
|
3865
|
+
const credentials = Buffer.from(`${config.username}:${config.apiToken}`).toString("base64");
|
|
3866
|
+
this.authHeader = `Basic ${credentials}`;
|
|
3867
|
+
this.workspace = config.workspace;
|
|
3868
|
+
this.repoSlug = config.repoSlug;
|
|
3869
|
+
}
|
|
3870
|
+
/**
|
|
3871
|
+
* Make an HTTP request to BitBucket API
|
|
3872
|
+
*/
|
|
3873
|
+
async request(method, endpoint, body) {
|
|
3874
|
+
const url = endpoint.startsWith("http://") || endpoint.startsWith("https://") ? new URL(endpoint) : new URL(`${this.baseUrl}${endpoint}`);
|
|
3875
|
+
if ((endpoint.startsWith("http://") || endpoint.startsWith("https://")) && url.hostname !== "api.bitbucket.org") {
|
|
3876
|
+
throw new Error(`Refusing to send authenticated request to unexpected host: ${url.hostname} (expected api.bitbucket.org)`);
|
|
3877
|
+
}
|
|
3878
|
+
getLogger().debug(`BitBucket API ${method} request`, { url: url.toString() });
|
|
3879
|
+
return new Promise((resolve, reject) => {
|
|
3880
|
+
const options = {
|
|
3881
|
+
hostname: url.hostname,
|
|
3882
|
+
port: url.port || 443,
|
|
3883
|
+
path: url.pathname + url.search,
|
|
3884
|
+
method,
|
|
3885
|
+
headers: {
|
|
3886
|
+
"Authorization": this.authHeader,
|
|
3887
|
+
"Accept": "application/json",
|
|
3888
|
+
"Content-Type": "application/json"
|
|
3889
|
+
}
|
|
3890
|
+
};
|
|
3891
|
+
const req = https2.request(options, (res) => {
|
|
3892
|
+
let data = "";
|
|
3893
|
+
res.on("data", (chunk) => {
|
|
3894
|
+
data += chunk;
|
|
3895
|
+
});
|
|
3896
|
+
res.on("end", () => {
|
|
3897
|
+
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
|
|
3898
|
+
reject(new Error(`BitBucket API error (${res.statusCode}): ${data}`));
|
|
3899
|
+
return;
|
|
3900
|
+
}
|
|
3901
|
+
if (res.statusCode === 204 || !data) {
|
|
3902
|
+
resolve({});
|
|
3903
|
+
return;
|
|
3904
|
+
}
|
|
3905
|
+
try {
|
|
3906
|
+
resolve(JSON.parse(data));
|
|
3907
|
+
} catch (error) {
|
|
3908
|
+
reject(new Error(`Failed to parse BitBucket API response: ${error}`));
|
|
3909
|
+
}
|
|
3910
|
+
});
|
|
3911
|
+
});
|
|
3912
|
+
req.on("error", (error) => {
|
|
3913
|
+
reject(new Error(`BitBucket API request failed: ${error.message}`));
|
|
3914
|
+
});
|
|
3915
|
+
if (body) {
|
|
3916
|
+
req.write(JSON.stringify(body));
|
|
3917
|
+
}
|
|
3918
|
+
req.end();
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
/**
|
|
3922
|
+
* Make a GET request to BitBucket API
|
|
3923
|
+
*/
|
|
3924
|
+
async get(endpoint) {
|
|
3925
|
+
return this.request("GET", endpoint);
|
|
3926
|
+
}
|
|
3927
|
+
/**
|
|
3928
|
+
* Make a POST request to BitBucket API
|
|
3929
|
+
*/
|
|
3930
|
+
async post(endpoint, body) {
|
|
3931
|
+
return this.request("POST", endpoint, body);
|
|
3932
|
+
}
|
|
3933
|
+
/**
|
|
3934
|
+
* Make a PUT request to BitBucket API
|
|
3935
|
+
*/
|
|
3936
|
+
async put(endpoint, body) {
|
|
3937
|
+
return this.request("PUT", endpoint, body);
|
|
3938
|
+
}
|
|
3939
|
+
/**
|
|
3940
|
+
* Get repository information
|
|
3941
|
+
*/
|
|
3942
|
+
async getRepository(workspace, repoSlug) {
|
|
3943
|
+
return this.get(`/repositories/${workspace}/${repoSlug}`);
|
|
3944
|
+
}
|
|
3945
|
+
/**
|
|
3946
|
+
* Get a pull request by ID
|
|
3947
|
+
*/
|
|
3948
|
+
async getPullRequest(workspace, repoSlug, prId) {
|
|
3949
|
+
return this.get(
|
|
3950
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}`
|
|
3951
|
+
);
|
|
3952
|
+
}
|
|
3953
|
+
/**
|
|
3954
|
+
* List open pull requests for a branch
|
|
3955
|
+
*
|
|
3956
|
+
* Note: BitBucket uses BBQL (BitBucket Query Language) for filtering.
|
|
3957
|
+
* The q parameter must use the format: q=source.branch.name="branch-name"
|
|
3958
|
+
* When using BBQL, we include state filter in the query to ensure it's applied.
|
|
3959
|
+
* See: https://developer.atlassian.com/cloud/bitbucket/rest/intro/#filtering
|
|
3960
|
+
*/
|
|
3961
|
+
async listPullRequests(workspace, repoSlug, sourceBranch) {
|
|
3962
|
+
let endpoint = `/repositories/${workspace}/${repoSlug}/pullrequests`;
|
|
3963
|
+
if (sourceBranch) {
|
|
3964
|
+
const safeBranch = sourceBranch.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
3965
|
+
const query = `state="OPEN" AND source.branch.name="${safeBranch}"`;
|
|
3966
|
+
endpoint += `?q=${encodeURIComponent(query)}`;
|
|
3967
|
+
} else {
|
|
3968
|
+
endpoint += `?state=OPEN`;
|
|
3969
|
+
}
|
|
3970
|
+
const response = await this.get(endpoint);
|
|
3971
|
+
return response.values;
|
|
3972
|
+
}
|
|
3973
|
+
/**
|
|
3974
|
+
* Create a pull request
|
|
3975
|
+
*/
|
|
3976
|
+
async createPullRequest(workspace, repoSlug, title, description, sourceBranch, destinationBranch, reviewerAccountIds) {
|
|
3977
|
+
const payload = {
|
|
3978
|
+
title,
|
|
3979
|
+
description,
|
|
3980
|
+
source: {
|
|
3981
|
+
branch: {
|
|
3982
|
+
name: sourceBranch
|
|
3983
|
+
}
|
|
3984
|
+
},
|
|
3985
|
+
destination: {
|
|
3986
|
+
branch: {
|
|
3987
|
+
name: destinationBranch
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
};
|
|
3991
|
+
if (reviewerAccountIds && reviewerAccountIds.length > 0) {
|
|
3992
|
+
payload.reviewers = reviewerAccountIds.map((id) => ({ account_id: id }));
|
|
3993
|
+
}
|
|
3994
|
+
return this.post(
|
|
3995
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests`,
|
|
3996
|
+
payload
|
|
3997
|
+
);
|
|
3998
|
+
}
|
|
3999
|
+
/**
|
|
4000
|
+
* Add a comment to a pull request
|
|
4001
|
+
*/
|
|
4002
|
+
async addPRComment(workspace, repoSlug, prId, content) {
|
|
4003
|
+
return this.post(
|
|
4004
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,
|
|
4005
|
+
{
|
|
4006
|
+
content: {
|
|
4007
|
+
raw: content
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
);
|
|
4011
|
+
}
|
|
4012
|
+
/**
|
|
4013
|
+
* Update an existing comment on a pull request
|
|
4014
|
+
*/
|
|
4015
|
+
async updatePRComment(workspace, repoSlug, prId, commentId, content) {
|
|
4016
|
+
return this.put(
|
|
4017
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments/${commentId}`,
|
|
4018
|
+
{
|
|
4019
|
+
content: {
|
|
4020
|
+
raw: content
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
);
|
|
4024
|
+
}
|
|
4025
|
+
/**
|
|
4026
|
+
* List all comments on a pull request with pagination
|
|
4027
|
+
*/
|
|
4028
|
+
async listPRComments(workspace, repoSlug, prId) {
|
|
4029
|
+
const MAX_PAGES = 50;
|
|
4030
|
+
const allComments = [];
|
|
4031
|
+
let nextUrl = `/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`;
|
|
4032
|
+
let pageCount = 0;
|
|
4033
|
+
while (nextUrl) {
|
|
4034
|
+
pageCount++;
|
|
4035
|
+
if (pageCount > MAX_PAGES) {
|
|
4036
|
+
console.error(`BitBucket listPRComments: exceeded maximum pagination limit of ${MAX_PAGES} pages, returning ${allComments.length} comments collected so far`);
|
|
4037
|
+
break;
|
|
4038
|
+
}
|
|
4039
|
+
const response = await this.get(nextUrl);
|
|
4040
|
+
allComments.push(...response.values);
|
|
4041
|
+
nextUrl = response.next ?? null;
|
|
4042
|
+
}
|
|
4043
|
+
getLogger().debug(`Fetched ${allComments.length} PR comments from BitBucket`);
|
|
4044
|
+
return allComments;
|
|
4045
|
+
}
|
|
4046
|
+
/**
|
|
4047
|
+
* Add an inline comment to a specific file and line in a pull request
|
|
4048
|
+
*/
|
|
4049
|
+
async addInlinePRComment(workspace, repoSlug, prId, content, filePath, line) {
|
|
4050
|
+
return this.post(
|
|
4051
|
+
`/repositories/${workspace}/${repoSlug}/pullrequests/${prId}/comments`,
|
|
4052
|
+
{
|
|
4053
|
+
content: {
|
|
4054
|
+
raw: content
|
|
4055
|
+
},
|
|
4056
|
+
inline: {
|
|
4057
|
+
to: line,
|
|
4058
|
+
path: filePath
|
|
4059
|
+
}
|
|
4060
|
+
}
|
|
4061
|
+
);
|
|
4062
|
+
}
|
|
4063
|
+
/**
|
|
4064
|
+
* Find workspace members by usernames
|
|
4065
|
+
* Returns a map of username -> account_id for resolved users
|
|
4066
|
+
* Handles pagination to fetch all workspace members
|
|
4067
|
+
*/
|
|
4068
|
+
async findUsersByUsername(workspace, usernames) {
|
|
4069
|
+
const result = /* @__PURE__ */ new Map();
|
|
4070
|
+
const allMembers = await this.getAllWorkspaceMembers(workspace);
|
|
4071
|
+
getLogger().debug(`Resolving ${usernames.length} usernames against ${allMembers.length} workspace members`);
|
|
4072
|
+
for (const username of usernames) {
|
|
4073
|
+
const usernameLower = username.toLowerCase();
|
|
4074
|
+
const member = allMembers.find(
|
|
4075
|
+
(m) => {
|
|
4076
|
+
var _a;
|
|
4077
|
+
return ((_a = m.user.nickname) == null ? void 0 : _a.toLowerCase()) === usernameLower || m.user.display_name.toLowerCase() === usernameLower;
|
|
4078
|
+
}
|
|
4079
|
+
);
|
|
4080
|
+
if (member) {
|
|
4081
|
+
result.set(username, member.user.account_id);
|
|
4082
|
+
getLogger().debug(`Resolved reviewer ${username} to account ID ${member.user.account_id}`);
|
|
4083
|
+
} else {
|
|
4084
|
+
getLogger().warn(`Could not resolve reviewer ${username} to a BitBucket account ID`);
|
|
4085
|
+
}
|
|
4086
|
+
}
|
|
4087
|
+
return result;
|
|
4088
|
+
}
|
|
4089
|
+
/**
|
|
4090
|
+
* Fetch all workspace members with pagination
|
|
4091
|
+
*/
|
|
4092
|
+
async getAllWorkspaceMembers(workspace) {
|
|
4093
|
+
const allMembers = [];
|
|
4094
|
+
let nextUrl = `/workspaces/${workspace}/members`;
|
|
4095
|
+
while (nextUrl) {
|
|
4096
|
+
const response = await this.get(nextUrl);
|
|
4097
|
+
allMembers.push(...response.values);
|
|
4098
|
+
nextUrl = response.next ?? null;
|
|
4099
|
+
}
|
|
4100
|
+
getLogger().debug(`Fetched ${allMembers.length} workspace members from BitBucket`);
|
|
4101
|
+
return allMembers;
|
|
4102
|
+
}
|
|
4103
|
+
/**
|
|
4104
|
+
* Get the currently authenticated user
|
|
4105
|
+
*/
|
|
4106
|
+
async getCurrentUser() {
|
|
4107
|
+
return this.get("/user");
|
|
4108
|
+
}
|
|
4109
|
+
/**
|
|
4110
|
+
* Test connection to BitBucket API
|
|
4111
|
+
*/
|
|
4112
|
+
async testConnection() {
|
|
4113
|
+
try {
|
|
4114
|
+
await this.getCurrentUser();
|
|
4115
|
+
return true;
|
|
4116
|
+
} catch (error) {
|
|
4117
|
+
getLogger().error("BitBucket connection test failed", { error });
|
|
4118
|
+
return false;
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
/**
|
|
4122
|
+
* Get configured workspace
|
|
4123
|
+
*/
|
|
4124
|
+
getWorkspace() {
|
|
4125
|
+
return this.workspace;
|
|
4126
|
+
}
|
|
4127
|
+
/**
|
|
4128
|
+
* Get configured repository slug
|
|
4129
|
+
*/
|
|
4130
|
+
getRepoSlug() {
|
|
4131
|
+
return this.repoSlug;
|
|
4132
|
+
}
|
|
4133
|
+
};
|
|
4134
|
+
|
|
4135
|
+
// src/utils/remote.ts
|
|
4136
|
+
import { execa as execa3 } from "execa";
|
|
4137
|
+
async function parseGitRemotes(cwd) {
|
|
4138
|
+
const result = await execa3("git", ["remote", "-v"], {
|
|
4139
|
+
cwd: cwd ?? process.cwd(),
|
|
4140
|
+
encoding: "utf8"
|
|
4141
|
+
});
|
|
4142
|
+
const lines = result.stdout.trim().split("\n");
|
|
4143
|
+
const remoteMap = /* @__PURE__ */ new Map();
|
|
4144
|
+
for (const line of lines) {
|
|
4145
|
+
const match = line.match(/^(\S+)\s+(\S+)\s+\((fetch|push)\)/);
|
|
4146
|
+
if (!match) continue;
|
|
4147
|
+
const name = match[1];
|
|
4148
|
+
const url = match[2];
|
|
4149
|
+
if (!name || !url) continue;
|
|
4150
|
+
if (remoteMap.has(name)) continue;
|
|
4151
|
+
const ownerRepo = extractOwnerRepoFromUrl(url);
|
|
4152
|
+
if (!ownerRepo) continue;
|
|
4153
|
+
remoteMap.set(name, {
|
|
4154
|
+
name,
|
|
4155
|
+
url,
|
|
4156
|
+
owner: ownerRepo.owner,
|
|
4157
|
+
repo: ownerRepo.repo
|
|
4158
|
+
});
|
|
4159
|
+
}
|
|
4160
|
+
return Array.from(remoteMap.values());
|
|
4161
|
+
}
|
|
4162
|
+
function extractOwnerRepoFromUrl(url) {
|
|
4163
|
+
const cleanUrl = url.replace(/\.git$/, "");
|
|
4164
|
+
const githubHttpsMatch = cleanUrl.match(/https?:\/\/github\.com\/([^/]+)\/([^/]+)/);
|
|
4165
|
+
if ((githubHttpsMatch == null ? void 0 : githubHttpsMatch[1]) && (githubHttpsMatch == null ? void 0 : githubHttpsMatch[2])) {
|
|
4166
|
+
return { owner: githubHttpsMatch[1], repo: githubHttpsMatch[2] };
|
|
4167
|
+
}
|
|
4168
|
+
const githubSshMatch = cleanUrl.match(/git@github\.com:([^/]+)\/(.+)/);
|
|
4169
|
+
if ((githubSshMatch == null ? void 0 : githubSshMatch[1]) && (githubSshMatch == null ? void 0 : githubSshMatch[2])) {
|
|
4170
|
+
return { owner: githubSshMatch[1], repo: githubSshMatch[2] };
|
|
4171
|
+
}
|
|
4172
|
+
const bitbucketHttpsMatch = cleanUrl.match(/https?:\/\/bitbucket\.org\/([^/]+)\/([^/]+)/);
|
|
4173
|
+
if ((bitbucketHttpsMatch == null ? void 0 : bitbucketHttpsMatch[1]) && (bitbucketHttpsMatch == null ? void 0 : bitbucketHttpsMatch[2])) {
|
|
4174
|
+
return { owner: bitbucketHttpsMatch[1], repo: bitbucketHttpsMatch[2] };
|
|
4175
|
+
}
|
|
4176
|
+
const bitbucketSshMatch = cleanUrl.match(/git@bitbucket\.org:([^/]+)\/(.+)/);
|
|
4177
|
+
if ((bitbucketSshMatch == null ? void 0 : bitbucketSshMatch[1]) && (bitbucketSshMatch == null ? void 0 : bitbucketSshMatch[2])) {
|
|
4178
|
+
return { owner: bitbucketSshMatch[1], repo: bitbucketSshMatch[2] };
|
|
4179
|
+
}
|
|
4180
|
+
return null;
|
|
4181
|
+
}
|
|
4182
|
+
|
|
4183
|
+
// src/lib/providers/bitbucket/BitBucketVCSProvider.ts
|
|
4184
|
+
var BitBucketVCSProvider = class _BitBucketVCSProvider {
|
|
4185
|
+
constructor(config) {
|
|
4186
|
+
this.providerName = "bitbucket";
|
|
4187
|
+
this.supportsForks = true;
|
|
4188
|
+
this.supportsDraftPRs = false;
|
|
4189
|
+
this.client = new BitBucketApiClient(config);
|
|
4190
|
+
if (config.reviewers) {
|
|
4191
|
+
this.reviewerUsernames = config.reviewers;
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
/**
|
|
4195
|
+
* Create a BitBucketVCSProvider from IloomSettings
|
|
4196
|
+
* Extracts and validates BitBucket config from settings
|
|
4197
|
+
*/
|
|
4198
|
+
static fromSettings(settings2) {
|
|
4199
|
+
var _a;
|
|
4200
|
+
const bbSettings = (_a = settings2.versionControl) == null ? void 0 : _a.bitbucket;
|
|
4201
|
+
if (!(bbSettings == null ? void 0 : bbSettings.username)) {
|
|
4202
|
+
throw new Error("BitBucket username is required. Configure versionControl.bitbucket.username in .iloom/settings.json");
|
|
4203
|
+
}
|
|
4204
|
+
if (!(bbSettings == null ? void 0 : bbSettings.apiToken)) {
|
|
4205
|
+
throw new Error("BitBucket API token is required. Configure versionControl.bitbucket.apiToken in .iloom/settings.local.json");
|
|
4206
|
+
}
|
|
4207
|
+
const config = {
|
|
4208
|
+
username: bbSettings.username,
|
|
4209
|
+
apiToken: bbSettings.apiToken
|
|
4210
|
+
};
|
|
4211
|
+
if (bbSettings.workspace) {
|
|
4212
|
+
config.workspace = bbSettings.workspace;
|
|
4213
|
+
}
|
|
4214
|
+
if (bbSettings.repoSlug) {
|
|
4215
|
+
config.repoSlug = bbSettings.repoSlug;
|
|
4216
|
+
}
|
|
4217
|
+
if (bbSettings.reviewers) {
|
|
4218
|
+
config.reviewers = bbSettings.reviewers;
|
|
4219
|
+
}
|
|
4220
|
+
return new _BitBucketVCSProvider(config);
|
|
4221
|
+
}
|
|
4222
|
+
/**
|
|
4223
|
+
* Check if a PR already exists for the given branch
|
|
4224
|
+
*/
|
|
4225
|
+
async checkForExistingPR(branchName, cwd) {
|
|
4226
|
+
try {
|
|
4227
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4228
|
+
const prs = await this.client.listPullRequests(workspace, repoSlug, branchName);
|
|
4229
|
+
if (prs.length > 0 && prs[0]) {
|
|
4230
|
+
const pr = prs[0];
|
|
4231
|
+
return {
|
|
4232
|
+
number: pr.id,
|
|
4233
|
+
url: pr.links.html.href
|
|
4234
|
+
};
|
|
4235
|
+
}
|
|
4236
|
+
return null;
|
|
4237
|
+
} catch (error) {
|
|
4238
|
+
if (error instanceof Error) {
|
|
4239
|
+
const statusMatch = error.message.match(/BitBucket API error \((\d+)\)/);
|
|
4240
|
+
if (statusMatch == null ? void 0 : statusMatch[1]) {
|
|
4241
|
+
const statusCode = parseInt(statusMatch[1], 10);
|
|
4242
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
4243
|
+
throw error;
|
|
4244
|
+
}
|
|
4245
|
+
}
|
|
4246
|
+
}
|
|
4247
|
+
getLogger().debug("Error checking for existing PR", { error });
|
|
4248
|
+
return null;
|
|
4249
|
+
}
|
|
4250
|
+
}
|
|
4251
|
+
/**
|
|
4252
|
+
* Create a pull request
|
|
4253
|
+
*/
|
|
4254
|
+
async createPR(branchName, title, body, baseBranch, cwd) {
|
|
4255
|
+
var _a, _b;
|
|
4256
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4257
|
+
getLogger().info(`Creating BitBucket PR in ${workspace}/${repoSlug}`);
|
|
4258
|
+
getLogger().debug("PR details", { branchName, title, baseBranch });
|
|
4259
|
+
let reviewerIds;
|
|
4260
|
+
if (this.reviewerUsernames && this.reviewerUsernames.length > 0) {
|
|
4261
|
+
reviewerIds = await this.resolveReviewerUsernames(workspace, this.reviewerUsernames);
|
|
4262
|
+
if (reviewerIds.length > 0) {
|
|
4263
|
+
const currentUser = await this.client.getCurrentUser();
|
|
4264
|
+
const originalCount = reviewerIds.length;
|
|
4265
|
+
reviewerIds = reviewerIds.filter((id) => id !== currentUser.account_id);
|
|
4266
|
+
if (reviewerIds.length < originalCount) {
|
|
4267
|
+
getLogger().debug(
|
|
4268
|
+
`Removed current user (${currentUser.display_name}) from reviewers list - PR author cannot be a reviewer`
|
|
4269
|
+
);
|
|
4270
|
+
}
|
|
4271
|
+
}
|
|
4272
|
+
}
|
|
4273
|
+
const pr = await this.client.createPullRequest(
|
|
4274
|
+
workspace,
|
|
4275
|
+
repoSlug,
|
|
4276
|
+
title,
|
|
4277
|
+
body,
|
|
4278
|
+
branchName,
|
|
4279
|
+
baseBranch,
|
|
4280
|
+
reviewerIds
|
|
4281
|
+
);
|
|
4282
|
+
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)) {
|
|
4283
|
+
getLogger().error("Invalid BitBucket API response", { pr });
|
|
4284
|
+
throw new Error(
|
|
4285
|
+
`BitBucket API returned invalid PR response. Expected PR with id and links.html.href, got: ${JSON.stringify(pr)}`
|
|
4286
|
+
);
|
|
4287
|
+
}
|
|
4288
|
+
getLogger().info(`BitBucket PR #${pr.id} created successfully`);
|
|
4289
|
+
return { url: pr.links.html.href, number: pr.id, wasExisting: false };
|
|
4290
|
+
}
|
|
4291
|
+
/**
|
|
4292
|
+
* Fetch PR details
|
|
4293
|
+
*/
|
|
4294
|
+
async fetchPR(prNumber, cwd) {
|
|
4295
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4296
|
+
const bbPR = await this.client.getPullRequest(workspace, repoSlug, prNumber);
|
|
4297
|
+
return this.mapBitBucketPRToPullRequest(bbPR);
|
|
4298
|
+
}
|
|
4299
|
+
/**
|
|
4300
|
+
* Get PR URL
|
|
4301
|
+
*/
|
|
4302
|
+
async getPRUrl(prNumber, cwd) {
|
|
4303
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4304
|
+
const bbPR = await this.client.getPullRequest(workspace, repoSlug, prNumber);
|
|
4305
|
+
return bbPR.links.html.href;
|
|
4306
|
+
}
|
|
4307
|
+
/**
|
|
4308
|
+
* Create a comment on a PR
|
|
4309
|
+
*/
|
|
4310
|
+
async createPRComment(prNumber, body, cwd) {
|
|
4311
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4312
|
+
getLogger().debug("Creating BitBucket PR comment", { workspace, repoSlug, prNumber });
|
|
4313
|
+
const comment = await this.client.addPRComment(workspace, repoSlug, prNumber, body);
|
|
4314
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
4315
|
+
}
|
|
4316
|
+
/**
|
|
4317
|
+
* Update an existing comment on a PR
|
|
4318
|
+
*/
|
|
4319
|
+
async updatePRComment(prNumber, commentId, body, cwd) {
|
|
4320
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4321
|
+
getLogger().debug("Updating BitBucket PR comment", { workspace, repoSlug, prNumber, commentId });
|
|
4322
|
+
const numericCommentId = parseInt(commentId, 10);
|
|
4323
|
+
if (isNaN(numericCommentId)) {
|
|
4324
|
+
throw new Error(`Invalid comment ID "${commentId}": expected a numeric value`);
|
|
4325
|
+
}
|
|
4326
|
+
const comment = await this.client.updatePRComment(workspace, repoSlug, prNumber, numericCommentId, body);
|
|
4327
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
4328
|
+
}
|
|
4329
|
+
/**
|
|
4330
|
+
* Get inline review comments on a PR
|
|
4331
|
+
* Fetches all comments and filters for those with inline metadata
|
|
4332
|
+
*/
|
|
4333
|
+
async getReviewComments(prNumber, cwd) {
|
|
4334
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4335
|
+
getLogger().debug("Fetching BitBucket PR review comments", { workspace, repoSlug, prNumber });
|
|
4336
|
+
const allComments = await this.client.listPRComments(workspace, repoSlug, prNumber);
|
|
4337
|
+
const inlineComments = [];
|
|
4338
|
+
for (const c of allComments) {
|
|
4339
|
+
if (c.inline == null) continue;
|
|
4340
|
+
inlineComments.push({
|
|
4341
|
+
id: String(c.id),
|
|
4342
|
+
body: c.content.raw,
|
|
4343
|
+
path: c.inline.path,
|
|
4344
|
+
line: c.inline.to ?? c.inline.from ?? null,
|
|
4345
|
+
side: null,
|
|
4346
|
+
// BitBucket doesn't have a "side" concept like GitHub
|
|
4347
|
+
author: c.user ? { id: c.user.uuid, displayName: c.user.display_name } : null,
|
|
4348
|
+
createdAt: c.created_on ?? "",
|
|
4349
|
+
updatedAt: c.updated_on ?? null,
|
|
4350
|
+
inReplyToId: null
|
|
4351
|
+
// BitBucket uses nested comments, not reply chains
|
|
4352
|
+
});
|
|
4353
|
+
}
|
|
4354
|
+
return inlineComments;
|
|
4355
|
+
}
|
|
4356
|
+
/**
|
|
4357
|
+
* Create an inline review comment on a specific file and line in a PR
|
|
4358
|
+
*/
|
|
4359
|
+
async createReviewComment(prNumber, path3, line, body, cwd) {
|
|
4360
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4361
|
+
getLogger().debug("Creating BitBucket inline PR comment", { workspace, repoSlug, prNumber, path: path3, line });
|
|
4362
|
+
const comment = await this.client.addInlinePRComment(workspace, repoSlug, prNumber, body, path3, line);
|
|
4363
|
+
return { id: String(comment.id), url: comment.links.html.href };
|
|
4364
|
+
}
|
|
4365
|
+
/**
|
|
4366
|
+
* List open pull requests for the repository
|
|
4367
|
+
* Uses getWorkspaceAndRepo for auto-detection from git remotes
|
|
4368
|
+
*/
|
|
4369
|
+
async listPullRequests(cwd) {
|
|
4370
|
+
const { workspace, repoSlug } = await this.getWorkspaceAndRepo(cwd);
|
|
4371
|
+
return this.client.listPullRequests(workspace, repoSlug);
|
|
4372
|
+
}
|
|
4373
|
+
/**
|
|
4374
|
+
* Detect repository from git remote
|
|
4375
|
+
*/
|
|
4376
|
+
async detectRepository(cwd) {
|
|
4377
|
+
try {
|
|
4378
|
+
const remotes = await parseGitRemotes(cwd);
|
|
4379
|
+
const bbRemote = remotes.find(
|
|
4380
|
+
(r) => r.url.includes("bitbucket.org")
|
|
4381
|
+
);
|
|
4382
|
+
if (!bbRemote) {
|
|
4383
|
+
return null;
|
|
4384
|
+
}
|
|
4385
|
+
return {
|
|
4386
|
+
owner: bbRemote.owner,
|
|
4387
|
+
// workspace
|
|
4388
|
+
repo: bbRemote.repo
|
|
4389
|
+
};
|
|
4390
|
+
} catch (error) {
|
|
4391
|
+
getLogger().error("Failed to detect BitBucket repository", { error });
|
|
4392
|
+
return null;
|
|
4393
|
+
}
|
|
4394
|
+
}
|
|
4395
|
+
/**
|
|
4396
|
+
* Get target remote for PR operations
|
|
4397
|
+
*/
|
|
4398
|
+
async getTargetRemote(_cwd) {
|
|
4399
|
+
return "origin";
|
|
4400
|
+
}
|
|
4401
|
+
/**
|
|
4402
|
+
* Get workspace and repository slug from config or git remote
|
|
4403
|
+
*/
|
|
4404
|
+
async getWorkspaceAndRepo(cwd) {
|
|
4405
|
+
let workspace = this.client.getWorkspace();
|
|
4406
|
+
let repoSlug = this.client.getRepoSlug();
|
|
4407
|
+
if (!workspace || !repoSlug) {
|
|
4408
|
+
const detected = await this.detectRepository(cwd);
|
|
4409
|
+
if (!detected) {
|
|
4410
|
+
throw new Error(
|
|
4411
|
+
"Could not determine BitBucket workspace/repository. Either configure them in settings or ensure git remote points to bitbucket.org"
|
|
4412
|
+
);
|
|
4413
|
+
}
|
|
4414
|
+
workspace = workspace ?? detected.owner;
|
|
4415
|
+
repoSlug = repoSlug ?? detected.repo;
|
|
4416
|
+
}
|
|
4417
|
+
return { workspace, repoSlug };
|
|
4418
|
+
}
|
|
4419
|
+
/**
|
|
4420
|
+
* Resolve reviewer usernames to BitBucket account IDs
|
|
4421
|
+
* Warns for any usernames that cannot be resolved but continues with partial list
|
|
4422
|
+
*/
|
|
4423
|
+
async resolveReviewerUsernames(workspace, usernames) {
|
|
4424
|
+
getLogger().debug(`Resolving ${usernames.length} reviewer username(s) to BitBucket account IDs`);
|
|
4425
|
+
const usernameToAccountId = await this.client.findUsersByUsername(workspace, usernames);
|
|
4426
|
+
const resolvedIds = [];
|
|
4427
|
+
const unresolvedUsernames = [];
|
|
4428
|
+
for (const username of usernames) {
|
|
4429
|
+
const accountId = usernameToAccountId.get(username);
|
|
4430
|
+
if (accountId) {
|
|
4431
|
+
resolvedIds.push(accountId);
|
|
4432
|
+
} else {
|
|
4433
|
+
unresolvedUsernames.push(username);
|
|
4434
|
+
}
|
|
4435
|
+
}
|
|
4436
|
+
if (unresolvedUsernames.length > 0) {
|
|
4437
|
+
getLogger().warn(
|
|
4438
|
+
`Could not resolve ${unresolvedUsernames.length} reviewer username(s) to BitBucket account IDs: ${unresolvedUsernames.join(", ")}. These reviewers will not be added to the PR.`
|
|
4439
|
+
);
|
|
4440
|
+
}
|
|
4441
|
+
if (resolvedIds.length > 0) {
|
|
4442
|
+
getLogger().info(`Resolved ${resolvedIds.length} reviewer(s) for PR`);
|
|
4443
|
+
}
|
|
4444
|
+
return resolvedIds;
|
|
4445
|
+
}
|
|
4446
|
+
/**
|
|
4447
|
+
* Map BitBucket PR to generic PullRequest type
|
|
4448
|
+
*/
|
|
4449
|
+
mapBitBucketPRToPullRequest(bbPR) {
|
|
4450
|
+
let state;
|
|
4451
|
+
if (bbPR.state === "OPEN") {
|
|
4452
|
+
state = "open";
|
|
4453
|
+
} else if (bbPR.state === "MERGED") {
|
|
4454
|
+
state = "merged";
|
|
4455
|
+
} else {
|
|
4456
|
+
state = "closed";
|
|
4457
|
+
}
|
|
4458
|
+
return {
|
|
4459
|
+
number: bbPR.id,
|
|
4460
|
+
title: bbPR.title,
|
|
4461
|
+
body: bbPR.description,
|
|
4462
|
+
state,
|
|
4463
|
+
branch: bbPR.source.branch.name,
|
|
4464
|
+
baseBranch: bbPR.destination.branch.name,
|
|
4465
|
+
url: bbPR.links.html.href,
|
|
4466
|
+
isDraft: false
|
|
4467
|
+
// BitBucket doesn't have draft PRs
|
|
4468
|
+
};
|
|
4469
|
+
}
|
|
4470
|
+
};
|
|
4471
|
+
|
|
4472
|
+
// src/lib/VCSProviderFactory.ts
|
|
4473
|
+
var VCSProviderFactory = class {
|
|
4474
|
+
/**
|
|
4475
|
+
* Create a VersionControlProvider instance based on settings configuration
|
|
4476
|
+
*
|
|
4477
|
+
* @param settings - iloom settings containing versionControl.provider
|
|
4478
|
+
* @returns VersionControlProvider instance configured for the specified provider
|
|
4479
|
+
* @throws Error if provider type is not supported or required config is missing
|
|
4480
|
+
*/
|
|
4481
|
+
static create(settings2) {
|
|
4482
|
+
var _a;
|
|
4483
|
+
const provider = (_a = settings2.versionControl) == null ? void 0 : _a.provider;
|
|
4484
|
+
if (!provider) {
|
|
4485
|
+
getLogger().debug("VCSProviderFactory: No versionControl.provider configured, using legacy PRManager");
|
|
4486
|
+
return null;
|
|
4487
|
+
}
|
|
4488
|
+
getLogger().debug(`VCSProviderFactory: Creating VCS provider for "${provider}"`);
|
|
4489
|
+
switch (provider) {
|
|
4490
|
+
case "github":
|
|
4491
|
+
getLogger().debug("VCSProviderFactory: GitHub uses legacy PRManager, returning null");
|
|
4492
|
+
return null;
|
|
4493
|
+
case "bitbucket": {
|
|
4494
|
+
getLogger().debug(`VCSProviderFactory: Creating BitBucketVCSProvider from settings`);
|
|
4495
|
+
return BitBucketVCSProvider.fromSettings(settings2);
|
|
4496
|
+
}
|
|
4497
|
+
default:
|
|
4498
|
+
throw new Error(`Unsupported VCS provider: ${provider}`);
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4501
|
+
/**
|
|
4502
|
+
* Check if a VCS provider is configured
|
|
4503
|
+
*
|
|
4504
|
+
* @param settings - iloom settings
|
|
4505
|
+
* @returns true if versionControl provider is configured
|
|
4506
|
+
*/
|
|
4507
|
+
static isConfigured(settings2) {
|
|
4508
|
+
var _a, _b;
|
|
4509
|
+
return ((_a = settings2.versionControl) == null ? void 0 : _a.provider) !== void 0 && ((_b = settings2.versionControl) == null ? void 0 : _b.provider) !== "github";
|
|
4510
|
+
}
|
|
4511
|
+
/**
|
|
4512
|
+
* Get the configured provider name from settings
|
|
4513
|
+
*
|
|
4514
|
+
* @param settings - iloom settings
|
|
4515
|
+
* @returns Provider type string or undefined if not configured
|
|
4516
|
+
*/
|
|
4517
|
+
static getProviderName(settings2) {
|
|
4518
|
+
var _a;
|
|
4519
|
+
return (_a = settings2.versionControl) == null ? void 0 : _a.provider;
|
|
4520
|
+
}
|
|
4521
|
+
};
|
|
4522
|
+
|
|
3733
4523
|
// src/mcp/issue-management-server.ts
|
|
3734
4524
|
var settings;
|
|
4525
|
+
var vcsProvider = null;
|
|
3735
4526
|
function validateEnvironment() {
|
|
3736
4527
|
const provider = process.env.ISSUE_PROVIDER;
|
|
3737
4528
|
if (!provider) {
|
|
@@ -3849,7 +4640,7 @@ server.registerTool(
|
|
|
3849
4640
|
"get_pr",
|
|
3850
4641
|
{
|
|
3851
4642
|
title: "Get Pull Request",
|
|
3852
|
-
description: "Fetch pull request details including title, body, comments, files, commits, and branch information.
|
|
4643
|
+
description: "Fetch pull request details including title, body, comments, files, commits, and branch information. Uses the configured VCS provider (GitHub or BitBucket). Falls back to GitHub when no VCS provider is configured. Author fields have normalized core fields: { id, displayName } plus provider-specific fields.",
|
|
3853
4644
|
inputSchema: {
|
|
3854
4645
|
number: z2.string().describe("The PR number"),
|
|
3855
4646
|
includeComments: z2.boolean().optional().describe("Whether to include comments (default: true)"),
|
|
@@ -3900,6 +4691,34 @@ server.registerTool(
|
|
|
3900
4691
|
async ({ number, includeComments, repo }) => {
|
|
3901
4692
|
console.error(`Fetching PR ${number}${repo ? ` from ${repo}` : ""}`);
|
|
3902
4693
|
try {
|
|
4694
|
+
if (vcsProvider) {
|
|
4695
|
+
if (repo) {
|
|
4696
|
+
console.error(`VCS provider path does not support 'repo' override parameter, using configured repository`);
|
|
4697
|
+
}
|
|
4698
|
+
const pr = await vcsProvider.fetchPR(parseInt(number, 10));
|
|
4699
|
+
const result2 = {
|
|
4700
|
+
id: String(pr.number),
|
|
4701
|
+
number: pr.number,
|
|
4702
|
+
title: pr.title,
|
|
4703
|
+
body: pr.body,
|
|
4704
|
+
state: pr.state.toUpperCase(),
|
|
4705
|
+
url: pr.url,
|
|
4706
|
+
headRefName: pr.branch,
|
|
4707
|
+
baseRefName: pr.baseBranch,
|
|
4708
|
+
author: null,
|
|
4709
|
+
isDraft: pr.isDraft
|
|
4710
|
+
};
|
|
4711
|
+
console.error(`PR fetched successfully: #${result2.number} - ${result2.title}`);
|
|
4712
|
+
return {
|
|
4713
|
+
content: [
|
|
4714
|
+
{
|
|
4715
|
+
type: "text",
|
|
4716
|
+
text: JSON.stringify(result2)
|
|
4717
|
+
}
|
|
4718
|
+
],
|
|
4719
|
+
structuredContent: result2
|
|
4720
|
+
};
|
|
4721
|
+
}
|
|
3903
4722
|
const provider = new GitHubIssueManagementProvider();
|
|
3904
4723
|
const result = await provider.getPR({ number, includeComments, repo });
|
|
3905
4724
|
console.error(`PR fetched successfully: #${result.number} - ${result.title}`);
|
|
@@ -3923,7 +4742,7 @@ server.registerTool(
|
|
|
3923
4742
|
"get_review_comments",
|
|
3924
4743
|
{
|
|
3925
4744
|
title: "Get PR Review Comments",
|
|
3926
|
-
description: "Fetch inline code review comments on a pull request (comments on specific files and lines). Returns comments with file path, line number, diff side, author, and reply threading.
|
|
4745
|
+
description: "Fetch inline code review comments on a pull request (comments on specific files and lines). Returns comments with file path, line number, diff side, author, and reply threading. Uses the configured VCS provider when available, falls back to GitHub.",
|
|
3927
4746
|
inputSchema: {
|
|
3928
4747
|
number: z2.string().describe("The PR number"),
|
|
3929
4748
|
reviewId: z2.string().optional().describe("Optional review ID to filter comments by a specific review"),
|
|
@@ -3951,6 +4770,30 @@ server.registerTool(
|
|
|
3951
4770
|
async ({ number, reviewId, repo }) => {
|
|
3952
4771
|
console.error(`Fetching review comments for PR ${number}${reviewId ? ` (review ${reviewId})` : ""}${repo ? ` from ${repo}` : ""}`);
|
|
3953
4772
|
try {
|
|
4773
|
+
if (vcsProvider == null ? void 0 : vcsProvider.getReviewComments) {
|
|
4774
|
+
if (repo) {
|
|
4775
|
+
console.error(`VCS provider path does not support 'repo' override parameter, using configured repository`);
|
|
4776
|
+
}
|
|
4777
|
+
if (reviewId) {
|
|
4778
|
+
console.error(`VCS provider path does not support 'reviewId' filter, returning all inline comments`);
|
|
4779
|
+
}
|
|
4780
|
+
const reviewComments = await vcsProvider.getReviewComments(parseInt(number, 10));
|
|
4781
|
+
const comments2 = reviewComments.map((c) => ({
|
|
4782
|
+
...c,
|
|
4783
|
+
pullRequestReviewId: null
|
|
4784
|
+
}));
|
|
4785
|
+
console.error(`Review comments fetched successfully: ${comments2.length} comments`);
|
|
4786
|
+
const result2 = { comments: comments2 };
|
|
4787
|
+
return {
|
|
4788
|
+
content: [
|
|
4789
|
+
{
|
|
4790
|
+
type: "text",
|
|
4791
|
+
text: JSON.stringify(result2)
|
|
4792
|
+
}
|
|
4793
|
+
],
|
|
4794
|
+
structuredContent: result2
|
|
4795
|
+
};
|
|
4796
|
+
}
|
|
3954
4797
|
const provider = new GitHubIssueManagementProvider();
|
|
3955
4798
|
const comments = await provider.getReviewComments({ number, reviewId, repo });
|
|
3956
4799
|
console.error(`Review comments fetched successfully: ${comments.length} comments`);
|
|
@@ -4039,6 +4882,22 @@ server.registerTool(
|
|
|
4039
4882
|
console.error(`Creating ${type} comment on ${number}`);
|
|
4040
4883
|
try {
|
|
4041
4884
|
const sanitizedBody = JiraWikiSanitizer.sanitize(body);
|
|
4885
|
+
if (type === "pr" && vcsProvider) {
|
|
4886
|
+
const vcsResult = await vcsProvider.createPRComment(parseInt(number, 10), sanitizedBody);
|
|
4887
|
+
console.error(
|
|
4888
|
+
`Comment created successfully: ${vcsResult.id} at ${vcsResult.url}`
|
|
4889
|
+
);
|
|
4890
|
+
const result2 = { id: vcsResult.id, url: vcsResult.url, created_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4891
|
+
return {
|
|
4892
|
+
content: [
|
|
4893
|
+
{
|
|
4894
|
+
type: "text",
|
|
4895
|
+
text: JSON.stringify(result2)
|
|
4896
|
+
}
|
|
4897
|
+
],
|
|
4898
|
+
structuredContent: result2
|
|
4899
|
+
};
|
|
4900
|
+
}
|
|
4042
4901
|
const providerType = type === "pr" ? "github" : process.env.ISSUE_PROVIDER;
|
|
4043
4902
|
const provider = IssueManagementProviderFactory.create(providerType, settings);
|
|
4044
4903
|
const result = await provider.createComment({ number, body: sanitizedBody, type });
|
|
@@ -4083,6 +4942,22 @@ server.registerTool(
|
|
|
4083
4942
|
console.error(`Updating comment ${commentId} on ${type === "pr" ? "PR" : "issue"} ${number}`);
|
|
4084
4943
|
try {
|
|
4085
4944
|
const sanitizedBody = JiraWikiSanitizer.sanitize(body);
|
|
4945
|
+
if (type === "pr" && (vcsProvider == null ? void 0 : vcsProvider.updatePRComment)) {
|
|
4946
|
+
const vcsResult = await vcsProvider.updatePRComment(parseInt(number, 10), commentId, sanitizedBody);
|
|
4947
|
+
console.error(
|
|
4948
|
+
`Comment updated successfully: ${vcsResult.id} at ${vcsResult.url}`
|
|
4949
|
+
);
|
|
4950
|
+
const result2 = { id: vcsResult.id, url: vcsResult.url, updated_at: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4951
|
+
return {
|
|
4952
|
+
content: [
|
|
4953
|
+
{
|
|
4954
|
+
type: "text",
|
|
4955
|
+
text: JSON.stringify(result2)
|
|
4956
|
+
}
|
|
4957
|
+
],
|
|
4958
|
+
structuredContent: result2
|
|
4959
|
+
};
|
|
4960
|
+
}
|
|
4086
4961
|
const providerType = type === "pr" ? "github" : process.env.ISSUE_PROVIDER;
|
|
4087
4962
|
const provider = IssueManagementProviderFactory.create(providerType, settings);
|
|
4088
4963
|
const result = await provider.updateComment({ commentId, number, body: sanitizedBody });
|
|
@@ -4532,6 +5407,19 @@ async function main() {
|
|
|
4532
5407
|
const settingsManager = new SettingsManager();
|
|
4533
5408
|
settings = await settingsManager.loadSettings();
|
|
4534
5409
|
console.error("Settings loaded");
|
|
5410
|
+
try {
|
|
5411
|
+
vcsProvider = VCSProviderFactory.create(settings);
|
|
5412
|
+
if (vcsProvider) {
|
|
5413
|
+
console.error(`VCS provider initialized: ${vcsProvider.providerName}`);
|
|
5414
|
+
}
|
|
5415
|
+
} catch (error) {
|
|
5416
|
+
if (error instanceof Error && (error.message.includes("is required") || error.message.includes("Unsupported VCS provider"))) {
|
|
5417
|
+
console.error(`Failed to initialize VCS provider (falling back to GitHub): ${error.message}`);
|
|
5418
|
+
vcsProvider = null;
|
|
5419
|
+
} else {
|
|
5420
|
+
throw error;
|
|
5421
|
+
}
|
|
5422
|
+
}
|
|
4535
5423
|
const provider = validateEnvironment();
|
|
4536
5424
|
console.error("Environment validated");
|
|
4537
5425
|
console.error(`Issue management provider: ${provider}`);
|