@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/terminal-backends/darwin.ts","../src/utils/terminal-backends/command-builder.ts","../src/utils/env.ts","../src/utils/logger.ts","../src/utils/terminal.ts","../src/utils/platform-detect.ts","../src/utils/terminal-backends/index.ts"],"sourcesContent":["import { execa } from 'execa'\nimport { existsSync } from 'node:fs'\nimport type { TerminalWindowOptions } from '../terminal.js'\nimport type { TerminalBackend } from './types.js'\nimport { buildCommandSequence } from './command-builder.js'\n\n/**\n * Detect if iTerm2 is installed on macOS.\n */\nexport function detectITerm2(): boolean {\n\treturn existsSync('/Applications/iTerm.app')\n}\n\n/**\n * Escape command string for embedding inside an AppleScript `do script \"...\"`.\n */\nfunction escapeForAppleScript(command: string): string {\n\treturn command\n\t\t.replace(/\\\\/g, '\\\\\\\\')\n\t\t.replace(/\"/g, '\\\\\"')\n}\n\n/**\n * Build AppleScript for macOS Terminal.app (single tab).\n *\n * Delegates to the shared buildCommandSequence for command construction,\n * then wraps the result with AppleScript escaping for `do script \"...\"`.\n */\nasync function buildTerminalAppScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = `tell application \"Terminal\"\\n`\n\tscript += ` set newTab to do script \"${escapeForAppleScript(command)}\"\\n`\n\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += `end tell`\n\treturn script\n}\n\n/**\n * Build iTerm2 AppleScript for a single tab in a new window.\n */\nasync function buildITerm2SingleTabScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set s1 to current session of current window\\n\\n'\n\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\tif (options.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t}\n\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\treturn script\n}\n\n/**\n * Build iTerm2 AppleScript for multiple tabs (2+) in a single window.\n */\nasync function buildITerm2MultiTabScript(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<string> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('buildITerm2MultiTabScript requires at least 2 terminal options')\n\t}\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set newWindow to current window\\n'\n\n\tconst options1 = optionsArray[0]\n\tif (!options1) {\n\t\tthrow new Error('First terminal option is undefined')\n\t}\n\tconst command1 = await buildCommandSequence(options1)\n\n\tscript += ' set s1 to current session of newWindow\\n\\n'\n\n\tif (options1.backgroundColor) {\n\t\tconst { r, g, b } = options1.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command1)}\"\\n\\n`\n\n\tif (options1.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options1.title)}\"\\n\\n`\n\t}\n\n\tfor (let i = 1; i < optionsArray.length; i++) {\n\t\tconst options = optionsArray[i]\n\t\tif (!options) {\n\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t}\n\t\tconst command = await buildCommandSequence(options)\n\t\tconst sessionVar = `s${i + 1}`\n\n\t\tscript += ' tell newWindow\\n'\n\t\tscript += ` set newTab${i} to (create tab with default profile)\\n`\n\t\tscript += ' end tell\\n'\n\t\tscript += ` set ${sessionVar} to current session of newTab${i}\\n\\n`\n\n\t\tif (options.backgroundColor) {\n\t\t\tconst { r, g, b } = options.backgroundColor\n\t\t\tscript += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t\t}\n\n\t\tscript += ` tell ${sessionVar} to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t\tif (options.title) {\n\t\t\tscript += ` set name of ${sessionVar} to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t\t}\n\t}\n\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\treturn script\n}\n\n/**\n * macOS terminal backend — supports Terminal.app and iTerm2.\n */\nexport class DarwinBackend implements TerminalBackend {\n\treadonly name = 'darwin'\n\n\tasync openSingle(options: TerminalWindowOptions): Promise<void> {\n\t\tconst hasITerm2 = detectITerm2()\n\n\t\tconst applescript = hasITerm2\n\t\t\t? await buildITerm2SingleTabScript(options)\n\t\t\t: await buildTerminalAppScript(options)\n\n\t\ttry {\n\t\t\tawait execa('osascript', ['-e', applescript])\n\n\t\t\tif (!hasITerm2) {\n\t\t\t\tawait execa('osascript', ['-e', 'tell application \"Terminal\" to activate'])\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to open terminal window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\tasync openMultiple(optionsArray: TerminalWindowOptions[]): Promise<void> {\n\t\tconst hasITerm2 = detectITerm2()\n\n\t\tif (hasITerm2) {\n\t\t\tconst applescript = await buildITerm2MultiTabScript(optionsArray)\n\n\t\t\ttry {\n\t\t\t\tawait execa('osascript', ['-e', applescript])\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to open iTerm2 window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = 0; i < optionsArray.length; i++) {\n\t\t\t\tconst options = optionsArray[i]\n\t\t\t\tif (!options) {\n\t\t\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t\t\t}\n\t\t\t\tawait this.openSingle(options)\n\n\t\t\t\tif (i < optionsArray.length - 1) {\n\t\t\t\t\tawait new Promise<void>((resolve) => globalThis.setTimeout(resolve, 1000))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport type { TerminalWindowOptions } from '../terminal.js'\nimport { buildEnvSourceCommands } from '../env.js'\n\n/**\n * Build the shell command sequence from TerminalWindowOptions.\n *\n * The returned string is a chain of commands joined by ` && `, prefixed with\n * a space to prevent shell history pollution (HISTCONTROL=ignorespace).\n *\n * This logic is shared across all backends — each backend applies its own\n * escaping on top of the raw command string.\n */\nexport async function buildCommandSequence(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\tconst commands: string[] = []\n\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapeSingleQuotes(workspacePath)}'`)\n\t}\n\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\treturn ` ${fullCommand}`\n}\n\n/**\n * Escape single quotes for use inside a single-quoted shell string.\n * 'it'\\''s' → ends quote, adds escaped quote, resumes quote\n */\nexport function escapeSingleQuotes(s: string): string {\n\treturn s.replace(/'/g, \"'\\\\''\")\n}\n\n/**\n * Convert {r, g, b} (0–255) to a hex color string \"#RRGGBB\".\n */\nexport function rgbToHex(rgb: { r: number; g: number; b: number }): string {\n\tconst toHex = (n: number): string => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, '0')\n\treturn `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`\n}\n","import path from 'path'\nimport dotenvFlow, { type DotenvFlowConfigOptions } from 'dotenv-flow'\nimport { logger } from './logger.js'\n\n/**\n * Parse .env file content into key-value map\n * Handles comments, empty lines, quoted/unquoted values, multiline values\n */\nexport function parseEnvFile(content: string): Map<string, string> {\n const envMap = new Map<string, string>()\n const lines = content.split('\\n')\n\n for (const line of lines) {\n const trimmedLine = line.trim()\n\n // Skip empty lines and comments\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n continue\n }\n\n // Remove 'export ' prefix if present\n const cleanLine = trimmedLine.startsWith('export ')\n ? trimmedLine.substring(7)\n : trimmedLine\n\n // Find the first equals sign\n const equalsIndex = cleanLine.indexOf('=')\n if (equalsIndex === -1) {\n continue\n }\n\n const key = cleanLine.substring(0, equalsIndex).trim()\n let value = cleanLine.substring(equalsIndex + 1)\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.substring(1, value.length - 1)\n // Unescape quotes\n value = value.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\")\n // Unescape newlines\n value = value.replace(/\\\\n/g, '\\n')\n }\n\n if (key) {\n envMap.set(key, value)\n }\n }\n\n return envMap\n}\n\n/**\n * Format environment variable as line for .env file\n * Always quotes values and escapes internal quotes\n */\nexport function formatEnvLine(key: string, value: string): string {\n // Escape quotes and newlines in the value\n const escapedValue = value\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n\n return `${key}=\"${escapedValue}\"`\n}\n\n/**\n * Validate environment variable name and value\n */\nexport function validateEnvVariable(\n key: string,\n _value?: string\n): { valid: boolean; error?: string } {\n if (!key || key.length === 0) {\n return {\n valid: false,\n error: 'Environment variable key cannot be empty',\n }\n }\n\n if (!isValidEnvKey(key)) {\n return {\n valid: false,\n error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`,\n }\n }\n\n // Values can be any string, including empty\n return { valid: true }\n}\n\n/**\n * Normalize line endings for cross-platform compatibility\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n}\n\n/**\n * Extract port from .env file if present\n */\nexport function extractPort(envContent: Map<string, string>): number | null {\n const portValue = envContent.get('PORT')\n if (!portValue) {\n return null\n }\n\n const port = parseInt(portValue, 10)\n if (isNaN(port)) {\n return null\n }\n\n return port\n}\n\n/**\n * Check if environment variable key is valid\n */\nexport function isValidEnvKey(key: string): boolean {\n if (!key || key.length === 0) {\n return false\n }\n\n // Must start with letter or underscore, followed by letters, numbers, or underscores\n const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/\n return validKeyRegex.test(key)\n}\n\n/**\n * Load environment variables using dotenv-flow\n * Supports environment-specific files (.env.development, .env.production, etc.)\n * and local overrides (.env.local, .env.development.local)\n */\nexport function loadEnvIntoProcess(options?: {\n path?: string\n nodeEnv?: string\n defaultNodeEnv?: string\n}): { parsed?: Record<string, string>; error?: Error } {\n logger.debug('Loading environment variables with dotenv-flow', {\n options: {\n path: options?.path ?? 'current working directory',\n nodeEnv: options?.nodeEnv ?? 'not specified',\n defaultNodeEnv: options?.defaultNodeEnv ?? 'development (default)'\n }\n })\n\n const configOptions: Partial<DotenvFlowConfigOptions> = {\n silent: true, // Don't throw errors if .env files are missing\n }\n\n // Only add defined values to avoid TypeScript strict type issues\n if (options?.path !== undefined) {\n configOptions.path = options.path\n logger.debug(`Using custom path: ${options.path}`)\n }\n if (options?.nodeEnv !== undefined) {\n configOptions.node_env = options.nodeEnv\n logger.debug(`Using NODE_ENV: ${options.nodeEnv}`)\n }\n if (options?.defaultNodeEnv !== undefined) {\n configOptions.default_node_env = options.defaultNodeEnv\n logger.debug(`Using default NODE_ENV: ${options.defaultNodeEnv}`)\n } else {\n configOptions.default_node_env = 'development'\n logger.debug('Using default NODE_ENV: development')\n }\n\n logger.debug('dotenv-flow config options:', configOptions)\n\n const result = dotenvFlow.config(configOptions)\n\n const returnValue: { parsed?: Record<string, string>; error?: Error } = {}\n\n if (result.parsed) {\n returnValue.parsed = result.parsed as Record<string, string>\n const variableCount = Object.keys(result.parsed).length\n logger.debug(`Successfully loaded ${variableCount} environment variables`)\n } else {\n logger.debug('No environment variables were parsed')\n }\n\n if (result.error) {\n returnValue.error = result.error\n logger.debug('dotenv-flow returned an error', {\n error: result.error.message,\n name: result.error.name\n })\n } else {\n logger.debug('dotenv-flow completed without errors')\n }\n\n return returnValue\n}\n\n/**\n * Check if an error from loadEnvIntoProcess indicates no .env files were found\n * This is a harmless condition that shouldn't be logged as a warning\n */\nexport function isNoEnvFilesFoundError(error: Error): boolean {\n return error.message.startsWith('no \".env*\" files matching pattern')\n}\n\n/**\n * Load environment variables for a specific workspace\n * Automatically determines environment based on NODE_ENV or defaults to development\n */\nexport function loadWorkspaceEnv(workspacePath: string): {\n parsed?: Record<string, string>\n error?: Error\n} {\n const nodeEnv = process.env.NODE_ENV ?? 'development'\n\n logger.debug('Loading workspace environment variables', {\n workspacePath,\n detectedNodeEnv: nodeEnv,\n processNodeEnv: process.env.NODE_ENV ?? 'not set'\n })\n\n return loadEnvIntoProcess({\n path: workspacePath,\n nodeEnv: nodeEnv,\n defaultNodeEnv: 'development'\n })\n}\n\n// CONSTANT: Always use 'development' per critical constraint, unless overridden\nconst DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? 'development'\n\n/**\n * Get dotenv-flow files in precedence order (lowest to highest)\n * Always uses 'development' as NODE_ENV per constraint\n */\nexport function getDotenvFlowFiles(): string[] {\n return [\n '.env',\n '.env.local',\n `.env.${DOTENV_FLOW_NODE_ENV}`,\n `.env.${DOTENV_FLOW_NODE_ENV}.local`\n ]\n}\n\n/**\n * Map a file to its \"local\" equivalent for git-safe writes\n * .env -> .env.local\n * .env.{NODE_ENV} -> .env.{NODE_ENV}.local\n * Already local files return unchanged\n */\nexport function getLocalEquivalent(filename: string): string {\n // Already a .local file\n if (filename.endsWith('.local')) {\n return filename\n }\n return `${filename}.local`\n}\n\n/**\n * Find the appropriate env file to write a database URL variable to\n * Considers dotenv-flow precedence and git tracking status\n * Returns path relative to workspacePath\n *\n * Algorithm:\n * 1. Search files in reverse precedence order (highest first)\n * 2. Find first file containing the variable\n * 3. If tracked by git, return its .local equivalent\n * 4. If not tracked, return the file itself\n * 5. If not found anywhere, return '.env.local' (safe default)\n */\nexport async function findEnvFileForDatabaseUrl(\n workspacePath: string,\n variableName: string,\n isFileTracked: (filePath: string, cwd: string) => Promise<boolean>,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string> {\n // Find the highest-precedence file containing the variable\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n\n if (file === null) {\n // Variable not found anywhere - use safe default\n return '.env.local'\n }\n\n // Found the variable - check git tracking\n const isTracked = await isFileTracked(file, workspacePath)\n if (isTracked) {\n // Return .local equivalent for git safety\n return getLocalEquivalent(file)\n }\n\n return file\n}\n\n/**\n * Build shell source commands for all existing dotenv-flow files\n * Returns commands in precedence order (later overrides earlier)\n */\nexport async function buildEnvSourceCommands(\n workspacePath: string,\n fileExists: (filePath: string) => Promise<boolean>\n): Promise<string[]> {\n const files = getDotenvFlowFiles()\n const commands: string[] = []\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n const exists = await fileExists(fullPath)\n if (exists) {\n commands.push(`source ${file}`)\n }\n }\n\n return commands\n}\n\n/**\n * Find the highest-precedence env file containing a variable\n * Searches all dotenv-flow files in reverse precedence order (highest first)\n * Returns the relative filename if found, null otherwise\n */\nexport async function findEnvFileContainingVariable(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string | null> {\n const files = getDotenvFlowFiles().reverse() // highest precedence first\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n\n // Skip if file doesn't exist\n if (!(await fileExists(fullPath))) {\n continue\n }\n\n // Check if file contains the variable\n const value = await getEnvVariable(fullPath, variableName)\n if (value !== null) {\n return file\n }\n }\n\n return null\n}\n\n/**\n * Check if a variable exists in any dotenv-flow file\n * Searches all dotenv-flow files (.env, .env.local, .env.{NODE_ENV}, .env.{NODE_ENV}.local)\n * Returns true if variable is found in any file, false otherwise\n */\nexport async function hasVariableInAnyEnvFile(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<boolean> {\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n return file !== null\n}\n","// Lines 1-5: Imports\nimport chalk, { Chalk } from 'chalk'\nimport { detectDarkMode, type ThemeMode } from './terminal.js'\n\n// Lines 7-17: Type definitions\nexport interface LoggerOptions {\n prefix?: string\n timestamp?: boolean\n silent?: boolean\n forceColor?: boolean | undefined | null\n debug?: boolean\n}\n\nexport interface Logger {\n info: (message: string, ...args: unknown[]) => void\n success: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n setDebug: (enabled: boolean) => void\n isDebugEnabled: () => boolean\n stdout: NodeJS.WriteStream // Stream for progress output (stdout normally, stderr in JSON mode)\n}\n\n// Lines 19-29: Stream-specific chalk instances\nconst stdoutChalk = new Chalk({ level: chalk.level })\nconst stderrChalk = new Chalk({ level: chalk.level })\n\n// Lines 31-60: Theme-aware color selection\nlet currentThemeMode: ThemeMode = 'light'\n\n/**\n * Initialize theme mode detection\n * This is called automatically on module load\n */\nasync function initializeThemeMode(): Promise<void> {\n try {\n currentThemeMode = await detectDarkMode()\n } catch {\n // Default to light mode on error\n currentThemeMode = 'light'\n }\n}\n\n// Initialize theme mode on module load (non-blocking)\nvoid initializeThemeMode()\n\n/**\n * Get color function based on current theme mode\n * Light mode uses standard colors, dark mode uses brighter/more saturated variants\n */\nfunction getInfoColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.cyan : chalkInstance.blue\n}\n\nfunction getSuccessColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.greenBright : chalkInstance.green\n}\n\nfunction getWarnColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.yellowBright : chalkInstance.yellow\n}\n\nfunction getErrorColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.redBright : chalkInstance.red\n}\n\nfunction getDebugColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.gray : chalkInstance.gray\n}\n\n// Lines 31-45: Helper functions\nfunction formatMessage(message: string, ...args: unknown[]): string {\n // Convert args to strings and append to message\n const formattedArgs = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)\n )\n return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(' ')}` : message\n}\n\nfunction formatWithEmoji(message: string, emoji: string, colorFn: (str: string) => string): string {\n if (message.trim()) {\n return colorFn(`${emoji} ${message}`)\n } else {\n return ''\n }\n}\n\nlet globalDebugEnabled = false\n\n// Lines 47-96: Main logger implementation\n/* eslint-disable no-console */\nexport const logger: Logger = {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🗂️ ', getInfoColor(stdoutChalk))\n console.log(output)\n },\n\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '✅', getSuccessColor(stdoutChalk))\n console.log(output)\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '⚠️ ', getWarnColor(stderrChalk))\n console.error(output)\n },\n\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '❌', getErrorColor(stderrChalk))\n console.error(output)\n },\n\n debug: (message: string, ...args: unknown[]): void => {\n if (globalDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🔍', getDebugColor(stdoutChalk))\n console.log(output)\n }\n },\n\n setDebug: (enabled: boolean): void => {\n globalDebugEnabled = enabled\n },\n\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n\n stdout: process.stdout\n}\n/* eslint-enable no-console */\n\n// Lines 98-145: Factory function for custom logger instances\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customStdoutChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stdoutChalk\n const customStderrChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n if (silent) {\n // Return no-op logger when silent\n return {\n info: (): void => {},\n success: (): void => {},\n warn: (): void => {},\n error: (): void => {},\n debug: (): void => {},\n setDebug: (): void => {},\n isDebugEnabled: (): boolean => {\n return false\n },\n stdout: process.stdout\n }\n }\n\n /* eslint-disable no-console */\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customStdoutChalk))\n console.log(output)\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customStdoutChalk))\n console.log(output)\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customStderrChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customStderrChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customStdoutChalk))\n console.log(output)\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stdout\n }\n /* eslint-enable no-console */\n}\n\n// Lines 147-200: Factory function for stderr-only logger (for JSON mode)\n/**\n * Creates a logger that redirects all output to stderr.\n * Use this in JSON mode so progress messages don't pollute stdout.\n * The JSON output can then be cleanly piped.\n */\nexport function createStderrLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customChalk))\n console.error(output) // Redirect to stderr\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stderr // Use stderr for progress output in JSON mode\n }\n}\n\n/**\n * Set the theme mode for logger colors\n * This is useful for testing or overriding auto-detection\n *\n * @param mode - Theme mode to use ('light' or 'dark')\n */\nexport function setThemeMode(mode: ThemeMode): void {\n currentThemeMode = mode\n}\n\n/**\n * Get the current theme mode\n *\n * @returns Current theme mode\n */\nexport function getThemeMode(): ThemeMode {\n return currentThemeMode\n}\n\n// Default export\nexport default logger\n","import { execa } from 'execa'\nimport type { Platform } from '../types/index.js'\nimport { getTerminalBackend } from './terminal-backends/index.js'\nimport { detectITerm2 as darwinDetectITerm2 } from './terminal-backends/darwin.js'\nimport { detectTerminalEnvironment } from './platform-detect.js'\n\nexport interface TerminalWindowOptions {\n\tworkspacePath?: string\n\tcommand?: string\n\tbackgroundColor?: { r: number; g: number; b: number }\n\tport?: number\n\tincludeEnvSetup?: boolean // source .env\n\tincludePortExport?: boolean // export PORT=<port>\n\ttitle?: string // Terminal tab title\n}\n\n/**\n * Detect current platform.\n *\n * Delegates to detectTerminalEnvironment() from platform-detect.ts,\n * mapping 'wsl' back to 'linux' to preserve the Platform return type.\n */\nexport function detectPlatform(): Platform {\n\tconst env = detectTerminalEnvironment()\n\tif (env === 'wsl') return 'linux'\n\treturn env\n}\n\n/**\n * Theme mode for color palette selection\n */\nexport type ThemeMode = 'light' | 'dark'\n\n/**\n * Detect macOS dark mode using defaults command\n * Returns 'light' as default for non-macOS platforms or detection failures\n *\n * Uses `defaults read -g AppleInterfaceStyle` which returns \"Dark\" in dark mode\n * and errors (exit code 1) in light mode. This approach doesn't require\n * System Events permission unlike AppleScript.\n */\nexport async function detectDarkMode(): Promise<ThemeMode> {\n\tconst platform = detectPlatform()\n\tif (platform !== 'darwin') {\n\t\treturn 'light'\n\t}\n\n\ttry {\n\t\tconst result = await execa('defaults', ['read', '-g', 'AppleInterfaceStyle'])\n\t\treturn result.stdout.trim().toLowerCase() === 'dark' ? 'dark' : 'light'\n\t} catch {\n\t\t// defaults command errors when AppleInterfaceStyle is not set (light mode)\n\t\treturn 'light'\n\t}\n}\n\n/**\n * Detect if iTerm2 is installed on macOS.\n * Returns false on non-macOS platforms.\n *\n * Delegates to the canonical implementation in darwin.ts.\n */\nexport async function detectITerm2(): Promise<boolean> {\n\tif (detectPlatform() !== 'darwin') return false\n\treturn darwinDetectITerm2()\n}\n\n/**\n * Open new terminal window with specified options.\n * Supports macOS (Terminal.app/iTerm2), WSL (Windows Terminal),\n * Linux GUI terminals (gnome-terminal/konsole/xterm), and tmux for headless.\n */\nexport async function openTerminalWindow(\n\toptions: TerminalWindowOptions\n): Promise<void> {\n\tconst backend = await getTerminalBackend()\n\tawait backend.openSingle(options)\n}\n\n/**\n * Open multiple terminal windows/tabs (2+) with specified options.\n * On macOS with iTerm2, creates a single window with multiple tabs.\n * On WSL, creates multiple Windows Terminal tabs.\n * On Linux, uses the detected terminal emulator or tmux.\n */\nexport async function openMultipleTerminalWindows(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<void> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.')\n\t}\n\n\tconst backend = await getTerminalBackend()\n\tawait backend.openMultiple(optionsArray)\n}\n\n/**\n * Open dual terminal windows/tabs with specified options\n * If iTerm2 is available on macOS, creates single window with two tabs\n * Otherwise falls back to two separate Terminal.app windows\n */\nexport async function openDualTerminalWindow(\n\toptions1: TerminalWindowOptions,\n\toptions2: TerminalWindowOptions\n): Promise<void> {\n\tawait openMultipleTerminalWindows([options1, options2])\n}\n","import { readFileSync } from 'node:fs'\n\n/**\n * Terminal environment types.\n * 'darwin' = macOS, 'wsl' = Windows Subsystem for Linux, 'linux' = native Linux, 'win32' = native Windows\n */\nexport type TerminalEnvironment = 'darwin' | 'wsl' | 'linux' | 'win32' | 'unsupported'\n\nlet cachedIsWSL: boolean | undefined\n\n/**\n * Detect if running inside Windows Subsystem for Linux.\n *\n * Detection strategy (in order):\n * 1. Check WSL_DISTRO_NAME env var (always set in WSL2, most reliable)\n * 2. Fallback: read /proc/version for \"microsoft\" or \"WSL\" signature\n *\n * Result is cached to avoid repeated /proc reads.\n */\nexport function isWSL(): boolean {\n\tif (cachedIsWSL !== undefined) {\n\t\treturn cachedIsWSL\n\t}\n\n\tif (process.platform !== 'linux') {\n\t\tcachedIsWSL = false\n\t\treturn false\n\t}\n\n\t// Most reliable: WSL_DISTRO_NAME is always set in WSL2\n\tif (process.env.WSL_DISTRO_NAME) {\n\t\tcachedIsWSL = true\n\t\treturn true\n\t}\n\n\t// Fallback: check /proc/version for WSL signature\n\ttry {\n\t\tconst procVersion = readFileSync('/proc/version', 'utf-8')\n\t\tcachedIsWSL = /microsoft|wsl/i.test(procVersion)\n\t\treturn cachedIsWSL\n\t} catch (error: unknown) {\n\t\t// /proc/version not found — not WSL\n\t\tif (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT') {\n\t\t\tcachedIsWSL = false\n\t\t\treturn false\n\t\t}\n\t\t// Unexpected error — assume not WSL\n\t\tcachedIsWSL = false\n\t\treturn false\n\t}\n}\n\n/**\n * Detect the terminal environment, distinguishing WSL from plain Linux.\n */\nexport function detectTerminalEnvironment(): TerminalEnvironment {\n\tconst platform = process.platform\n\tif (platform === 'darwin') return 'darwin'\n\tif (platform === 'win32') return 'win32'\n\tif (platform === 'linux') {\n\t\treturn isWSL() ? 'wsl' : 'linux'\n\t}\n\treturn 'unsupported'\n}\n\n/**\n * Get the WSL distribution name from the environment.\n * Returns undefined when not running in WSL or when the variable is not set.\n */\nexport function detectWSLDistro(): string | undefined {\n\tconst distro = process.env.WSL_DISTRO_NAME\n\t// Empty string means unset; nullish coalescing won't catch it\n\tif (!distro) return undefined\n\treturn distro\n}\n\n/**\n * Reset the cached WSL detection result.\n * Exposed for testing only.\n */\nexport function _resetWSLCache(): void {\n\tcachedIsWSL = undefined\n}\n","import { detectTerminalEnvironment } from '../platform-detect.js'\nimport type { TerminalBackend } from './types.js'\n\nexport type { TerminalBackend } from './types.js'\n\n/**\n * Get the appropriate terminal backend for the current platform.\n *\n * - macOS → DarwinBackend (Terminal.app / iTerm2)\n * - WSL → WSLBackend (Windows Terminal via wt.exe)\n * - Linux → LinuxBackend (gnome-terminal / konsole / xterm) with TmuxBackend fallback\n *\n * On Linux, if no GUI terminal emulator is detected (headless SSH, Docker,\n * Code Server, etc.), falls back to tmux automatically.\n *\n * Throws a descriptive error on unsupported platforms or when no backend is available.\n */\nexport async function getTerminalBackend(): Promise<TerminalBackend> {\n\tconst env = detectTerminalEnvironment()\n\n\tswitch (env) {\n\t\tcase 'darwin': {\n\t\t\tconst { DarwinBackend } = await import('./darwin.js')\n\t\t\treturn new DarwinBackend()\n\t\t}\n\t\tcase 'wsl': {\n\t\t\tconst { WSLBackend } = await import('./wsl.js')\n\t\t\treturn new WSLBackend()\n\t\t}\n\t\tcase 'linux': {\n\t\t\t// Only try GUI terminals if a display server is available.\n\t\t\t// A terminal emulator like konsole may be installed but unusable\n\t\t\t// without X11/Wayland (e.g., SSH, Docker, Code Server).\n\t\t\tconst hasDisplay = !!(process.env.DISPLAY ?? process.env.WAYLAND_DISPLAY)\n\n\t\t\tif (hasDisplay) {\n\t\t\t\tconst { detectLinuxTerminal } = await import('./linux.js')\n\t\t\t\tif (await detectLinuxTerminal()) {\n\t\t\t\t\tconst { LinuxBackend } = await import('./linux.js')\n\t\t\t\t\treturn new LinuxBackend()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fall back to tmux for headless environments\n\t\t\tconst { isTmuxAvailable, TmuxBackend } = await import('./tmux.js')\n\t\t\tif (await isTmuxAvailable()) {\n\t\t\t\treturn new TmuxBackend()\n\t\t\t}\n\n\t\t\tthrow new Error(\n\t\t\t\t'No supported terminal found on Linux. ' +\n\t\t\t\t'Install tmux for headless environments, or set DISPLAY and install a GUI terminal (gnome-terminal, konsole, xterm).'\n\t\t\t)\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(\n\t\t\t\t`Terminal window launching is not supported on ${env}. ` +\n\t\t\t\t'Supported platforms: macOS, WSL (Windows Terminal), Linux (GUI terminals or tmux).'\n\t\t\t)\n\t}\n}\n"],"mappings":"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","names":["execa","existsSync","DarwinBackend","detectITerm2","existsSync","execa"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/terminal-backends/darwin.ts","../src/utils/terminal-backends/command-builder.ts","../src/utils/env.ts","../src/utils/logger.ts","../src/utils/terminal.ts","../src/utils/platform-detect.ts","../src/utils/terminal-backends/index.ts"],"sourcesContent":["import { execa } from 'execa'\nimport { existsSync } from 'node:fs'\nimport type { TerminalWindowOptions } from '../terminal.js'\nimport type { TerminalBackend } from './types.js'\nimport { buildCommandSequence } from './command-builder.js'\n\n/**\n * Detect if iTerm2 is installed on macOS.\n */\nexport function detectITerm2(): boolean {\n\treturn existsSync('/Applications/iTerm.app')\n}\n\n/**\n * Escape command string for embedding inside an AppleScript `do script \"...\"`.\n */\nfunction escapeForAppleScript(command: string): string {\n\treturn command\n\t\t.replace(/\\\\/g, '\\\\\\\\')\n\t\t.replace(/\"/g, '\\\\\"')\n}\n\n/**\n * Build AppleScript for macOS Terminal.app (single tab).\n *\n * Delegates to the shared buildCommandSequence for command construction,\n * then wraps the result with AppleScript escaping for `do script \"...\"`.\n */\nasync function buildTerminalAppScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = `tell application \"Terminal\"\\n`\n\tscript += ` set newTab to do script \"${escapeForAppleScript(command)}\"\\n`\n\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += `end tell`\n\treturn script\n}\n\n/**\n * Build iTerm2 AppleScript for a single tab in a new window.\n */\nasync function buildITerm2SingleTabScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set s1 to current session of current window\\n\\n'\n\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\tif (options.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t}\n\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\treturn script\n}\n\n/**\n * Build iTerm2 AppleScript for multiple tabs (2+) in a single window.\n */\nasync function buildITerm2MultiTabScript(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<string> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('buildITerm2MultiTabScript requires at least 2 terminal options')\n\t}\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set newWindow to current window\\n'\n\n\tconst options1 = optionsArray[0]\n\tif (!options1) {\n\t\tthrow new Error('First terminal option is undefined')\n\t}\n\tconst command1 = await buildCommandSequence(options1)\n\n\tscript += ' set s1 to current session of newWindow\\n\\n'\n\n\tif (options1.backgroundColor) {\n\t\tconst { r, g, b } = options1.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command1)}\"\\n\\n`\n\n\tif (options1.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options1.title)}\"\\n\\n`\n\t}\n\n\tfor (let i = 1; i < optionsArray.length; i++) {\n\t\tconst options = optionsArray[i]\n\t\tif (!options) {\n\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t}\n\t\tconst command = await buildCommandSequence(options)\n\t\tconst sessionVar = `s${i + 1}`\n\n\t\tscript += ' tell newWindow\\n'\n\t\tscript += ` set newTab${i} to (create tab with default profile)\\n`\n\t\tscript += ' end tell\\n'\n\t\tscript += ` set ${sessionVar} to current session of newTab${i}\\n\\n`\n\n\t\tif (options.backgroundColor) {\n\t\t\tconst { r, g, b } = options.backgroundColor\n\t\t\tscript += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t\t}\n\n\t\tscript += ` tell ${sessionVar} to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t\tif (options.title) {\n\t\t\tscript += ` set name of ${sessionVar} to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t\t}\n\t}\n\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\treturn script\n}\n\n/**\n * macOS terminal backend — supports Terminal.app and iTerm2.\n */\nexport class DarwinBackend implements TerminalBackend {\n\treadonly name = 'darwin'\n\n\tasync openSingle(options: TerminalWindowOptions): Promise<void> {\n\t\tconst hasITerm2 = detectITerm2()\n\n\t\tconst applescript = hasITerm2\n\t\t\t? await buildITerm2SingleTabScript(options)\n\t\t\t: await buildTerminalAppScript(options)\n\n\t\ttry {\n\t\t\tawait execa('osascript', ['-e', applescript])\n\n\t\t\tif (!hasITerm2) {\n\t\t\t\tawait execa('osascript', ['-e', 'tell application \"Terminal\" to activate'])\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to open terminal window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\tasync openMultiple(optionsArray: TerminalWindowOptions[]): Promise<void> {\n\t\tconst hasITerm2 = detectITerm2()\n\n\t\tif (hasITerm2) {\n\t\t\tconst applescript = await buildITerm2MultiTabScript(optionsArray)\n\n\t\t\ttry {\n\t\t\t\tawait execa('osascript', ['-e', applescript])\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to open iTerm2 window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t\t)\n\t\t\t}\n\t\t} else {\n\t\t\tfor (let i = 0; i < optionsArray.length; i++) {\n\t\t\t\tconst options = optionsArray[i]\n\t\t\t\tif (!options) {\n\t\t\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t\t\t}\n\t\t\t\tawait this.openSingle(options)\n\n\t\t\t\tif (i < optionsArray.length - 1) {\n\t\t\t\t\tawait new Promise<void>((resolve) => globalThis.setTimeout(resolve, 1000))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n","import { existsSync } from 'node:fs'\nimport type { TerminalWindowOptions } from '../terminal.js'\nimport { buildEnvSourceCommands } from '../env.js'\n\n/**\n * Build the shell command sequence from TerminalWindowOptions.\n *\n * The returned string is a chain of commands joined by ` && `, prefixed with\n * a space to prevent shell history pollution (HISTCONTROL=ignorespace).\n *\n * This logic is shared across all backends — each backend applies its own\n * escaping on top of the raw command string.\n */\nexport async function buildCommandSequence(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\tconst commands: string[] = []\n\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapeSingleQuotes(workspacePath)}'`)\n\t}\n\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\treturn ` ${fullCommand}`\n}\n\n/**\n * Escape single quotes for use inside a single-quoted shell string.\n * 'it'\\''s' → ends quote, adds escaped quote, resumes quote\n */\nexport function escapeSingleQuotes(s: string): string {\n\treturn s.replace(/'/g, \"'\\\\''\")\n}\n\n/**\n * Convert {r, g, b} (0–255) to a hex color string \"#RRGGBB\".\n */\nexport function rgbToHex(rgb: { r: number; g: number; b: number }): string {\n\tconst toHex = (n: number): string => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, '0')\n\treturn `#${toHex(rgb.r)}${toHex(rgb.g)}${toHex(rgb.b)}`\n}\n","import path from 'path'\nimport dotenvFlow, { type DotenvFlowConfigOptions } from 'dotenv-flow'\nimport { logger } from './logger.js'\n\n/**\n * Parse .env file content into key-value map\n * Handles comments, empty lines, quoted/unquoted values, multiline values\n */\nexport function parseEnvFile(content: string): Map<string, string> {\n const envMap = new Map<string, string>()\n const lines = content.split('\\n')\n\n for (const line of lines) {\n const trimmedLine = line.trim()\n\n // Skip empty lines and comments\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n continue\n }\n\n // Remove 'export ' prefix if present\n const cleanLine = trimmedLine.startsWith('export ')\n ? trimmedLine.substring(7)\n : trimmedLine\n\n // Find the first equals sign\n const equalsIndex = cleanLine.indexOf('=')\n if (equalsIndex === -1) {\n continue\n }\n\n const key = cleanLine.substring(0, equalsIndex).trim()\n let value = cleanLine.substring(equalsIndex + 1)\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.substring(1, value.length - 1)\n // Unescape quotes\n value = value.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\")\n // Unescape newlines\n value = value.replace(/\\\\n/g, '\\n')\n }\n\n if (key) {\n envMap.set(key, value)\n }\n }\n\n return envMap\n}\n\n/**\n * Format environment variable as line for .env file\n * Always quotes values and escapes internal quotes\n */\nexport function formatEnvLine(key: string, value: string): string {\n // Escape quotes and newlines in the value\n const escapedValue = value\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n\n return `${key}=\"${escapedValue}\"`\n}\n\n/**\n * Validate environment variable name and value\n */\nexport function validateEnvVariable(\n key: string,\n _value?: string\n): { valid: boolean; error?: string } {\n if (!key || key.length === 0) {\n return {\n valid: false,\n error: 'Environment variable key cannot be empty',\n }\n }\n\n if (!isValidEnvKey(key)) {\n return {\n valid: false,\n error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`,\n }\n }\n\n // Values can be any string, including empty\n return { valid: true }\n}\n\n/**\n * Normalize line endings for cross-platform compatibility\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n}\n\n/**\n * Extract port from .env file if present\n */\nexport function extractPort(envContent: Map<string, string>): number | null {\n const portValue = envContent.get('PORT')\n if (!portValue) {\n return null\n }\n\n const port = parseInt(portValue, 10)\n if (isNaN(port)) {\n return null\n }\n\n return port\n}\n\n/**\n * Check if environment variable key is valid\n */\nexport function isValidEnvKey(key: string): boolean {\n if (!key || key.length === 0) {\n return false\n }\n\n // Must start with letter or underscore, followed by letters, numbers, or underscores\n const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/\n return validKeyRegex.test(key)\n}\n\n/**\n * Load environment variables using dotenv-flow\n * Supports environment-specific files (.env.development, .env.production, etc.)\n * and local overrides (.env.local, .env.development.local)\n */\nexport function loadEnvIntoProcess(options?: {\n path?: string\n nodeEnv?: string\n defaultNodeEnv?: string\n}): { parsed?: Record<string, string>; error?: Error } {\n logger.debug('Loading environment variables with dotenv-flow', {\n options: {\n path: options?.path ?? 'current working directory',\n nodeEnv: options?.nodeEnv ?? 'not specified',\n defaultNodeEnv: options?.defaultNodeEnv ?? 'development (default)'\n }\n })\n\n const configOptions: Partial<DotenvFlowConfigOptions> = {\n silent: true, // Don't throw errors if .env files are missing\n }\n\n // Only add defined values to avoid TypeScript strict type issues\n if (options?.path !== undefined) {\n configOptions.path = options.path\n logger.debug(`Using custom path: ${options.path}`)\n }\n if (options?.nodeEnv !== undefined) {\n configOptions.node_env = options.nodeEnv\n logger.debug(`Using NODE_ENV: ${options.nodeEnv}`)\n }\n if (options?.defaultNodeEnv !== undefined) {\n configOptions.default_node_env = options.defaultNodeEnv\n logger.debug(`Using default NODE_ENV: ${options.defaultNodeEnv}`)\n } else {\n configOptions.default_node_env = 'development'\n logger.debug('Using default NODE_ENV: development')\n }\n\n logger.debug('dotenv-flow config options:', configOptions)\n\n const result = dotenvFlow.config(configOptions)\n\n const returnValue: { parsed?: Record<string, string>; error?: Error } = {}\n\n if (result.parsed) {\n returnValue.parsed = result.parsed as Record<string, string>\n const variableCount = Object.keys(result.parsed).length\n logger.debug(`Successfully loaded ${variableCount} environment variables`)\n } else {\n logger.debug('No environment variables were parsed')\n }\n\n if (result.error) {\n returnValue.error = result.error\n logger.debug('dotenv-flow returned an error', {\n error: result.error.message,\n name: result.error.name\n })\n } else {\n logger.debug('dotenv-flow completed without errors')\n }\n\n return returnValue\n}\n\n/**\n * Check if an error from loadEnvIntoProcess indicates no .env files were found\n * This is a harmless condition that shouldn't be logged as a warning\n */\nexport function isNoEnvFilesFoundError(error: Error): boolean {\n return error.message.startsWith('no \".env*\" files matching pattern')\n}\n\n/**\n * Load environment variables for a specific workspace\n * Automatically determines environment based on NODE_ENV or defaults to development\n */\nexport function loadWorkspaceEnv(workspacePath: string): {\n parsed?: Record<string, string>\n error?: Error\n} {\n const nodeEnv = process.env.NODE_ENV ?? 'development'\n\n logger.debug('Loading workspace environment variables', {\n workspacePath,\n detectedNodeEnv: nodeEnv,\n processNodeEnv: process.env.NODE_ENV ?? 'not set'\n })\n\n return loadEnvIntoProcess({\n path: workspacePath,\n nodeEnv: nodeEnv,\n defaultNodeEnv: 'development'\n })\n}\n\n// CONSTANT: Always use 'development' per critical constraint, unless overridden\nconst DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? 'development'\n\n/**\n * Get dotenv-flow files in precedence order (lowest to highest)\n * Always uses 'development' as NODE_ENV per constraint\n */\nexport function getDotenvFlowFiles(): string[] {\n return [\n '.env',\n '.env.local',\n `.env.${DOTENV_FLOW_NODE_ENV}`,\n `.env.${DOTENV_FLOW_NODE_ENV}.local`\n ]\n}\n\n/**\n * Map a file to its \"local\" equivalent for git-safe writes\n * .env -> .env.local\n * .env.{NODE_ENV} -> .env.{NODE_ENV}.local\n * Already local files return unchanged\n */\nexport function getLocalEquivalent(filename: string): string {\n // Already a .local file\n if (filename.endsWith('.local')) {\n return filename\n }\n return `${filename}.local`\n}\n\n/**\n * Find the appropriate env file to write a database URL variable to\n * Considers dotenv-flow precedence and git tracking status\n * Returns path relative to workspacePath\n *\n * Algorithm:\n * 1. Search files in reverse precedence order (highest first)\n * 2. Find first file containing the variable\n * 3. If tracked by git, return its .local equivalent\n * 4. If not tracked, return the file itself\n * 5. If not found anywhere, return '.env.local' (safe default)\n */\nexport async function findEnvFileForDatabaseUrl(\n workspacePath: string,\n variableName: string,\n isFileTracked: (filePath: string, cwd: string) => Promise<boolean>,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string> {\n // Find the highest-precedence file containing the variable\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n\n if (file === null) {\n // Variable not found anywhere - use safe default\n return '.env.local'\n }\n\n // Found the variable - check git tracking\n const isTracked = await isFileTracked(file, workspacePath)\n if (isTracked) {\n // Return .local equivalent for git safety\n return getLocalEquivalent(file)\n }\n\n return file\n}\n\n/**\n * Build shell source commands for all existing dotenv-flow files\n * Returns commands in precedence order (later overrides earlier)\n */\nexport async function buildEnvSourceCommands(\n workspacePath: string,\n fileExists: (filePath: string) => Promise<boolean>\n): Promise<string[]> {\n const files = getDotenvFlowFiles()\n const commands: string[] = []\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n const exists = await fileExists(fullPath)\n if (exists) {\n commands.push(`source ${file}`)\n }\n }\n\n return commands\n}\n\n/**\n * Find the highest-precedence env file containing a variable\n * Searches all dotenv-flow files in reverse precedence order (highest first)\n * Returns the relative filename if found, null otherwise\n */\nexport async function findEnvFileContainingVariable(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string | null> {\n const files = getDotenvFlowFiles().reverse() // highest precedence first\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n\n // Skip if file doesn't exist\n if (!(await fileExists(fullPath))) {\n continue\n }\n\n // Check if file contains the variable\n const value = await getEnvVariable(fullPath, variableName)\n if (value !== null) {\n return file\n }\n }\n\n return null\n}\n\n/**\n * Check if a variable exists in any dotenv-flow file\n * Searches all dotenv-flow files (.env, .env.local, .env.{NODE_ENV}, .env.{NODE_ENV}.local)\n * Returns true if variable is found in any file, false otherwise\n */\nexport async function hasVariableInAnyEnvFile(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<boolean> {\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n return file !== null\n}\n","// Lines 1-5: Imports\nimport chalk, { Chalk } from 'chalk'\nimport { detectDarkMode, type ThemeMode } from './terminal.js'\n\n// Lines 7-17: Type definitions\nexport interface LoggerOptions {\n prefix?: string\n timestamp?: boolean\n silent?: boolean\n forceColor?: boolean | undefined | null\n debug?: boolean\n}\n\nexport interface Logger {\n info: (message: string, ...args: unknown[]) => void\n success: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n setDebug: (enabled: boolean) => void\n isDebugEnabled: () => boolean\n stdout: NodeJS.WriteStream // Stream for progress output (stdout normally, stderr in JSON mode)\n}\n\n// Lines 19-29: Stream-specific chalk instances\nconst stdoutChalk = new Chalk({ level: chalk.level })\nconst stderrChalk = new Chalk({ level: chalk.level })\n\n// Lines 31-60: Theme-aware color selection\nlet currentThemeMode: ThemeMode = 'light'\n\n/**\n * Initialize theme mode detection\n * This is called automatically on module load\n */\nasync function initializeThemeMode(): Promise<void> {\n try {\n currentThemeMode = await detectDarkMode()\n } catch {\n // Default to light mode on error\n currentThemeMode = 'light'\n }\n}\n\n// Initialize theme mode on module load (non-blocking)\nvoid initializeThemeMode()\n\n/**\n * Get color function based on current theme mode\n * Light mode uses standard colors, dark mode uses brighter/more saturated variants\n */\nfunction getInfoColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.cyan : chalkInstance.blue\n}\n\nfunction getSuccessColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.greenBright : chalkInstance.green\n}\n\nfunction getWarnColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.yellowBright : chalkInstance.yellow\n}\n\nfunction getErrorColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.redBright : chalkInstance.red\n}\n\nfunction getDebugColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.gray : chalkInstance.gray\n}\n\n// Lines 31-45: Helper functions\nfunction formatMessage(message: string, ...args: unknown[]): string {\n // Convert args to strings and append to message\n const formattedArgs = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)\n )\n return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(' ')}` : message\n}\n\nfunction formatWithEmoji(message: string, emoji: string, colorFn: (str: string) => string): string {\n if (message.trim()) {\n return colorFn(`${emoji} ${message}`)\n } else {\n return ''\n }\n}\n\nlet globalDebugEnabled = false\n\n// Lines 47-96: Main logger implementation\n/* eslint-disable no-console */\nexport const logger: Logger = {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🗂️ ', getInfoColor(stdoutChalk))\n console.log(output)\n },\n\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '✅', getSuccessColor(stdoutChalk))\n console.log(output)\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '⚠️ ', getWarnColor(stderrChalk))\n console.error(output)\n },\n\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '❌', getErrorColor(stderrChalk))\n console.error(output)\n },\n\n debug: (message: string, ...args: unknown[]): void => {\n if (globalDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🔍', getDebugColor(stdoutChalk))\n console.log(output)\n }\n },\n\n setDebug: (enabled: boolean): void => {\n globalDebugEnabled = enabled\n },\n\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n\n stdout: process.stdout\n}\n/* eslint-enable no-console */\n\n// Lines 98-145: Factory function for custom logger instances\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customStdoutChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stdoutChalk\n const customStderrChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n if (silent) {\n // Return no-op logger when silent\n return {\n info: (): void => {},\n success: (): void => {},\n warn: (): void => {},\n error: (): void => {},\n debug: (): void => {},\n setDebug: (): void => {},\n isDebugEnabled: (): boolean => {\n return false\n },\n stdout: process.stdout\n }\n }\n\n /* eslint-disable no-console */\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customStdoutChalk))\n console.log(output)\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customStdoutChalk))\n console.log(output)\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customStderrChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customStderrChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customStdoutChalk))\n console.log(output)\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stdout\n }\n /* eslint-enable no-console */\n}\n\n// Lines 147-200: Factory function for stderr-only logger (for JSON mode)\n/**\n * Creates a logger that redirects all output to stderr.\n * Use this in JSON mode so progress messages don't pollute stdout.\n * The JSON output can then be cleanly piped.\n */\nexport function createStderrLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customChalk))\n console.error(output) // Redirect to stderr\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stderr // Use stderr for progress output in JSON mode\n }\n}\n\n/**\n * Set the theme mode for logger colors\n * This is useful for testing or overriding auto-detection\n *\n * @param mode - Theme mode to use ('light' or 'dark')\n */\nexport function setThemeMode(mode: ThemeMode): void {\n currentThemeMode = mode\n}\n\n/**\n * Get the current theme mode\n *\n * @returns Current theme mode\n */\nexport function getThemeMode(): ThemeMode {\n return currentThemeMode\n}\n\n// Default export\nexport default logger\n","import { execSync } from 'child_process'\nimport { execa } from 'execa'\nimport type { Platform } from '../types/index.js'\nimport { getTerminalBackend } from './terminal-backends/index.js'\nimport { detectITerm2 as darwinDetectITerm2 } from './terminal-backends/darwin.js'\nimport { detectTerminalEnvironment } from './platform-detect.js'\n\nexport interface TerminalWindowOptions {\n\tworkspacePath?: string\n\tcommand?: string\n\tbackgroundColor?: { r: number; g: number; b: number }\n\tport?: number\n\tincludeEnvSetup?: boolean // source .env\n\tincludePortExport?: boolean // export PORT=<port>\n\ttitle?: string // Terminal tab title\n}\n\n/**\n * Detect current platform.\n *\n * Delegates to detectTerminalEnvironment() from platform-detect.ts,\n * mapping 'wsl' back to 'linux' to preserve the Platform return type.\n */\nexport function detectPlatform(): Platform {\n\tconst env = detectTerminalEnvironment()\n\tif (env === 'wsl') return 'linux'\n\treturn env\n}\n\n/**\n * Theme mode for color palette selection\n */\nexport type ThemeMode = 'light' | 'dark'\n\n/**\n * Detect macOS dark mode using defaults command\n * Returns 'light' as default for non-macOS platforms or detection failures\n *\n * Uses `defaults read -g AppleInterfaceStyle` which returns \"Dark\" in dark mode\n * and errors (exit code 1) in light mode. This approach doesn't require\n * System Events permission unlike AppleScript.\n */\nexport async function detectDarkMode(): Promise<ThemeMode> {\n\tconst platform = detectPlatform()\n\tif (platform !== 'darwin') {\n\t\treturn 'light'\n\t}\n\n\ttry {\n\t\tconst result = await execa('defaults', ['read', '-g', 'AppleInterfaceStyle'])\n\t\treturn result.stdout.trim().toLowerCase() === 'dark' ? 'dark' : 'light'\n\t} catch {\n\t\t// defaults command errors when AppleInterfaceStyle is not set (light mode)\n\t\treturn 'light'\n\t}\n}\n\n/**\n * Detect if iTerm2 is installed on macOS.\n * Returns false on non-macOS platforms.\n *\n * Delegates to the canonical implementation in darwin.ts.\n */\nexport async function detectITerm2(): Promise<boolean> {\n\tif (detectPlatform() !== 'darwin') return false\n\treturn darwinDetectITerm2()\n}\n\n/**\n * Open new terminal window with specified options.\n * Supports macOS (Terminal.app/iTerm2), WSL (Windows Terminal),\n * Linux GUI terminals (gnome-terminal/konsole/xterm), and tmux for headless.\n */\nexport async function openTerminalWindow(\n\toptions: TerminalWindowOptions\n): Promise<void> {\n\tconst backend = await getTerminalBackend()\n\tawait backend.openSingle(options)\n}\n\n/**\n * Open multiple terminal windows/tabs (2+) with specified options.\n * On macOS with iTerm2, creates a single window with multiple tabs.\n * On WSL, creates multiple Windows Terminal tabs.\n * On Linux, uses the detected terminal emulator or tmux.\n */\nexport async function openMultipleTerminalWindows(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<void> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.')\n\t}\n\n\tconst backend = await getTerminalBackend()\n\tawait backend.openMultiple(optionsArray)\n}\n\n/**\n * Open dual terminal windows/tabs with specified options\n * If iTerm2 is available on macOS, creates single window with two tabs\n * Otherwise falls back to two separate Terminal.app windows\n */\nexport async function openDualTerminalWindow(\n\toptions1: TerminalWindowOptions,\n\toptions2: TerminalWindowOptions\n): Promise<void> {\n\tawait openMultipleTerminalWindows([options1, options2])\n}\n\n/**\n * Restore terminal state after a child process may have left it in a bad state.\n *\n * Uses `stty sane` which resets terminal line settings to reasonable defaults.\n * This is more reliable than Node's `setRawMode(false)` because child processes\n * (e.g., dev servers) may change tty settings directly on the shared fd, and\n * Node's API doesn't reliably undo those changes.\n *\n * This function never throws — terminal restoration is best-effort.\n */\nexport function restoreTerminalState(): void {\n\tif (!process.stdin.isTTY) {\n\t\treturn\n\t}\n\ttry {\n\t\texecSync('stty sane', { stdio: 'ignore' })\n\t} catch {\n\t\t// Best-effort: if stty fails, there's nothing more we can do\n\t}\n}\n","import { readFileSync } from 'node:fs'\n\n/**\n * Terminal environment types.\n * 'darwin' = macOS, 'wsl' = Windows Subsystem for Linux, 'linux' = native Linux, 'win32' = native Windows\n */\nexport type TerminalEnvironment = 'darwin' | 'wsl' | 'linux' | 'win32' | 'unsupported'\n\nlet cachedIsWSL: boolean | undefined\n\n/**\n * Detect if running inside Windows Subsystem for Linux.\n *\n * Detection strategy (in order):\n * 1. Check WSL_DISTRO_NAME env var (always set in WSL2, most reliable)\n * 2. Fallback: read /proc/version for \"microsoft\" or \"WSL\" signature\n *\n * Result is cached to avoid repeated /proc reads.\n */\nexport function isWSL(): boolean {\n\tif (cachedIsWSL !== undefined) {\n\t\treturn cachedIsWSL\n\t}\n\n\tif (process.platform !== 'linux') {\n\t\tcachedIsWSL = false\n\t\treturn false\n\t}\n\n\t// Most reliable: WSL_DISTRO_NAME is always set in WSL2\n\tif (process.env.WSL_DISTRO_NAME) {\n\t\tcachedIsWSL = true\n\t\treturn true\n\t}\n\n\t// Fallback: check /proc/version for WSL signature\n\ttry {\n\t\tconst procVersion = readFileSync('/proc/version', 'utf-8')\n\t\tcachedIsWSL = /microsoft|wsl/i.test(procVersion)\n\t\treturn cachedIsWSL\n\t} catch (error: unknown) {\n\t\t// /proc/version not found — not WSL\n\t\tif (error instanceof Error && 'code' in error && (error as NodeJS.ErrnoException).code === 'ENOENT') {\n\t\t\tcachedIsWSL = false\n\t\t\treturn false\n\t\t}\n\t\t// Unexpected error — assume not WSL\n\t\tcachedIsWSL = false\n\t\treturn false\n\t}\n}\n\n/**\n * Detect the terminal environment, distinguishing WSL from plain Linux.\n */\nexport function detectTerminalEnvironment(): TerminalEnvironment {\n\tconst platform = process.platform\n\tif (platform === 'darwin') return 'darwin'\n\tif (platform === 'win32') return 'win32'\n\tif (platform === 'linux') {\n\t\treturn isWSL() ? 'wsl' : 'linux'\n\t}\n\treturn 'unsupported'\n}\n\n/**\n * Get the WSL distribution name from the environment.\n * Returns undefined when not running in WSL or when the variable is not set.\n */\nexport function detectWSLDistro(): string | undefined {\n\tconst distro = process.env.WSL_DISTRO_NAME\n\t// Empty string means unset; nullish coalescing won't catch it\n\tif (!distro) return undefined\n\treturn distro\n}\n\n/**\n * Reset the cached WSL detection result.\n * Exposed for testing only.\n */\nexport function _resetWSLCache(): void {\n\tcachedIsWSL = undefined\n}\n","import { detectTerminalEnvironment } from '../platform-detect.js'\nimport type { TerminalBackend } from './types.js'\n\nexport type { TerminalBackend } from './types.js'\n\n/**\n * Get the appropriate terminal backend for the current platform.\n *\n * - macOS → DarwinBackend (Terminal.app / iTerm2)\n * - WSL → WSLBackend (Windows Terminal via wt.exe)\n * - Linux → LinuxBackend (gnome-terminal / konsole / xterm) with TmuxBackend fallback\n *\n * On Linux, if no GUI terminal emulator is detected (headless SSH, Docker,\n * Code Server, etc.), falls back to tmux automatically.\n *\n * Throws a descriptive error on unsupported platforms or when no backend is available.\n */\nexport async function getTerminalBackend(): Promise<TerminalBackend> {\n\tconst env = detectTerminalEnvironment()\n\n\tswitch (env) {\n\t\tcase 'darwin': {\n\t\t\tconst { DarwinBackend } = await import('./darwin.js')\n\t\t\treturn new DarwinBackend()\n\t\t}\n\t\tcase 'wsl': {\n\t\t\tconst { WSLBackend } = await import('./wsl.js')\n\t\t\treturn new WSLBackend()\n\t\t}\n\t\tcase 'linux': {\n\t\t\t// Only try GUI terminals if a display server is available.\n\t\t\t// A terminal emulator like konsole may be installed but unusable\n\t\t\t// without X11/Wayland (e.g., SSH, Docker, Code Server).\n\t\t\tconst hasDisplay = !!(process.env.DISPLAY ?? process.env.WAYLAND_DISPLAY)\n\n\t\t\tif (hasDisplay) {\n\t\t\t\tconst { detectLinuxTerminal } = await import('./linux.js')\n\t\t\t\tif (await detectLinuxTerminal()) {\n\t\t\t\t\tconst { LinuxBackend } = await import('./linux.js')\n\t\t\t\t\treturn new LinuxBackend()\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Fall back to tmux for headless environments\n\t\t\tconst { isTmuxAvailable, TmuxBackend } = await import('./tmux.js')\n\t\t\tif (await isTmuxAvailable()) {\n\t\t\t\treturn new TmuxBackend()\n\t\t\t}\n\n\t\t\tthrow new Error(\n\t\t\t\t'No supported terminal found on Linux. ' +\n\t\t\t\t'Install tmux for headless environments, or set DISPLAY and install a GUI terminal (gnome-terminal, konsole, xterm).'\n\t\t\t)\n\t\t}\n\t\tdefault:\n\t\t\tthrow new Error(\n\t\t\t\t`Terminal window launching is not supported on ${env}. ` +\n\t\t\t\t'Supported platforms: macOS, WSL (Windows Terminal), Linux (GUI terminals or tmux).'\n\t\t\t)\n\t}\n}\n"],"mappings":";;;AAAA,SAAS,SAAAA,cAAa;AACtB,SAAS,cAAAC,mBAAkB;;;ACD3B,SAAS,kBAAkB;;;ACA3B,OAAO,UAAU;AACjB,OAAO,gBAAkD;;;ACAzD,OAAO,SAAS,aAAa;;;ACD7B,SAAS,gBAAgB;AACzB,SAAS,aAAa;;;ACDtB,SAAS,oBAAoB;AAQ7B,IAAI;AAWG,SAAS,QAAiB;AAChC,MAAI,gBAAgB,QAAW;AAC9B,WAAO;AAAA,EACR;AAEA,MAAI,QAAQ,aAAa,SAAS;AACjC,kBAAc;AACd,WAAO;AAAA,EACR;AAGA,MAAI,QAAQ,IAAI,iBAAiB;AAChC,kBAAc;AACd,WAAO;AAAA,EACR;AAGA,MAAI;AACH,UAAM,cAAc,aAAa,iBAAiB,OAAO;AACzD,kBAAc,iBAAiB,KAAK,WAAW;AAC/C,WAAO;AAAA,EACR,SAAS,OAAgB;AAExB,QAAI,iBAAiB,SAAS,UAAU,SAAU,MAAgC,SAAS,UAAU;AACpG,oBAAc;AACd,aAAO;AAAA,IACR;AAEA,kBAAc;AACd,WAAO;AAAA,EACR;AACD;AAKO,SAAS,4BAAiD;AAChE,QAAM,WAAW,QAAQ;AACzB,MAAI,aAAa,SAAU,QAAO;AAClC,MAAI,aAAa,QAAS,QAAO;AACjC,MAAI,aAAa,SAAS;AACzB,WAAO,MAAM,IAAI,QAAQ;AAAA,EAC1B;AACA,SAAO;AACR;AAMO,SAAS,kBAAsC;AACrD,QAAM,SAAS,QAAQ,IAAI;AAE3B,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AACR;;;ACzDA,eAAsB,qBAA+C;AACpE,QAAM,MAAM,0BAA0B;AAEtC,UAAQ,KAAK;AAAA,IACZ,KAAK,UAAU;AACd,YAAM,EAAE,eAAAC,eAAc,IAAI,MAAM,OAAO,sBAAa;AACpD,aAAO,IAAIA,eAAc;AAAA,IAC1B;AAAA,IACA,KAAK,OAAO;AACX,YAAM,EAAE,WAAW,IAAI,MAAM,OAAO,mBAAU;AAC9C,aAAO,IAAI,WAAW;AAAA,IACvB;AAAA,IACA,KAAK,SAAS;AAIb,YAAM,aAAa,CAAC,EAAE,QAAQ,IAAI,WAAW,QAAQ,IAAI;AAEzD,UAAI,YAAY;AACf,cAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,qBAAY;AACzD,YAAI,MAAM,oBAAoB,GAAG;AAChC,gBAAM,EAAE,aAAa,IAAI,MAAM,OAAO,qBAAY;AAClD,iBAAO,IAAI,aAAa;AAAA,QACzB;AAAA,MACD;AAGA,YAAM,EAAE,iBAAiB,YAAY,IAAI,MAAM,OAAO,oBAAW;AACjE,UAAI,MAAM,gBAAgB,GAAG;AAC5B,eAAO,IAAI,YAAY;AAAA,MACxB;AAEA,YAAM,IAAI;AAAA,QACT;AAAA,MAED;AAAA,IACD;AAAA,IACA;AACC,YAAM,IAAI;AAAA,QACT,iDAAiD,GAAG;AAAA,MAErD;AAAA,EACF;AACD;;;AFrCO,SAAS,iBAA2B;AAC1C,QAAM,MAAM,0BAA0B;AACtC,MAAI,QAAQ,MAAO,QAAO;AAC1B,SAAO;AACR;AAeA,eAAsB,iBAAqC;AAC1D,QAAM,WAAW,eAAe;AAChC,MAAI,aAAa,UAAU;AAC1B,WAAO;AAAA,EACR;AAEA,MAAI;AACH,UAAM,SAAS,MAAM,MAAM,YAAY,CAAC,QAAQ,MAAM,qBAAqB,CAAC;AAC5E,WAAO,OAAO,OAAO,KAAK,EAAE,YAAY,MAAM,SAAS,SAAS;AAAA,EACjE,QAAQ;AAEP,WAAO;AAAA,EACR;AACD;AAQA,eAAsBC,gBAAiC;AACtD,MAAI,eAAe,MAAM,SAAU,QAAO;AAC1C,SAAO,aAAmB;AAC3B;AAOA,eAAsB,mBACrB,SACgB;AAChB,QAAM,UAAU,MAAM,mBAAmB;AACzC,QAAM,QAAQ,WAAW,OAAO;AACjC;AAQA,eAAsB,4BACrB,cACgB;AAChB,MAAI,aAAa,SAAS,GAAG;AAC5B,UAAM,IAAI,MAAM,+GAA+G;AAAA,EAChI;AAEA,QAAM,UAAU,MAAM,mBAAmB;AACzC,QAAM,QAAQ,aAAa,YAAY;AACxC;AAwBO,SAAS,uBAA6B;AAC5C,MAAI,CAAC,QAAQ,MAAM,OAAO;AACzB;AAAA,EACD;AACA,MAAI;AACH,aAAS,aAAa,EAAE,OAAO,SAAS,CAAC;AAAA,EAC1C,QAAQ;AAAA,EAER;AACD;;;ADvGA,IAAM,cAAc,IAAI,MAAM,EAAE,OAAO,MAAM,MAAM,CAAC;AACpD,IAAM,cAAc,IAAI,MAAM,EAAE,OAAO,MAAM,MAAM,CAAC;AAGpD,IAAI,mBAA8B;AAMlC,eAAe,sBAAqC;AAClD,MAAI;AACF,uBAAmB,MAAM,eAAe;AAAA,EAC1C,QAAQ;AAEN,uBAAmB;AAAA,EACrB;AACF;AAGA,KAAK,oBAAoB;AAMzB,SAAS,aAAa,eAAoE;AACxF,SAAO,qBAAqB,SAAS,cAAc,OAAO,cAAc;AAC1E;AAEA,SAAS,gBAAgB,eAAoE;AAC3F,SAAO,qBAAqB,SAAS,cAAc,cAAc,cAAc;AACjF;AAEA,SAAS,aAAa,eAAoE;AACxF,SAAO,qBAAqB,SAAS,cAAc,eAAe,cAAc;AAClF;AAEA,SAAS,cAAc,eAAoE;AACzF,SAAO,qBAAqB,SAAS,cAAc,YAAY,cAAc;AAC/E;AAEA,SAAS,cAAc,eAAoE;AACzF,SAAO,qBAAqB,SAAS,cAAc,OAAO,cAAc;AAC1E;AAGA,SAAS,cAAc,YAAoB,MAAyB;AAElE,QAAM,gBAAgB,KAAK;AAAA,IAAI,SAC7B,OAAO,QAAQ,WAAW,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,OAAO,GAAG;AAAA,EACrE;AACA,SAAO,cAAc,SAAS,IAAI,GAAG,OAAO,IAAI,cAAc,KAAK,GAAG,CAAC,KAAK;AAC9E;AAEA,SAAS,gBAAgB,SAAiB,OAAe,SAA0C;AACjG,MAAI,QAAQ,KAAK,GAAG;AAClB,WAAO,QAAQ,GAAG,KAAK,IAAI,OAAO,EAAE;AAAA,EACtC,OAAO;AACL,WAAO;AAAA,EACT;AACF;AAEA,IAAI,qBAAqB;AAIlB,IAAM,SAAiB;AAAA,EAC5B,MAAM,CAAC,YAAoB,SAA0B;AACnD,UAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,UAAM,SAAS,gBAAgB,WAAW,oBAAQ,aAAa,WAAW,CAAC;AAC3E,YAAQ,IAAI,MAAM;AAAA,EACpB;AAAA,EAEA,SAAS,CAAC,YAAoB,SAA0B;AACtD,UAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,UAAM,SAAS,gBAAgB,WAAW,UAAK,gBAAgB,WAAW,CAAC;AAC3E,YAAQ,IAAI,MAAM;AAAA,EACpB;AAAA,EAEA,MAAM,CAAC,YAAoB,SAA0B;AACnD,UAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,UAAM,SAAS,gBAAgB,WAAW,iBAAO,aAAa,WAAW,CAAC;AAC1E,YAAQ,MAAM,MAAM;AAAA,EACtB;AAAA,EAEA,OAAO,CAAC,YAAoB,SAA0B;AACpD,UAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,UAAM,SAAS,gBAAgB,WAAW,UAAK,cAAc,WAAW,CAAC;AACzE,YAAQ,MAAM,MAAM;AAAA,EACtB;AAAA,EAEA,OAAO,CAAC,YAAoB,SAA0B;AACpD,QAAI,oBAAoB;AACtB,YAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,YAAM,SAAS,gBAAgB,WAAW,aAAM,cAAc,WAAW,CAAC;AAC1E,cAAQ,IAAI,MAAM;AAAA,IACpB;AAAA,EACF;AAAA,EAEA,UAAU,CAAC,YAA2B;AACpC,yBAAqB;AAAA,EACvB;AAAA,EAEA,gBAAgB,MAAe;AAC7B,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,QAAQ;AAClB;AAwFO,SAAS,mBAAmB,UAAyB,CAAC,GAAW;AACtE,QAAM,EAAE,SAAS,IAAI,YAAY,OAAO,YAAY,QAAQ,mBAAmB,IAAI;AAGnF,MAAI,oBAAoB;AAGxB,QAAM,cAAc,eAAe,SAC/B,IAAI,MAAM,EAAE,OAAO,aAAa,IAAI,EAAE,CAAC,IACvC;AAEJ,QAAM,YAAY,SAAS,IAAI,MAAM,OAAO;AAC5C,QAAM,eAAe,MAAc,YAAY,KAAI,oBAAI,KAAK,GAAE,YAAY,CAAC,OAAO;AAElF,SAAO;AAAA,IACL,MAAM,CAAC,YAAoB,SAA0B;AACnD,YAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,YAAM,cAAc,GAAG,aAAa,CAAC,GAAG,SAAS,GAAG,SAAS;AAC7D,YAAM,SAAS,gBAAgB,aAAa,oBAAQ,aAAa,WAAW,CAAC;AAC7E,cAAQ,MAAM,MAAM;AAAA,IACtB;AAAA,IACA,SAAS,CAAC,YAAoB,SAA0B;AACtD,YAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,YAAM,cAAc,GAAG,aAAa,CAAC,GAAG,SAAS,GAAG,SAAS;AAC7D,YAAM,SAAS,gBAAgB,aAAa,UAAK,gBAAgB,WAAW,CAAC;AAC7E,cAAQ,MAAM,MAAM;AAAA,IACtB;AAAA,IACA,MAAM,CAAC,YAAoB,SAA0B;AACnD,YAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,YAAM,cAAc,GAAG,aAAa,CAAC,GAAG,SAAS,GAAG,SAAS;AAC7D,YAAM,SAAS,gBAAgB,aAAa,iBAAO,aAAa,WAAW,CAAC;AAC5E,cAAQ,MAAM,MAAM;AAAA,IACtB;AAAA,IACA,OAAO,CAAC,YAAoB,SAA0B;AACpD,YAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,YAAM,cAAc,GAAG,aAAa,CAAC,GAAG,SAAS,GAAG,SAAS;AAC7D,YAAM,SAAS,gBAAgB,aAAa,UAAK,cAAc,WAAW,CAAC;AAC3E,cAAQ,MAAM,MAAM;AAAA,IACtB;AAAA,IACA,OAAO,CAAC,YAAoB,SAA0B;AACpD,UAAI,mBAAmB;AACrB,cAAM,YAAY,cAAc,SAAS,GAAG,IAAI;AAChD,cAAM,cAAc,GAAG,aAAa,CAAC,GAAG,SAAS,GAAG,SAAS;AAC7D,cAAM,SAAS,gBAAgB,aAAa,aAAM,cAAc,WAAW,CAAC;AAC5E,gBAAQ,MAAM,MAAM;AAAA,MACtB;AAAA,IACF;AAAA,IACA,UAAU,CAAC,YAA2B;AACpC,0BAAoB;AAAA,IACtB;AAAA,IACA,gBAAgB,MAAe;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,QAAQ,QAAQ;AAAA;AAAA,EAClB;AACF;AAsBA,IAAO,iBAAQ;;;ADnSR,SAAS,aAAa,SAAsC;AACjE,QAAM,SAAS,oBAAI,IAAoB;AACvC,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAEhC,aAAW,QAAQ,OAAO;AACxB,UAAM,cAAc,KAAK,KAAK;AAG9B,QAAI,CAAC,eAAe,YAAY,WAAW,GAAG,GAAG;AAC/C;AAAA,IACF;AAGA,UAAM,YAAY,YAAY,WAAW,SAAS,IAC9C,YAAY,UAAU,CAAC,IACvB;AAGJ,UAAM,cAAc,UAAU,QAAQ,GAAG;AACzC,QAAI,gBAAgB,IAAI;AACtB;AAAA,IACF;AAEA,UAAM,MAAM,UAAU,UAAU,GAAG,WAAW,EAAE,KAAK;AACrD,QAAI,QAAQ,UAAU,UAAU,cAAc,CAAC;AAG/C,QACG,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,KAC3C,MAAM,WAAW,GAAG,KAAK,MAAM,SAAS,GAAG,GAC5C;AACA,cAAQ,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC;AAE3C,cAAQ,MAAM,QAAQ,QAAQ,GAAG,EAAE,QAAQ,QAAQ,GAAG;AAEtD,cAAQ,MAAM,QAAQ,QAAQ,IAAI;AAAA,IACpC;AAEA,QAAI,KAAK;AACP,aAAO,IAAI,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,SAAO;AACT;AAMO,SAAS,cAAc,KAAa,OAAuB;AAEhE,QAAM,eAAe,MAClB,QAAQ,MAAM,KAAK,EACnB,QAAQ,OAAO,KAAK,EACpB,QAAQ,OAAO,KAAK;AAEvB,SAAO,GAAG,GAAG,KAAK,YAAY;AAChC;AAKO,SAAS,oBACd,KACA,QACoC;AACpC,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG;AAC5B,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,cAAc,GAAG,GAAG;AACvB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,sCAAsC,GAAG;AAAA,IAClD;AAAA,EACF;AAGA,SAAO,EAAE,OAAO,KAAK;AACvB;AAYO,SAAS,YAAY,YAAgD;AAC1E,QAAM,YAAY,WAAW,IAAI,MAAM;AACvC,MAAI,CAAC,WAAW;AACd,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,SAAS,WAAW,EAAE;AACnC,MAAI,MAAM,IAAI,GAAG;AACf,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,cAAc,KAAsB;AAClD,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AAGA,QAAM,gBAAgB;AACtB,SAAO,cAAc,KAAK,GAAG;AAC/B;AAOO,SAAS,mBAAmB,SAIoB;AACrD,SAAO,MAAM,kDAAkD;AAAA,IAC7D,SAAS;AAAA,MACP,OAAM,mCAAS,SAAQ;AAAA,MACvB,UAAS,mCAAS,YAAW;AAAA,MAC7B,iBAAgB,mCAAS,mBAAkB;AAAA,IAC7C;AAAA,EACF,CAAC;AAED,QAAM,gBAAkD;AAAA,IACtD,QAAQ;AAAA;AAAA,EACV;AAGA,OAAI,mCAAS,UAAS,QAAW;AAC/B,kBAAc,OAAO,QAAQ;AAC7B,WAAO,MAAM,sBAAsB,QAAQ,IAAI,EAAE;AAAA,EACnD;AACA,OAAI,mCAAS,aAAY,QAAW;AAClC,kBAAc,WAAW,QAAQ;AACjC,WAAO,MAAM,mBAAmB,QAAQ,OAAO,EAAE;AAAA,EACnD;AACA,OAAI,mCAAS,oBAAmB,QAAW;AACzC,kBAAc,mBAAmB,QAAQ;AACzC,WAAO,MAAM,2BAA2B,QAAQ,cAAc,EAAE;AAAA,EAClE,OAAO;AACL,kBAAc,mBAAmB;AACjC,WAAO,MAAM,qCAAqC;AAAA,EACpD;AAEA,SAAO,MAAM,+BAA+B,aAAa;AAEzD,QAAM,SAAS,WAAW,OAAO,aAAa;AAE9C,QAAM,cAAkE,CAAC;AAEzE,MAAI,OAAO,QAAQ;AACjB,gBAAY,SAAS,OAAO;AAC5B,UAAM,gBAAgB,OAAO,KAAK,OAAO,MAAM,EAAE;AACjD,WAAO,MAAM,uBAAuB,aAAa,wBAAwB;AAAA,EAC3E,OAAO;AACL,WAAO,MAAM,sCAAsC;AAAA,EACrD;AAEA,MAAI,OAAO,OAAO;AAChB,gBAAY,QAAQ,OAAO;AAC3B,WAAO,MAAM,iCAAiC;AAAA,MAC5C,OAAO,OAAO,MAAM;AAAA,MACpB,MAAM,OAAO,MAAM;AAAA,IACrB,CAAC;AAAA,EACH,OAAO;AACL,WAAO,MAAM,sCAAsC;AAAA,EACrD;AAEA,SAAO;AACT;AAMO,SAAS,uBAAuB,OAAuB;AAC5D,SAAO,MAAM,QAAQ,WAAW,mCAAmC;AACrE;AAMO,SAAS,iBAAiB,eAG/B;AACA,QAAM,UAAU,QAAQ,IAAI,YAAY;AAExC,SAAO,MAAM,2CAA2C;AAAA,IACtD;AAAA,IACA,iBAAiB;AAAA,IACjB,gBAAgB,QAAQ,IAAI,YAAY;AAAA,EAC1C,CAAC;AAED,SAAO,mBAAmB;AAAA,IACxB,MAAM;AAAA,IACN;AAAA,IACA,gBAAgB;AAAA,EAClB,CAAC;AACH;AAGA,IAAM,uBAAuB,QAAQ,IAAI,wBAAwB;AAM1D,SAAS,qBAA+B;AAC7C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ,oBAAoB;AAAA,IAC5B,QAAQ,oBAAoB;AAAA,EAC9B;AACF;AAQO,SAAS,mBAAmB,UAA0B;AAE3D,MAAI,SAAS,SAAS,QAAQ,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,GAAG,QAAQ;AACpB;AAcA,eAAsB,0BACpB,eACA,cACA,eACA,YACA,gBACiB;AAEjB,QAAM,OAAO,MAAM,8BAA8B,eAAe,cAAc,YAAY,cAAc;AAExG,MAAI,SAAS,MAAM;AAEjB,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,MAAM,cAAc,MAAM,aAAa;AACzD,MAAI,WAAW;AAEb,WAAO,mBAAmB,IAAI;AAAA,EAChC;AAEA,SAAO;AACT;AAMA,eAAsB,uBACpB,eACA,YACmB;AACnB,QAAM,QAAQ,mBAAmB;AACjC,QAAM,WAAqB,CAAC;AAE5B,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,KAAK,eAAe,IAAI;AAC9C,UAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,QAAI,QAAQ;AACV,eAAS,KAAK,UAAU,IAAI,EAAE;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AAOA,eAAsB,8BACpB,eACA,cACA,YACA,gBACwB;AACxB,QAAM,QAAQ,mBAAmB,EAAE,QAAQ;AAE3C,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,KAAK,eAAe,IAAI;AAG9C,QAAI,CAAE,MAAM,WAAW,QAAQ,GAAI;AACjC;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM,eAAe,UAAU,YAAY;AACzD,QAAI,UAAU,MAAM;AAClB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAOA,eAAsB,wBACpB,eACA,cACA,YACA,gBACkB;AAClB,QAAM,OAAO,MAAM,8BAA8B,eAAe,cAAc,YAAY,cAAc;AACxG,SAAO,SAAS;AAClB;;;AD3VA,eAAsB,qBAAqB,SAAiD;AAC3F,QAAM;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACD,IAAI;AAEJ,QAAM,WAAqB,CAAC;AAE5B,MAAI,eAAe;AAClB,aAAS,KAAK,OAAO,mBAAmB,aAAa,CAAC,GAAG;AAAA,EAC1D;AAEA,MAAI,mBAAmB,eAAe;AACrC,UAAM,iBAAiB,MAAM;AAAA,MAC5B;AAAA,MACA,OAAO,MAAM,WAAW,CAAC;AAAA,IAC1B;AACA,aAAS,KAAK,GAAG,cAAc;AAAA,EAChC;AAEA,MAAI,qBAAqB,SAAS,QAAW;AAC5C,aAAS,KAAK,eAAe,IAAI,EAAE;AAAA,EACpC;AAEA,MAAI,SAAS;AACZ,aAAS,KAAK,OAAO;AAAA,EACtB;AAEA,QAAM,cAAc,SAAS,KAAK,MAAM;AAGxC,SAAO,IAAI,WAAW;AACvB;AAMO,SAAS,mBAAmB,GAAmB;AACrD,SAAO,EAAE,QAAQ,MAAM,OAAO;AAC/B;AAKO,SAAS,SAAS,KAAkD;AAC1E,QAAM,QAAQ,CAAC,MAAsB,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG;AAC3G,SAAO,IAAI,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AACtD;;;ADvDO,SAAS,eAAwB;AACvC,SAAOC,YAAW,yBAAyB;AAC5C;AAKA,SAAS,qBAAqB,SAAyB;AACtD,SAAO,QACL,QAAQ,OAAO,MAAM,EACrB,QAAQ,MAAM,KAAK;AACtB;AAQA,eAAe,uBAAuB,SAAiD;AACtF,QAAM,UAAU,MAAM,qBAAqB,OAAO;AAElD,MAAI,SAAS;AAAA;AACb,YAAU,8BAA8B,qBAAqB,OAAO,CAAC;AAAA;AAErE,MAAI,QAAQ,iBAAiB;AAC5B,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,QAAQ;AAC5B,cAAU,wCAAwC,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC;AAAA;AAAA,EACtH;AAEA,YAAU;AACV,SAAO;AACR;AAKA,eAAe,2BAA2B,SAAiD;AAC1F,QAAM,UAAU,MAAM,qBAAqB,OAAO;AAElD,MAAI,SAAS;AACb,YAAU;AACV,YAAU;AAEV,MAAI,QAAQ,iBAAiB;AAC5B,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,QAAQ;AAC5B,cAAU,oCAAoC,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC;AAAA;AAAA,EAClH;AAEA,YAAU,4BAA4B,qBAAqB,OAAO,CAAC;AAAA;AAAA;AAEnE,MAAI,QAAQ,OAAO;AAClB,cAAU,wBAAwB,qBAAqB,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA,EACtE;AAEA,YAAU;AACV,YAAU;AACV,SAAO;AACR;AAKA,eAAe,0BACd,cACkB;AAClB,MAAI,aAAa,SAAS,GAAG;AAC5B,UAAM,IAAI,MAAM,gEAAgE;AAAA,EACjF;AAEA,MAAI,SAAS;AACb,YAAU;AACV,YAAU;AAEV,QAAM,WAAW,aAAa,CAAC;AAC/B,MAAI,CAAC,UAAU;AACd,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACrD;AACA,QAAM,WAAW,MAAM,qBAAqB,QAAQ;AAEpD,YAAU;AAEV,MAAI,SAAS,iBAAiB;AAC7B,UAAM,EAAE,GAAG,GAAG,EAAE,IAAI,SAAS;AAC7B,cAAU,oCAAoC,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC;AAAA;AAAA,EAClH;AAEA,YAAU,4BAA4B,qBAAqB,QAAQ,CAAC;AAAA;AAAA;AAEpE,MAAI,SAAS,OAAO;AACnB,cAAU,wBAAwB,qBAAqB,SAAS,KAAK,CAAC;AAAA;AAAA;AAAA,EACvE;AAEA,WAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,UAAM,UAAU,aAAa,CAAC;AAC9B,QAAI,CAAC,SAAS;AACb,YAAM,IAAI,MAAM,4BAA4B,CAAC,eAAe;AAAA,IAC7D;AACA,UAAM,UAAU,MAAM,qBAAqB,OAAO;AAClD,UAAM,aAAa,IAAI,IAAI,CAAC;AAE5B,cAAU;AACV,cAAU,iBAAiB,CAAC;AAAA;AAC5B,cAAU;AACV,cAAU,SAAS,UAAU,gCAAgC,CAAC;AAAA;AAAA;AAE9D,QAAI,QAAQ,iBAAiB;AAC5B,YAAM,EAAE,GAAG,GAAG,EAAE,IAAI,QAAQ;AAC5B,gBAAU,6BAA6B,UAAU,QAAQ,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,GAAG,CAAC;AAAA;AAAA,IAC7H;AAEA,cAAU,UAAU,UAAU,mBAAmB,qBAAqB,OAAO,CAAC;AAAA;AAAA;AAE9E,QAAI,QAAQ,OAAO;AAClB,gBAAU,iBAAiB,UAAU,QAAQ,qBAAqB,QAAQ,KAAK,CAAC;AAAA;AAAA;AAAA,IACjF;AAAA,EACD;AAEA,YAAU;AACV,YAAU;AACV,SAAO;AACR;AAKO,IAAM,gBAAN,MAA+C;AAAA,EAA/C;AACN,SAAS,OAAO;AAAA;AAAA,EAEhB,MAAM,WAAW,SAA+C;AAC/D,UAAM,YAAY,aAAa;AAE/B,UAAM,cAAc,YACjB,MAAM,2BAA2B,OAAO,IACxC,MAAM,uBAAuB,OAAO;AAEvC,QAAI;AACH,YAAMC,OAAM,aAAa,CAAC,MAAM,WAAW,CAAC;AAE5C,UAAI,CAAC,WAAW;AACf,cAAMA,OAAM,aAAa,CAAC,MAAM,yCAAyC,CAAC;AAAA,MAC3E;AAAA,IACD,SAAS,OAAO;AACf,YAAM,IAAI;AAAA,QACT,mCAAmC,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MAC5F;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM,aAAa,cAAsD;AACxE,UAAM,YAAY,aAAa;AAE/B,QAAI,WAAW;AACd,YAAM,cAAc,MAAM,0BAA0B,YAAY;AAEhE,UAAI;AACH,cAAMA,OAAM,aAAa,CAAC,MAAM,WAAW,CAAC;AAAA,MAC7C,SAAS,OAAO;AACf,cAAM,IAAI;AAAA,UACT,iCAAiC,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,QAC1F;AAAA,MACD;AAAA,IACD,OAAO;AACN,eAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC7C,cAAM,UAAU,aAAa,CAAC;AAC9B,YAAI,CAAC,SAAS;AACb,gBAAM,IAAI,MAAM,4BAA4B,CAAC,eAAe;AAAA,QAC7D;AACA,cAAM,KAAK,WAAW,OAAO;AAE7B,YAAI,IAAI,aAAa,SAAS,GAAG;AAChC,gBAAM,IAAI,QAAc,CAAC,YAAY,WAAW,WAAW,SAAS,GAAI,CAAC;AAAA,QAC1E;AAAA,MACD;AAAA,IACD;AAAA,EACD;AACD;","names":["execa","existsSync","DarwinBackend","detectITerm2","existsSync","execa"]}
|
|
@@ -2,27 +2,27 @@
|
|
|
2
2
|
import {
|
|
3
3
|
detectPackageManager,
|
|
4
4
|
runScript
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-VIQOQ463.js";
|
|
6
6
|
import {
|
|
7
7
|
getPackageConfig,
|
|
8
8
|
hasScript
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-K3QGG4O2.js";
|
|
10
10
|
import {
|
|
11
11
|
promptCommitAction
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-NPVA65KS.js";
|
|
13
13
|
import {
|
|
14
14
|
detectClaudeCli,
|
|
15
15
|
launchClaude
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-DDHWZNGL.js";
|
|
17
17
|
import {
|
|
18
18
|
executeGitCommand
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-OPQC4OWM.js";
|
|
20
20
|
import {
|
|
21
21
|
getLogger
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-FTYWGQFM.js";
|
|
23
23
|
import {
|
|
24
24
|
logger
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-VRPPI6GU.js";
|
|
26
26
|
|
|
27
27
|
// src/lib/ValidationRunner.ts
|
|
28
28
|
var ValidationRunner = class {
|
|
@@ -828,4 +828,4 @@ export {
|
|
|
828
828
|
UserAbortedCommitError,
|
|
829
829
|
CommitManager
|
|
830
830
|
};
|
|
831
|
-
//# sourceMappingURL=chunk-
|
|
831
|
+
//# sourceMappingURL=chunk-XVCGPTEQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/ValidationRunner.ts","../src/types/index.ts","../src/utils/vscode.ts","../src/lib/CommitManager.ts"],"sourcesContent":["import { getLogger } from '../utils/logger-context.js'\nimport { detectPackageManager, runScript } from '../utils/package-manager.js'\nimport { getPackageConfig, hasScript } from '../utils/package-json.js'\nimport { detectClaudeCli, launchClaude } from '../utils/claude.js'\nimport type {\n\tValidationOptions,\n\tValidationResult,\n\tValidationStepResult,\n} from '../types/index.js'\n\n/**\n * ValidationRunner orchestrates pre-merge validation pipeline\n * Runs typecheck, lint, and tests in sequence with fail-fast behavior\n */\nexport class ValidationRunner {\n\tconstructor() {\n\t\t// Uses getLogger() for all logging operations\n\t}\n\n\t/**\n\t * Run all validations in sequence: typecheck → lint → test\n\t * Fails fast on first error\n\t */\n\tasync runValidations(\n\t\tworktreePath: string,\n\t\toptions: ValidationOptions = {}\n\t): Promise<ValidationResult> {\n\t\tconst startTime = Date.now()\n\t\tconst steps: ValidationStepResult[] = []\n\n\t\tconst { jsonStream } = options\n\n\t\t// Run typecheck\n\t\tif (!options.skipTypecheck) {\n\t\t\tconst typecheckResult = await this.runTypecheck(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false,\n\t\t\t\t{ jsonStream }\n\t\t\t)\n\t\t\tsteps.push(typecheckResult)\n\n\t\t\tif (!typecheckResult.passed && !typecheckResult.skipped) {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: false,\n\t\t\t\t\tsteps,\n\t\t\t\t\ttotalDuration: Date.now() - startTime,\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Run lint\n\t\tif (!options.skipLint) {\n\t\t\tconst lintResult = await this.runLint(worktreePath, options.dryRun ?? false, { jsonStream })\n\t\t\tsteps.push(lintResult)\n\n\t\t\tif (!lintResult.passed && !lintResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\t// Run tests\n\t\tif (!options.skipTests) {\n\t\t\tconst testResult = await this.runTests(\n\t\t\t\tworktreePath,\n\t\t\t\toptions.dryRun ?? false,\n\t\t\t\t{ jsonStream }\n\t\t\t)\n\t\t\tsteps.push(testResult)\n\n\t\t\tif (!testResult.passed && !testResult.skipped) {\n\t\t\t\treturn { success: false, steps, totalDuration: Date.now() - startTime }\n\t\t\t}\n\t\t}\n\n\t\treturn { success: true, steps, totalDuration: Date.now() - startTime }\n\t}\n\n\t/**\n\t * Run typecheck validation\n\t * Prefers 'compile' script over 'typecheck' if both exist\n\t */\n\tprivate async runTypecheck(\n\t\tworktreePath: string,\n\t\tdryRun: boolean,\n\t\toptions: { jsonStream?: boolean | undefined } = {}\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\tlet scriptToRun: 'compile' | 'typecheck' | null = null\n\n\t\ttry {\n\t\t\t// Check for compile and typecheck scripts - prefer compile if both exist\n\t\t\tconst pkgJson = await getPackageConfig(worktreePath)\n\t\t\tconst hasCompileScript = hasScript(pkgJson, 'compile')\n\t\t\tconst hasTypecheckScript = hasScript(pkgJson, 'typecheck')\n\n\t\t\tif (hasCompileScript) {\n\t\t\t\tscriptToRun = 'compile'\n\t\t\t} else if (hasTypecheckScript) {\n\t\t\t\tscriptToRun = 'typecheck'\n\t\t\t}\n\n\t\t\tif (!scriptToRun) {\n\t\t\t\tgetLogger().debug('Skipping typecheck - no compile or typecheck script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping typecheck - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'typecheck',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? `npm run ${scriptToRun}`\n\t\t\t\t\t: `${packageManager} ${scriptToRun}`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: scriptToRun,\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info(`Running ${scriptToRun}...`)\n\n\t\ttry {\n\t\t\tawait runScript(scriptToRun, worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success(`${scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1)} passed`)\n\n\t\t\treturn {\n\t\t\t\tstep: scriptToRun,\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\tscriptToRun,\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager,\n\t\t\t\t{ jsonStream: options.jsonStream }\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\treturn {\n\t\t\t\t\tstep: scriptToRun,\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm'\n\t\t\t\t\t? `npm run ${scriptToRun}`\n\t\t\t\t\t: `${packageManager} ${scriptToRun}`\n\n\t\t\tconst stepLabel = scriptToRun.charAt(0).toUpperCase() + scriptToRun.slice(1)\n\t\t\tthrow new Error(\n\t\t\t\t`Error: ${stepLabel} failed.\\n` +\n\t\t\t\t\t`Fix type errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run lint validation\n\t */\n\tprivate async runLint(\n\t\tworktreePath: string,\n\t\tdryRun: boolean,\n\t\toptions: { jsonStream?: boolean | undefined } = {}\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if lint script exists\n\t\t\tconst pkgJson = await getPackageConfig(worktreePath)\n\t\t\tconst hasLintScript = hasScript(pkgJson, 'lint')\n\n\t\t\tif (!hasLintScript) {\n\t\t\t\tgetLogger().debug('Skipping lint - no lint script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping lint - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info('Running lint...')\n\n\t\ttry {\n\t\t\tawait runScript('lint', worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success('Linting passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'lint',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'lint',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager,\n\t\t\t\t{ jsonStream: options.jsonStream }\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Linting passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'lint',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run lint' : `${packageManager} lint`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Linting failed.\\n` +\n\t\t\t\t\t`Fix linting errors before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Run test validation\n\t */\n\tprivate async runTests(\n\t\tworktreePath: string,\n\t\tdryRun: boolean,\n\t\toptions: { jsonStream?: boolean | undefined } = {}\n\t): Promise<ValidationStepResult> {\n\t\tconst stepStartTime = Date.now()\n\n\t\ttry {\n\t\t\t// Check if test script exists\n\t\t\tconst pkgJson = await getPackageConfig(worktreePath)\n\t\t\tconst hasTestScript = hasScript(pkgJson, 'test')\n\n\t\t\tif (!hasTestScript) {\n\t\t\t\tgetLogger().debug('Skipping tests - no test script found')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Handle missing package.json - skip validation for non-Node.js projects\n\t\t\tif (error instanceof Error && error.message.includes('package.json not found')) {\n\t\t\t\tgetLogger().debug('Skipping tests - no package.json found (non-Node.js project)')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Re-throw other errors\n\t\t\tthrow error\n\t\t}\n\n\t\tconst packageManager = await detectPackageManager(worktreePath)\n\n\t\tif (dryRun) {\n\t\t\tconst command =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\t\t\tgetLogger().info(`[DRY RUN] Would run: ${command}`)\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t}\n\n\t\tgetLogger().info('Running tests...')\n\n\t\ttry {\n\t\t\tawait runScript('test', worktreePath, [], { quiet: true })\n\t\t\tgetLogger().success('Tests passed')\n\n\t\t\treturn {\n\t\t\t\tstep: 'test',\n\t\t\t\tpassed: true,\n\t\t\t\tskipped: false,\n\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t}\n\t\t} catch {\n\t\t\t// Attempt Claude-assisted fix before failing\n\t\t\tconst fixed = await this.attemptClaudeFix(\n\t\t\t\t'test',\n\t\t\t\tworktreePath,\n\t\t\t\tpackageManager,\n\t\t\t\t{ jsonStream: options.jsonStream }\n\t\t\t)\n\n\t\t\tif (fixed) {\n\t\t\t\t// logger.success('Tests passed after Claude auto-fix')\n\t\t\t\treturn {\n\t\t\t\t\tstep: 'test',\n\t\t\t\t\tpassed: true,\n\t\t\t\t\tskipped: false,\n\t\t\t\t\tduration: Date.now() - stepStartTime,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Claude couldn't fix - throw original error\n\t\t\tconst runCommand =\n\t\t\t\tpackageManager === 'npm' ? 'npm run test' : `${packageManager} test`\n\n\t\t\tthrow new Error(\n\t\t\t\t`Error: Tests failed.\\n` +\n\t\t\t\t\t`Fix test failures before merging.\\n\\n` +\n\t\t\t\t\t`Run '${runCommand}' to see detailed errors.`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Attempt to fix validation errors using Claude\n\t * Pattern based on MergeManager.attemptClaudeConflictResolution\n\t *\n\t * @param validationType - Type of validation that failed ('compile' | 'typecheck' | 'lint' | 'test')\n\t * @param worktreePath - Path to the worktree\n\t * @param packageManager - Detected package manager\n\t * @returns true if Claude fixed the issue, false otherwise\n\t */\n\tprivate async attemptClaudeFix(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\tworktreePath: string,\n\t\tpackageManager: string,\n\t\toptions: { jsonStream?: boolean | undefined } = {}\n\t): Promise<boolean> {\n\t\t// Check if Claude CLI is available\n\t\tconst isClaudeAvailable = await detectClaudeCli()\n\t\tif (!isClaudeAvailable) {\n\t\t\tgetLogger().debug('Claude CLI not available, skipping auto-fix')\n\t\t\treturn false\n\t\t}\n\n\t\t// Build validation command for the prompt\n\t\tconst validationCommand = this.getValidationCommand(validationType, packageManager)\n\n\t\t// Build prompt based on validation type (matching bash script prompts)\n\t\tconst prompt = this.getClaudePrompt(validationType, validationCommand)\n\n\t\tconst validationTypeCapitalized = validationType.charAt(0).toUpperCase() + validationType.slice(1)\n\t\tgetLogger().info(`Launching Claude to help fix ${validationTypeCapitalized} errors...`)\n\n\t\ttry {\n\t\t\t// When jsonStream is true, run Claude headless with stdout passthrough for JSONL streaming\n\t\t\t// Otherwise, launch interactively in the current terminal\n\t\t\tawait launchClaude(prompt, {\n\t\t\t\taddDir: worktreePath,\n\t\t\t\theadless: !!options.jsonStream,\n\t\t\t\tpermissionMode: options.jsonStream ? 'bypassPermissions' : 'acceptEdits',\n\t\t\t\tmodel: 'sonnet',\n\t\t\t\tnoSessionPersistence: true,\n\t\t\t\t...(options.jsonStream && { passthroughStdout: true }),\n\t\t\t})\n\n\t\t\t// After Claude completes, re-run validation to verify fix\n\t\t\tgetLogger().info(`Re-running ${validationTypeCapitalized} after Claude's fixes...`)\n\n\t\t\ttry {\n\t\t\t\tawait runScript(validationType, worktreePath, [], { quiet: true })\n\t\t\t\t// Validation passed after Claude fix\n\t\t\t\tgetLogger().success(`${validationTypeCapitalized} passed after Claude auto-fix`)\n\t\t\t\treturn true\n\t\t\t} catch {\n\t\t\t\t// Validation still failing after Claude's attempt\n\t\t\t\tgetLogger().warn(`${validationTypeCapitalized} still failing after Claude's help`)\n\t\t\t\treturn false\n\t\t\t}\n\t\t} catch (error) {\n\t\t\t// Claude launch failed or crashed\n\t\t\tgetLogger().warn('Claude auto-fix failed', {\n\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t})\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Get validation command string for prompts\n\t * Uses il commands for multi-language project support\n\t */\n\tprivate getValidationCommand(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\t_packageManager: string\n\t): string {\n\t\t// Use il commands for consistent multi-language project support\n\t\treturn `il ${validationType}`\n\t}\n\n\t/**\n\t * Get Claude prompt for specific validation type\n\t * Matches bash script prompts exactly\n\t */\n\tprivate getClaudePrompt(\n\t\tvalidationType: 'compile' | 'typecheck' | 'lint' | 'test',\n\t\tvalidationCommand: string\n\t): string {\n\t\tswitch (validationType) {\n\t\t\tcase 'compile':\n\t\t\tcase 'typecheck':\n\t\t\t\treturn (\n\t\t\t\t\t`There are compilation errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the ${validationType} output, identify all type errors, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all type issues. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'lint':\n\t\t\t\treturn (\n\t\t\t\t\t`There are Lint errors in this codebase. ` +\n\t\t\t\t\t`Please analyze the linting output, identify all linting issues, and fix them. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the errors, then make the necessary code changes to resolve all linting issues. ` +\n\t\t\t\t\t`Focus on code quality, consistency, and following the project's linting rules. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t\tcase 'test':\n\t\t\t\treturn (\n\t\t\t\t\t`There are unit test failures in this codebase. ` +\n\t\t\t\t\t`Please analyze the test output to understand what's failing, then fix the issues. ` +\n\t\t\t\t\t`This might involve updating test code, fixing bugs in the source code, or updating tests to match new behavior. ` +\n\t\t\t\t\t`Run '${validationCommand}' to see the detailed test failures, then make the necessary changes to get all tests passing. ` +\n\t\t\t\t\t`When you are done, tell the user to quit using /exit to continue the validation process.`\n\t\t\t\t)\n\t\t}\n\t}\n}\n","// Core types\nexport interface Workspace {\n id: string\n path: string\n branch: string\n issueNumber?: string | number\n prNumber?: number\n port: number\n databaseBranch?: string\n createdAt: Date\n lastAccessed: Date\n}\n\nexport interface WorkspaceInput {\n identifier: string\n type: 'issue' | 'pr' | 'branch'\n skipClaude?: boolean\n}\n\nexport interface WorkspaceSummary {\n id: string\n issueNumber?: string | number\n prNumber?: number\n title: string\n branch: string\n port: number\n status: 'active' | 'stale' | 'error'\n lastAccessed: string\n}\n\n// Git types\nexport interface Worktree {\n path: string\n branch: string\n commit: string\n isPR: boolean\n prNumber?: number\n issueNumber?: string | number\n port?: number\n}\n\nexport interface GitStatus {\n hasUncommittedChanges: boolean\n unstagedFiles: string[]\n stagedFiles: string[]\n currentBranch: string\n isAheadOfRemote: boolean\n isBehindRemote: boolean\n}\n\n// GitHub types\nexport interface Issue {\n number: string | number\n title: string\n body: string\n state: 'open' | 'closed'\n labels: string[]\n assignees: string[]\n url: string\n}\n\nexport interface PullRequest {\n number: number\n title: string\n body: string\n state: 'open' | 'closed' | 'merged'\n branch: string\n baseBranch: string\n url: string\n isDraft: boolean\n isFork?: boolean\n}\n\n// Issue Tracker types\n/**\n * Generic input detection result for issue trackers\n * String-based identifier to support non-numeric IDs (e.g., Linear \"ENG-123\")\n */\nexport interface IssueTrackerInputDetection {\n\ttype: 'issue' | 'pr' | 'unknown'\n\tidentifier: string | null\n\trawInput: string\n}\n\n/**\n * Re-export branch naming types from branch-naming module\n * These types are provider-agnostic and support all issue trackers\n */\nexport type { BranchNameStrategy, BranchGenerationOptions } from './branch-naming.js'\n\n// Database types\n\n/**\n * Result of database branch deletion operation\n * Distinguishes between successful deletion, branch not found, and errors\n */\nexport interface DatabaseDeletionResult {\n /** Overall operation succeeded (true even if branch didn't exist) */\n success: boolean\n /** True only if a branch was actually deleted */\n deleted: boolean\n /** True if branch didn't exist (not an error, just nothing to do) */\n notFound: boolean\n /** Error message if operation failed */\n error?: string\n /** User declined deletion (for preview databases) */\n userDeclined?: boolean\n /** Name of the branch that was processed */\n branchName?: string\n}\n\nexport interface DatabaseProvider {\n // Core operations\n createBranch(name: string, fromBranch?: string, cwd?: string): Promise<string>\n deleteBranch(name: string, isPreview?: boolean, cwd?: string): Promise<DatabaseDeletionResult>\n getConnectionString(branch: string, cwd?: string): Promise<string>\n listBranches(cwd?: string): Promise<string[]>\n branchExists(name: string, cwd?: string): Promise<boolean>\n\n // Additional operations for Vercel integration and validation\n findPreviewBranch(branchName: string, cwd?: string): Promise<string | null>\n getBranchNameFromEndpoint(endpointId: string, cwd?: string): Promise<string | null>\n sanitizeBranchName(branchName: string): string\n isAuthenticated(cwd?: string): Promise<boolean>\n isCliAvailable(): Promise<boolean>\n\n // Configuration validation\n isConfigured(): boolean\n}\n\n// Configuration types\nexport interface Config {\n defaultPort: number\n databaseProvider?: 'neon' | 'supabase' | 'planetscale'\n claudeModel?: 'opus' | 'sonnet' | 'haiku'\n skipClaude?: boolean\n customWorkspaceRoot?: string\n}\n\n// One-shot automation mode type\nexport type OneShotMode = 'default' | 'noReview' | 'bypassPermissions'\n\n// Complexity override type\nexport type ComplexityOverride = 'trivial' | 'simple' | 'complex'\n\n// Command option types\nexport interface StartOptions {\n // Individual component flags (can be combined)\n claude?: boolean\n code?: boolean\n devServer?: boolean\n terminal?: boolean\n // Child loom control flag\n childLoom?: boolean\n // Epic loom control flag (for issues with child issues)\n epic?: boolean\n // Create-only mode: skip Claude, IDE, terminal, dev server, and epic\n createOnly?: boolean\n // One-shot automation mode\n oneShot?: OneShotMode\n // Complexity override (skips complexity evaluation)\n complexity?: ComplexityOverride\n // Optional body text for issue creation\n body?: string\n // Output result as JSON\n json?: boolean\n}\n\nexport interface AddIssueOptions {\n // Optional body text for issue (skips AI enhancement)\n body?: string\n // Output result as JSON\n json?: boolean\n}\n\nexport interface FeedbackOptions {\n // Optional body text for feedback (added after diagnostics)\n body?: string\n}\n\nexport interface EnhanceOptions {\n noBrowser?: boolean // --no-browser flag - skip browser opening prompt\n json?: boolean // --json flag - output result as JSON\n}\n\nexport interface FinishOptions {\n force?: boolean // -f, --force - Skip confirmation prompts\n dryRun?: boolean // -n, --dry-run - Preview actions without executing\n pr?: number // --pr <number> - Treat input as PR number\n skipBuild?: boolean // --skip-build - Skip post-merge build verification\n noBrowser?: boolean // --no-browser - Skip opening PR in browser (pr mode only)\n cleanup?: boolean // --cleanup / --no-cleanup - Control worktree cleanup after finishing\n json?: boolean // --json - Output result as JSON\n skipToPr?: boolean // --skip-to-pr - Skip rebase/validation/commit, go directly to PR creation (debug)\n jsonStream?: boolean // --json-stream - Stream JSONL output for Claude conflict resolution\n review?: boolean // --review - Review commit message before committing (default: auto-commit without review)\n}\n\n/**\n * Options for the cleanup command\n * All flags are optional and can be combined (subject to validation)\n */\nexport interface CleanupOptions {\n /** List all worktrees without removing anything */\n list?: boolean\n /** Remove all worktrees (interactive confirmation required unless --force) */\n all?: boolean\n /** Cleanup by specific issue number */\n issue?: number\n /** Skip confirmations and force removal */\n force?: boolean\n /** Show what would be done without actually doing it */\n dryRun?: boolean\n /** Output result as JSON */\n json?: boolean\n /** Wait specified milliseconds before cleanup execution */\n defer?: number\n /** Archive metadata instead of deleting (preserves loom in il list --finished) */\n archive?: boolean\n}\n\nexport interface ListOptions {\n json?: boolean\n}\n\n// JSON output result types for add-issue and enhance commands\nexport interface AddIssueResult {\n url: string\n id: number\n title: string\n created_at: string\n}\n\nexport interface EnhanceResult {\n url: string\n id: number\n title: string\n created_at: string\n enhanced: boolean\n}\n\nexport interface StartResult {\n id: string\n path: string\n branch: string\n port?: number\n type: 'issue' | 'pr' | 'branch' | 'epic'\n identifier: string | number\n title?: string\n capabilities?: string[]\n childIssueNumbers?: string[]\n}\n\nexport interface FinishResult {\n success: boolean\n type: 'issue' | 'pr' | 'branch' | 'epic'\n identifier: string | number\n /** Whether this was a dry-run operation */\n dryRun?: boolean\n operations: Array<{\n type: 'validation' | 'commit' | 'rebase' | 'merge' | 'cleanup' | 'pr-creation' | 'pr-ready' | 'build'\n message: string\n success: boolean\n error?: string\n }>\n prUrl?: string\n cleanupResult?: import('./cleanup.js').CleanupResult\n}\n\nexport interface SummaryResult {\n summary: string\n sessionId: string\n issueNumber?: string | number\n branchName: string\n loomType: 'issue' | 'pr' | 'branch' | 'epic'\n}\n\nexport interface RebaseResult {\n success: boolean\n conflictsDetected: boolean\n claudeLaunched: boolean\n conflictsResolved?: boolean\n error?: string\n}\n\nexport interface RebaseOutcome {\n conflictsDetected: boolean\n claudeLaunched: boolean\n conflictsResolved: boolean\n}\n\n// Deprecated: Result types - use exception-based error handling instead\n// export type Result<T, E = Error> = { success: true; data: T } | { success: false; error: E }\n\n// Mock factory types for testing\nexport interface MockOptions {\n scenario: 'empty' | 'existing' | 'conflicts' | 'error'\n data?: unknown\n}\n\n// Worktree management types\nexport * from './worktree.js'\n\n// Environment management types\nexport * from './environment.js'\n\n// Loom types\nexport * from './loom.js'\n\n// Cleanup types\nexport * from './cleanup.js'\n\n// Process types (excluding Platform which is already defined above)\nexport type { ProcessInfo } from './process.js'\n\n// Color synchronization types\nexport interface RgbColor {\n\tr: number\n\tg: number\n\tb: number\n}\n\nexport interface ColorData {\n\trgb: RgbColor\n\thex: string\n\tindex: number\n}\n\nexport type Platform = 'darwin' | 'linux' | 'win32' | 'unsupported'\n\n// Validation types\nexport interface ValidationOptions {\n\tdryRun?: boolean\n\tskipTypecheck?: boolean\n\tskipLint?: boolean\n\tskipTests?: boolean\n\tjsonStream?: boolean\n}\n\nexport interface ValidationStepResult {\n\tstep: 'typecheck' | 'compile' | 'lint' | 'test'\n\tpassed: boolean\n\tskipped: boolean\n\toutput?: string\n\terror?: string\n\tduration?: number\n}\n\nexport interface ValidationResult {\n\tsuccess: boolean\n\tsteps: ValidationStepResult[]\n\ttotalDuration: number\n}\n\n// Commit management types\nexport interface CommitOptions {\n\tdryRun?: boolean\n\tissueNumber?: string | number // For \"Fixes #N\" or \"Refs #N\" trailer\n\tissuePrefix: string // \"#\" for GitHub, \"\" for Linear\n\tmessage?: string // Custom message override\n\tnoReview?: boolean // Skip user review of commit message\n\tskipVerify?: boolean // Skip pre-commit hooks (--no-verify flag)\n\tskipVerifySilent?: boolean // Skip without warning (for --wip-commit)\n\ttrailerType?: 'Refs' | 'Fixes' // Trailer type: \"Refs\" references issue, \"Fixes\" closes it (default: 'Fixes' for backward compat)\n\ttimeout?: number // Timeout in milliseconds for commit operation\n}\n\n/**\n * Error thrown when user aborts a commit operation\n * Used by CommitManager when user selects 'abort' at the commit prompt\n */\nexport class UserAbortedCommitError extends Error {\n\tconstructor(message = 'User aborted the commit') {\n\t\tsuper(message)\n\t\tthis.name = 'UserAbortedCommitError'\n\t}\n}\n\n// Merge management types\nexport interface MergeOptions {\n\tdryRun?: boolean // Preview actions without executing\n\tforce?: boolean // Skip confirmation prompts\n\trepoRoot?: string // Repository root path (optional, auto-detected if not provided)\n\tjsonStream?: boolean // When true, run Claude headless and stream JSONL for conflict resolution\n}\n\nexport interface MergeResult {\n\tsuccess: boolean\n\tbranchName: string\n\tcommitsMerged: number\n\trebaseCompleted: boolean\n\tmergeCompleted: boolean\n}\n\n// Update notification types\nexport interface UpdateCheckCache {\n\tlastCheck: number // Unix timestamp\n\tlatestVersion: string\n}\n\nexport interface UpdateCheckResult {\n\tcurrentVersion: string\n\tlatestVersion: string\n\tupdateAvailable: boolean\n}\n\nexport type InstallationMethod = 'global' | 'local' | 'linked' | 'unknown'\n\n// Telemetry types\nexport * from './telemetry.js'\n","import { execa } from 'execa'\nimport { logger } from './logger.js'\n\n/**\n * Check if running inside VSCode's integrated terminal\n * VSCode sets TERM_PROGRAM=vscode in its integrated terminal\n */\nexport function isRunningInVSCode(): boolean {\n\treturn process.env.TERM_PROGRAM === 'vscode'\n}\n\n/**\n * Check if running inside Cursor's integrated terminal\n * Cursor sets CURSOR_TRACE_ID environment variable in its terminal\n * Note: Cursor may also set TERM_PROGRAM=vscode, so this check should be done first\n */\nexport function isRunningInCursor(): boolean {\n\treturn !!process.env.CURSOR_TRACE_ID\n}\n\n/**\n * Check if running inside Antigravity's integrated terminal\n * Antigravity sets ANTIGRAVITY_CLI_ALIAS environment variable\n * Note: This check should be done FIRST before Cursor and VSCode\n */\nexport function isRunningInAntigravity(): boolean {\n\treturn !!process.env.ANTIGRAVITY_CLI_ALIAS\n}\n\n/**\n * Check if VSCode command-line tool is available\n */\nexport async function isVSCodeAvailable(): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', 'code'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\tlogger.debug('VSCode CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Check if Cursor command-line tool is available\n */\nexport async function isCursorAvailable(): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', 'cursor'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\tlogger.debug('Cursor CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Check if Antigravity command-line tool is available\n */\nexport async function isAntigravityAvailable(): Promise<boolean> {\n\ttry {\n\t\tawait execa('command', ['-v', 'agy'], {\n\t\t\tshell: true,\n\t\t\ttimeout: 5000,\n\t\t})\n\t\treturn true\n\t} catch (error) {\n\t\tlogger.debug('Antigravity CLI not available', { error })\n\t\treturn false\n\t}\n}\n\n/**\n * Open VSCode window for workspace\n * Throws error if VSCode not available\n */\nexport async function openVSCodeWindow(workspacePath: string): Promise<void> {\n\t// Check availability first\n\tconst available = await isVSCodeAvailable()\n\tif (!available) {\n\t\tthrow new Error(\n\t\t\t'VSCode is not available. Please install VSCode and ensure the \"code\" command is in your PATH.\\n' +\n\t\t\t\t'Install command-line tools: Open VSCode > Command Palette > \"Shell Command: Install \\'code\\' command in PATH\"'\n\t\t)\n\t}\n\n\ttry {\n\t\t// Launch VSCode with workspace path\n\t\tawait execa('code', [workspacePath])\n\t\tlogger.debug(`Opened VSCode for workspace: ${workspacePath}`)\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open VSCode: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n","import { executeGitCommand } from '../utils/git.js'\nimport { getLogger } from '../utils/logger-context.js'\nimport { launchClaude, detectClaudeCli } from '../utils/claude.js'\nimport { promptCommitAction } from '../utils/prompt.js'\nimport { isRunningInVSCode, isVSCodeAvailable, isRunningInCursor, isCursorAvailable, isRunningInAntigravity, isAntigravityAvailable } from '../utils/vscode.js'\nimport { UserAbortedCommitError } from '../types/index.js'\nimport type { GitStatus, CommitOptions } from '../types/index.js'\nimport { writeFile, readFile, unlink } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport { execa } from 'execa'\n\n/**\n * CommitManager handles uncommitted changes detection and auto-commit\n * Ports logic from bash/merge-and-clean.sh lines 610-643\n */\nexport class CommitManager {\n constructor() {\n // Uses getLogger() for all logging operations\n }\n\n /**\n * Detect uncommitted changes in a worktree\n * Parses git status --porcelain output into structured GitStatus\n */\n async detectUncommittedChanges(worktreePath: string): Promise<GitStatus> {\n // Execute: git status --porcelain\n const porcelainOutput = await executeGitCommand(['status', '--porcelain'], {\n cwd: worktreePath,\n })\n\n // Parse output to get staged and unstaged files\n const { stagedFiles, unstagedFiles } = this.parseGitStatus(porcelainOutput)\n\n // Get current branch name\n const currentBranch = await executeGitCommand(['branch', '--show-current'], {\n cwd: worktreePath,\n })\n\n return {\n hasUncommittedChanges: stagedFiles.length > 0 || unstagedFiles.length > 0,\n unstagedFiles,\n stagedFiles,\n currentBranch: currentBranch.trim(),\n // Defer these to future enhancement\n isAheadOfRemote: false,\n isBehindRemote: false,\n }\n }\n\n\n /**\n * Stage all changes and commit with Claude-generated or simple message\n * Tries Claude first, falls back to simple message if Claude unavailable or fails\n * Returns the commit message that was used\n */\n async commitChanges(worktreePath: string, options: CommitOptions): Promise<{ message: string }> {\n // Step 1: Check dry-run mode\n if (options.dryRun) {\n getLogger().info('[DRY RUN] Would run: git add -A')\n getLogger().info('[DRY RUN] Would generate commit message with Claude (if available)')\n const fallbackMessage = this.generateFallbackMessage(options)\n const verifyFlag = options.skipVerify ? ' --no-verify' : ''\n getLogger().info(`[DRY RUN] Would commit with message${verifyFlag}: ${fallbackMessage}`)\n return { message: fallbackMessage }\n }\n\n // Step 2: Stage all changes\n await executeGitCommand(['add', '-A'], { cwd: worktreePath })\n\n // Step 3: Generate commit message (try Claude first, fallback to simple)\n let message: string | null = null\n\n // Skip Claude if custom message provided\n if (!options.message) {\n try {\n message = await this.generateClaudeCommitMessage(worktreePath, options.issueNumber, options.issuePrefix, options.trailerType)\n } catch (error) {\n getLogger().debug('Claude commit message generation failed, using fallback', { error })\n }\n }\n\n // Fallback to simple message if Claude failed or unavailable\n message ??= this.generateFallbackMessage(options)\n\n // Step 4: Log warning if --no-verify is configured (but not for silent skip like --wip-commit)\n if (options.skipVerify && !options.skipVerifySilent) {\n getLogger().warn('Skipping pre-commit hooks (--no-verify configured in settings)')\n }\n\n // Step 5: Commit with user review via prompt (unless noReview specified)\n try {\n if (options.noReview || options.message) {\n // Direct commit without review (custom message or noReview flag)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath, ...(options.timeout !== undefined && { timeout: options.timeout }) })\n } else {\n // Prompt user for action instead of going straight to editor\n const action = await promptCommitAction(message)\n\n if (action === 'abort') {\n throw new UserAbortedCommitError()\n }\n\n if (action === 'accept') {\n // Direct commit with -m flag (no editor)\n const commitArgs = ['commit', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, { cwd: worktreePath, ...(options.timeout !== undefined && { timeout: options.timeout }) })\n } else {\n // action === 'edit': Use git editor for user review\n getLogger().info('Opening editor for commit message review...')\n\n // Check for Antigravity FIRST as it takes priority\n if (isRunningInAntigravity() && await isAntigravityAvailable()) {\n await this.commitWithExternalEditor(worktreePath, message, options, 'agy', 'Antigravity')\n // Check for Cursor SECOND since it may also set TERM_PROGRAM=vscode\n // Use Cursor-specific flow when running in Cursor terminal\n } else if (isRunningInCursor() && await isCursorAvailable()) {\n await this.commitWithExternalEditor(worktreePath, message, options, 'cursor', 'Cursor')\n // Use VSCode-specific flow when running in VSCode terminal\n // This opens the file in the current VSCode window instead of a random one\n } else if (isRunningInVSCode() && await isVSCodeAvailable()) {\n await this.commitWithExternalEditor(worktreePath, message, options, 'code', 'VSCode')\n } else {\n // Standard git editor flow for non-VSCode/Cursor/Antigravity environments\n const commitArgs = ['commit', '-e', '-m', message]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n await executeGitCommand(commitArgs, {\n cwd: worktreePath,\n stdio: 'inherit',\n timeout: Math.max(options.timeout ?? 0, 300000) // Use the larger of configured timeout or 5 minutes for interactive editing\n })\n }\n }\n }\n return { message }\n } catch (error) {\n // Re-throw UserAbortedCommitError as-is\n if (error instanceof UserAbortedCommitError) {\n throw error\n }\n // Handle \"nothing to commit\" scenario gracefully\n if (error instanceof Error && error.message.includes('nothing to commit')) {\n getLogger().info('No changes to commit')\n return { message: '' }\n }\n // Re-throw all other errors (including pre-commit hook failures)\n throw error\n }\n }\n\n\n /**\n * Commit with external editor CLI (VSCode, Cursor, Antigravity, etc.)\n * Handles file creation, editing, and commit to ensure the file opens\n * in the current editor window (preserves IPC context)\n */\n private async commitWithExternalEditor(\n worktreePath: string,\n message: string,\n options: CommitOptions,\n cliCommand: string,\n editorName: string\n ): Promise<void> {\n // Put the commit message file in the worktree root so the editor opens it\n // in the correct window (files within a workspace folder open in that workspace's window)\n const commitMsgPath = join(worktreePath, '.COMMIT_EDITMSG')\n\n // Write the initial commit message (with git-style comments)\n const initialContent = `${message}\n\n# Please enter the commit message for your changes. Lines starting\n# with '#' will be ignored, and an empty message aborts the commit.\n#\n# Save and close the file to complete the commit.\n`\n await writeFile(commitMsgPath, initialContent, 'utf-8')\n\n try {\n getLogger().debug(`Opening commit message in ${editorName}: ${commitMsgPath}`)\n\n // Open the file with --wait flag so we block until the user closes it\n await execa(cliCommand, ['--wait', commitMsgPath], {\n cwd: worktreePath,\n stdio: 'inherit'\n })\n\n // Read the edited message\n const editedContent = await readFile(commitMsgPath, 'utf-8')\n\n // Strip comment lines and trim\n const finalMessage = editedContent\n .split('\\n')\n .filter(line => !line.startsWith('#'))\n .join('\\n')\n .trim()\n\n // Check for empty message (user aborted)\n if (!finalMessage) {\n throw new UserAbortedCommitError()\n }\n\n // Commit with the edited message\n const commitArgs = ['commit', '-F', commitMsgPath]\n if (options.skipVerify) {\n commitArgs.push('--no-verify')\n }\n\n // Rewrite the file without comments for git commit -F\n await writeFile(commitMsgPath, finalMessage, 'utf-8')\n await executeGitCommand(commitArgs, { cwd: worktreePath, ...(options.timeout !== undefined && { timeout: options.timeout }) })\n\n } finally {\n // Clean up - git normally handles this but we should be safe\n try {\n await unlink(commitMsgPath)\n } catch {\n // Ignore cleanup errors\n }\n }\n }\n\n /**\n * Generate simple fallback commit message when Claude unavailable\n * Used as fallback for Claude-powered commit messages\n */\n private generateFallbackMessage(options: CommitOptions): string {\n // If custom message provided, use it\n if (options.message) {\n return options.message\n }\n\n // Generate WIP message\n if (options.issueNumber) {\n const trailer = options.trailerType ?? 'Fixes'\n return `WIP: Auto-commit for issue ${options.issuePrefix}${options.issueNumber}\\n\\n${trailer} ${options.issuePrefix}${options.issueNumber}`\n } else {\n return 'WIP: Auto-commit uncommitted changes'\n }\n }\n\n /**\n * Parse git status --porcelain output\n * Format: \"XY filename\" where X=index, Y=worktree\n * Examples:\n * \"M file.ts\" - staged modification\n * \" M file.ts\" - unstaged modification\n * \"MM file.ts\" - both staged and unstaged\n * \"?? file.ts\" - untracked\n */\n private parseGitStatus(porcelainOutput: string): {\n stagedFiles: string[]\n unstagedFiles: string[]\n } {\n const stagedFiles: string[] = []\n const unstagedFiles: string[] = []\n\n if (!porcelainOutput.trim()) {\n return { stagedFiles, unstagedFiles }\n }\n\n const lines = porcelainOutput.split('\\n').filter((line) => line.trim())\n\n for (const line of lines) {\n if (line.length < 3) continue\n\n const indexStatus = line[0] // First character - staging area status\n const worktreeStatus = line[1] // Second character - working tree status\n const filename = line.substring(3) // Everything after \"XY \"\n\n // Check if file is staged\n // First char != ' ' and != '?' → staged\n if (indexStatus !== ' ' && indexStatus !== '?') {\n stagedFiles.push(filename)\n }\n\n // Check if file is unstaged\n // Second char != ' ' or line starts with '??' → unstaged\n if (worktreeStatus !== ' ' || line.startsWith('??')) {\n unstagedFiles.push(filename)\n }\n }\n\n return { stagedFiles, unstagedFiles }\n }\n\n /**\n * Generate commit message using Claude Code\n * Claude examines the git repository directly via --add-dir option\n * Returns null if Claude unavailable or fails validation\n */\n private async generateClaudeCommitMessage(\n worktreePath: string,\n issueNumber: string | number | undefined,\n issuePrefix: string,\n trailerType?: 'Refs' | 'Fixes'\n ): Promise<string | null> {\n const startTime = Date.now()\n\n if (getLogger().isDebugEnabled()) {\n getLogger().debug('Claude commit message generation started', {\n worktreePath: worktreePath.split('/').pop(), // Just show the folder name for privacy\n issueNumber\n })\n } else {\n getLogger().info('Generating commit message with Claude...')\n }\n\n // Check if Claude CLI is available\n getLogger().debug('Checking Claude CLI availability...')\n const isClaudeAvailable = await detectClaudeCli()\n if (!isClaudeAvailable) {\n getLogger().info('Claude CLI not available, skipping Claude commit message generation')\n return null\n }\n getLogger().debug('Claude CLI is available')\n\n // Build XML-based structured prompt\n getLogger().debug('Building commit message prompt...')\n const prompt = this.buildCommitMessagePrompt(issueNumber, issuePrefix, trailerType)\n getLogger().debug('Prompt built', { promptLength: prompt.length })\n\n // Debug log the actual prompt content for troubleshooting\n getLogger().debug('Claude prompt content:', {\n prompt: prompt,\n truncatedPreview: prompt.substring(0, 500) + (prompt.length > 500 ? '...[truncated]' : '')\n })\n\n try {\n const claudeStartTime = Date.now()\n\n // Debug log the Claude call parameters\n const claudeOptions = {\n headless: true,\n addDir: worktreePath,\n model: 'claude-haiku-4-5-20251001', // Fast, cost-effective model\n timeout: 120000, // 120 second timeout\n appendSystemPrompt: 'Output only the requested content. Never include preamble, analysis, or meta-commentary. Your response is used verbatim.',\n noSessionPersistence: true, // Utility operation - don't persist session\n env: { CLAUDE_CODE_SIMPLE: '1' }, // Minimal mode - no MCP, hooks, or CLAUDE.md loading\n }\n getLogger().debug('Claude CLI call parameters:', {\n options: claudeOptions,\n worktreePathForAnalysis: worktreePath,\n addDirContents: 'Will include entire worktree directory for analysis'\n })\n\n // Launch Claude in headless mode with repository access and shorter timeout for commit messages\n const result = await launchClaude(prompt, claudeOptions)\n\n const claudeDuration = Date.now() - claudeStartTime\n getLogger().debug('Claude API call completed', { duration: `${claudeDuration}ms` })\n\n if (typeof result !== 'string') {\n getLogger().warn('Claude returned non-string result', { resultType: typeof result })\n return null\n }\n\n getLogger().debug('Raw Claude output received', {\n outputLength: result.length,\n preview: result.substring(0, 200) + (result.length > 200 ? '...' : '')\n })\n\n\n // Sanitize output - remove meta-commentary and clean formatting\n getLogger().debug('Sanitizing Claude output...')\n const sanitized = this.sanitizeClaudeOutput(result)\n getLogger().debug('Output sanitized', {\n originalLength: result.length,\n sanitizedLength: sanitized.length,\n sanitized: sanitized.substring(0, 200) + (sanitized.length > 200 ? '...' : '')\n })\n\n // Ensure empty strings are rejected\n if (!sanitized) {\n getLogger().warn('Claude returned empty message after sanitization')\n return null\n }\n\n // Append trailer (e.g., \"Fixes #N\" or \"Refs #N\") if issue number provided\n let finalMessage = sanitized\n if (issueNumber) {\n const trailer = trailerType ?? 'Fixes'\n const trailerRef = `${trailer} ${issuePrefix}${issueNumber}`\n // Add trailer if not already present\n if (!finalMessage.includes(trailerRef)) {\n finalMessage = `${finalMessage}\\n\\n${trailerRef}`\n getLogger().debug(`Added \"${trailerRef}\" trailer to commit message`)\n } else {\n getLogger().debug(`\"${trailerRef}\" already present in commit message`)\n }\n }\n\n const totalDuration = Date.now() - startTime\n if (getLogger().isDebugEnabled()) {\n getLogger().debug('Claude commit message generated', {\n message: finalMessage,\n totalDuration: `${totalDuration}ms`,\n claudeApiDuration: `${claudeDuration}ms`\n })\n } else {\n getLogger().info('Commit message generated')\n }\n\n return finalMessage\n } catch (error) {\n const totalDuration = Date.now() - startTime\n const errorMessage = error instanceof Error ? error.message : 'Unknown error'\n\n if (errorMessage.includes('timed out') || errorMessage.includes('timeout')) {\n getLogger().warn('Claude commit message generation timed out after 45 seconds', {\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n } else {\n getLogger().warn('Failed to generate commit message with Claude', {\n error: errorMessage,\n totalDuration: `${totalDuration}ms`,\n worktreePath: worktreePath.split('/').pop()\n })\n }\n return null\n }\n }\n\n /**\n * Build structured XML prompt for commit message generation\n * Uses XML format for clear task definition and output expectations\n */\n private buildCommitMessagePrompt(\n issueNumber: string | number | undefined,\n issuePrefix: string,\n trailerType?: 'Refs' | 'Fixes'\n ): string {\n const trailer = trailerType ?? 'Fixes'\n const issueContext = issueNumber\n ? `\\n<IssueContext>\nThis commit is associated with issue ${issuePrefix}${issueNumber}.\n${trailer === 'Fixes' ? 'If the changes appear to resolve the issue, include' : 'Include'} \"${trailer} ${issuePrefix}${issueNumber}\" at the end of the first line of commit message.\n</IssueContext>`\n : ''\n\n const examplePrefix = issuePrefix || '' // Use empty string for Linear examples\n return `<Task>\nYou are a software engineer writing a commit message for this repository.\nExamine the staged changes in the git repository and generate a concise, meaningful commit message.\n</Task>\n\n<Requirements>\n<Format>The first line must be a brief summary of the changes made as a full sentence. If it references an issue, include \"${trailer} ${examplePrefix}N\" at the end of this line.\n\nAdd 2 newlines, then add a bullet-point form description of the changes made, each change on a new line.</Format>\n<Mood>Use imperative mood (e.g., \"Add feature\" not \"Added feature\")</Mood>\n<Focus>Be specific about what was changed and why</Focus>\n<Conciseness>Keep message under 72 characters for subject line when possible</Conciseness>\n<NoMeta>CRITICAL: Do NOT include ANY explanatory text, analysis, or meta-commentary. Output ONLY the raw commit message.</NoMeta>\n<Examples>\nGood: \"Add user authentication with JWT tokens. ${trailer} ${examplePrefix}42\n\n- Implement login and registration endpoints\n- Secure routes with JWT middleware\n- Update user model to store hashed passwords\"\nGood: \"Fix navigation bug in sidebar menu.\"\nBad: \"Based on the changes, I'll create: Add user authentication\"\nBad: \"Looking at the files, this commit should be: Fix navigation bug\"\n</Examples>\n${issueContext}\n</Requirements>\n\n<Output>\nIMPORTANT: Your entire response will be used directly as the git commit message.\nDo not include any explanatory text before or after the commit message.\nStart your response immediately with the commit message text.\n</Output>`\n }\n\n /**\n * Sanitize Claude output to remove meta-commentary and clean formatting\n * Handles cases where Claude includes explanatory text despite instructions\n */\n private sanitizeClaudeOutput(rawOutput: string): string {\n let cleaned = rawOutput.trim()\n\n // Remove common meta-commentary patterns (case-insensitive)\n const metaPatterns = [\n /^.*?based on.*?changes.*?:/i,\n /^.*?looking at.*?files.*?:/i,\n /^.*?examining.*?:/i,\n /^.*?analyzing.*?:/i,\n /^.*?i'll.*?generate.*?:/i,\n /^.*?let me.*?:/i,\n /^.*?the commit message.*?should be.*?:/i,\n /^.*?here.*?is.*?commit.*?message.*?:/i,\n ]\n\n for (const pattern of metaPatterns) {\n cleaned = cleaned.replace(pattern, '').trim()\n }\n\n // Extract content after separators only if it looks like meta-commentary\n // Only split on colons if there's clear meta-commentary before it\n if (cleaned.includes(':')) {\n const colonIndex = cleaned.indexOf(':')\n const beforeColon = cleaned.substring(0, colonIndex).trim().toLowerCase()\n\n // Only split if the text before colon looks like meta-commentary\n const metaIndicators = [\n 'here is the commit message',\n 'commit message',\n 'here is',\n 'the message should be',\n 'i suggest',\n 'my suggestion'\n ]\n\n const isMetaCommentary = metaIndicators.some(indicator => beforeColon.includes(indicator))\n\n if (isMetaCommentary) {\n const afterColon = cleaned.substring(colonIndex + 1).trim()\n if (afterColon && afterColon.length > 10) {\n cleaned = afterColon\n }\n }\n }\n\n // Remove quotes if the entire message is wrapped in them\n if ((cleaned.startsWith('\"') && cleaned.endsWith('\"')) ||\n (cleaned.startsWith(\"'\") && cleaned.endsWith(\"'\"))) {\n cleaned = cleaned.slice(1, -1).trim()\n }\n\n return cleaned\n }\n}\n"],"mappings":"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","names":["execa"]}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
PromptTemplateManager,
|
|
4
4
|
buildReviewTemplateVariables
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-7RCUWU3I.js";
|
|
6
6
|
import {
|
|
7
7
|
logger
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-VRPPI6GU.js";
|
|
9
9
|
|
|
10
10
|
// src/lib/AgentManager.ts
|
|
11
11
|
import { readFile } from "fs/promises";
|
|
@@ -270,6 +270,36 @@ var AgentManager = class {
|
|
|
270
270
|
formatForCli(agents) {
|
|
271
271
|
return agents;
|
|
272
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* Load agents and prepare them for the current platform.
|
|
275
|
+
* On macOS, returns agents formatted for the --agents CLI flag.
|
|
276
|
+
* On Linux/Windows, renders agents to disk for auto-discovery and returns undefined.
|
|
277
|
+
*
|
|
278
|
+
* @param settings - Project settings for model overrides
|
|
279
|
+
* @param templateVariables - Variables to substitute in agent prompts
|
|
280
|
+
* @param patterns - Glob patterns for which agent files to load
|
|
281
|
+
* @param targetDir - Directory for disk rendering (Linux/Windows). Defaults to cwd/.claude/agents/
|
|
282
|
+
* @returns Agents object for CLI flag (macOS) or undefined (Linux/Windows, agents on disk)
|
|
283
|
+
*/
|
|
284
|
+
async loadAndPrepare(settings, templateVariables, patterns, targetDir) {
|
|
285
|
+
const loadedAgents = await this.loadAgents(settings, templateVariables, patterns);
|
|
286
|
+
if (process.platform === "darwin") {
|
|
287
|
+
const agents = this.formatForCli(loadedAgents);
|
|
288
|
+
logger.debug("Loaded agent configurations for CLI", {
|
|
289
|
+
agentCount: Object.keys(agents).length,
|
|
290
|
+
agentNames: Object.keys(agents)
|
|
291
|
+
});
|
|
292
|
+
return agents;
|
|
293
|
+
}
|
|
294
|
+
const dir = targetDir ?? path.join(process.cwd(), ".claude", "agents");
|
|
295
|
+
const rendered = await this.renderAgentsToDisk(loadedAgents, dir);
|
|
296
|
+
logger.debug("Rendered agent files to disk for auto-discovery", {
|
|
297
|
+
agentCount: rendered.length,
|
|
298
|
+
agentNames: rendered,
|
|
299
|
+
targetDir: dir
|
|
300
|
+
});
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
273
303
|
/**
|
|
274
304
|
* Render loaded agents to disk as markdown files with YAML frontmatter.
|
|
275
305
|
* Claude Code auto-discovers agents from .claude/agents/ directory.
|
|
@@ -304,4 +334,4 @@ var AgentManager = class {
|
|
|
304
334
|
export {
|
|
305
335
|
AgentManager
|
|
306
336
|
};
|
|
307
|
-
//# sourceMappingURL=chunk-
|
|
337
|
+
//# sourceMappingURL=chunk-Y2MVSEJK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/AgentManager.ts","../src/utils/MarkdownAgentParser.ts"],"sourcesContent":["import { readFile } from 'fs/promises'\nimport { accessSync } from 'fs'\nimport path from 'path'\nimport { fileURLToPath } from 'url'\nimport fg from 'fast-glob'\nimport fs from 'fs-extra'\nimport { MarkdownAgentParser } from '../utils/MarkdownAgentParser.js'\nimport { logger } from '../utils/logger.js'\nimport type { IloomSettings } from './SettingsManager.js'\nimport { PromptTemplateManager, TemplateVariables, buildReviewTemplateVariables } from './PromptTemplateManager.js'\n\n// Agent schema interface\nexport interface AgentConfig {\n\tdescription: string\n\tprompt: string\n\ttools?: string[] // Optional - when omitted, agent inherits all tools from parent\n\tmodel: string\n\tcolor?: string\n}\n\n// Container for all loaded agents (keyed by agent name without extension)\nexport interface AgentConfigs {\n\t[agentName: string]: AgentConfig\n}\n\nexport class AgentManager {\n\tprivate agentDir: string\n\tprivate templateManager: PromptTemplateManager\n\n\tconstructor(agentDir?: string, templateManager?: PromptTemplateManager) {\n\t\tthis.templateManager = templateManager ?? new PromptTemplateManager()\n\t\tif (agentDir) {\n\t\t\tthis.agentDir = agentDir\n\t\t} else {\n\t\t\t// Find agents relative to package installation\n\t\t\t// Same pattern as PromptTemplateManager\n\t\t\t// When running from dist/, agents are copied to dist/agents/\n\t\t\tconst currentFileUrl = import.meta.url\n\t\t\tconst currentFilePath = fileURLToPath(currentFileUrl)\n\t\t\tconst distDir = path.dirname(currentFilePath)\n\n\t\t\t// Walk up to find the agents directory\n\t\t\tlet agentDirPath = path.join(distDir, 'agents')\n\t\t\tlet currentDir = distDir\n\n\t\t\twhile (currentDir !== path.dirname(currentDir)) {\n\t\t\t\tconst candidatePath = path.join(currentDir, 'agents')\n\t\t\t\ttry {\n\t\t\t\t\taccessSync(candidatePath)\n\t\t\t\t\tagentDirPath = candidatePath\n\t\t\t\t\tbreak\n\t\t\t\t} catch {\n\t\t\t\t\tcurrentDir = path.dirname(currentDir)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.agentDir = agentDirPath\n\t\t\tlogger.debug('AgentManager initialized', { agentDir: this.agentDir })\n\t\t}\n\t}\n\n\t/**\n\t * Load agent configuration files from markdown (.md) format\n\t * Optionally apply model overrides from settings and template variable substitution\n\t * Throws error if agents directory doesn't exist or files are malformed\n\t * @param settings - Optional project settings with per-agent model overrides\n\t * @param templateVariables - Optional variables for template substitution in agent prompts\n\t * @param patterns - Optional glob patterns to filter which agents to load (default: ['*.md'])\n\t * Supports negation patterns like ['*.md', '!iloom-framework-detector.md']\n\t */\n\tasync loadAgents(\n\t\tsettings?: IloomSettings,\n\t\ttemplateVariables?: TemplateVariables,\n\t\tpatterns: string[] = ['*.md']\n\t): Promise<AgentConfigs> {\n\t\t// Use fast-glob to filter agent files based on patterns\n\t\tconst agentFiles = await fg(patterns, {\n\t\t\tcwd: this.agentDir,\n\t\t\tonlyFiles: true,\n\t\t})\n\n\t\tconst agents: AgentConfigs = {}\n\n\t\tfor (const filename of agentFiles) {\n\t\t\tconst agentPath = path.join(this.agentDir, filename)\n\n\t\t\ttry {\n\t\t\t\tconst content = await readFile(agentPath, 'utf-8')\n\n\t\t\t\t// Parse markdown with frontmatter\n\t\t\t\tconst parsed = this.parseMarkdownAgent(content, filename)\n\t\t\t\tconst agentConfig = parsed.config\n\t\t\t\tconst agentName = parsed.name\n\n\t\t\t\t// Validate required fields\n\t\t\t\tthis.validateAgentConfig(agentConfig, agentName)\n\n\t\t\t\tagents[agentName] = agentConfig\n\t\t\t\tlogger.debug(`Loaded agent: ${agentName}`)\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(`Failed to load agent from ${filename}`, { error })\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Failed to load agent from ${filename}: ${error instanceof Error ? error.message : 'Unknown error'}`,\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\t// Apply template variable substitution to agent prompts if variables provided\n\t\tif (templateVariables) {\n\t\t\t// Extract review config from settings and add to template variables\n\t\t\tObject.assign(templateVariables, buildReviewTemplateVariables(!!templateVariables.SWARM_MODE, settings?.agents))\n\n\t\t\tfor (const [agentName, agentConfig] of Object.entries(agents)) {\n\t\t\t\tagents[agentName] = {\n\t\t\t\t\t...agentConfig,\n\t\t\t\t\tprompt: this.templateManager.substituteVariables(agentConfig.prompt, templateVariables),\n\t\t\t\t}\n\t\t\t\tlogger.debug(`Applied template substitution to agent: ${agentName}`)\n\t\t\t}\n\t\t}\n\n\t\t// Apply settings overrides if provided\n\t\tif (settings?.agents) {\n\t\t\tfor (const [agentName, agentSettings] of Object.entries(settings.agents)) {\n\t\t\t\tif (agents[agentName] && agentSettings.model) {\n\t\t\t\t\tlogger.debug(`Overriding model for ${agentName}: ${agents[agentName].model} -> ${agentSettings.model}`)\n\t\t\t\t\tagents[agentName] = {\n\t\t\t\t\t\t...agents[agentName],\n\t\t\t\t\t\tmodel: agentSettings.model,\n\t\t\t\t\t}\n\t\t\t\t} else if (!agents[agentName]) {\n\t\t\t\t\t// Skip warning for runtime-generated agents (e.g., swarm worker)\n\t\t\t\t\tconst RUNTIME_GENERATED_AGENTS = ['iloom-swarm-worker']\n\t\t\t\t\tif (!RUNTIME_GENERATED_AGENTS.includes(agentName)) {\n\t\t\t\t\t\t// Only warn if the agent file doesn't exist at all (typo in settings)\n\t\t\t\t\t\t// Skip warning if the agent exists but wasn't loaded due to pattern filtering\n\t\t\t\t\t\tconst agentFile = path.join(this.agentDir, `${agentName}.md`)\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\taccessSync(agentFile)\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tlogger.warn(`Settings reference unknown agent: ${agentName}`)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn agents\n\t}\n\n\t/**\n\t * Validate agent configuration has required fields\n\t * Note: tools is optional - when omitted, agent inherits all tools from parent\n\t */\n\tprivate validateAgentConfig(config: AgentConfig, agentName: string): void {\n\t\tconst requiredFields: (keyof AgentConfig)[] = ['description', 'prompt', 'model']\n\n\t\tfor (const field of requiredFields) {\n\t\t\tif (!config[field]) {\n\t\t\t\tthrow new Error(`Agent ${agentName} missing required field: ${field}`)\n\t\t\t}\n\t\t}\n\n\t\t// Tools is optional, but if present must be an array\n\t\tif (config.tools !== undefined && !Array.isArray(config.tools)) {\n\t\t\tthrow new Error(`Agent ${agentName} tools must be an array`)\n\t\t}\n\t}\n\n\t/**\n\t * Parse markdown agent file with YAML frontmatter\n\t * @param content - Raw markdown file content\n\t * @param filename - Original filename for error messages\n\t * @returns Parsed agent config and name\n\t */\n\tprivate parseMarkdownAgent(content: string, filename: string): { config: AgentConfig; name: string } {\n\t\ttry {\n\t\t\t// Parse frontmatter using custom parser\n\t\t\tconst { data, content: markdownBody } = MarkdownAgentParser.parse(content)\n\n\t\t\t// Validate frontmatter has required fields\n\t\t\tif (!data.name) {\n\t\t\t\tthrow new Error('Missing required field: name')\n\t\t\t}\n\t\t\tif (!data.description) {\n\t\t\t\tthrow new Error('Missing required field: description')\n\t\t\t}\n\t\t\t// Note: tools is now optional - when omitted, agent inherits all tools from parent\n\t\t\tif (!data.model) {\n\t\t\t\tthrow new Error('Missing required field: model')\n\t\t\t}\n\n\t\t\t// Parse tools from comma-separated string to array (only if tools field is present)\n\t\t\tlet tools: string[] | undefined\n\t\t\tif (data.tools) {\n\t\t\t\ttools = data.tools\n\t\t\t\t\t.split(',')\n\t\t\t\t\t.map((tool: string) => tool.trim())\n\t\t\t\t\t.filter((tool: string) => tool.length > 0)\n\t\t\t}\n\n\t\t\t// Validate model and warn if non-standard\n\t\t\tconst validModels = ['sonnet', 'opus', 'haiku']\n\t\t\tif (!validModels.includes(data.model)) {\n\t\t\t\tlogger.warn(\n\t\t\t\t\t`Agent ${data.name} uses model \"${data.model}\" which may not be recognized by Claude CLI, and your workflow may fail or produce unexpected results. ` +\n\t\t\t\t\t\t`Valid values are: ${validModels.join(', ')}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\t// Construct AgentConfig\n\t\t\tconst config: AgentConfig = {\n\t\t\t\tdescription: data.description,\n\t\t\t\tprompt: markdownBody.trim(),\n\t\t\t\tmodel: data.model,\n\t\t\t\t...(tools && { tools }),\n\t\t\t\t...(data.color && { color: data.color }),\n\t\t\t}\n\n\t\t\treturn { config, name: data.name }\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to parse markdown agent ${filename}: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t}\n\n\t/**\n\t * Format loaded agents for Claude CLI --agents flag\n\t * Returns object suitable for JSON.stringify\n\t */\n\tformatForCli(agents: AgentConfigs): Record<string, unknown> {\n\t\t// The agents object is already in the correct format\n\t\t// Just return it - launchClaude will JSON.stringify it\n\t\treturn agents as Record<string, unknown>\n\t}\n\n\t/**\n\t * Load agents and prepare them for the current platform.\n\t * On macOS, returns agents formatted for the --agents CLI flag.\n\t * On Linux/Windows, renders agents to disk for auto-discovery and returns undefined.\n\t *\n\t * @param settings - Project settings for model overrides\n\t * @param templateVariables - Variables to substitute in agent prompts\n\t * @param patterns - Glob patterns for which agent files to load\n\t * @param targetDir - Directory for disk rendering (Linux/Windows). Defaults to cwd/.claude/agents/\n\t * @returns Agents object for CLI flag (macOS) or undefined (Linux/Windows, agents on disk)\n\t */\n\tasync loadAndPrepare(\n\t\tsettings: IloomSettings | undefined,\n\t\ttemplateVariables: TemplateVariables,\n\t\tpatterns: string[],\n\t\ttargetDir?: string\n\t): Promise<Record<string, unknown> | undefined> {\n\t\tconst loadedAgents = await this.loadAgents(settings, templateVariables, patterns)\n\n\t\tif (process.platform === 'darwin') {\n\t\t\tconst agents = this.formatForCli(loadedAgents)\n\t\t\tlogger.debug('Loaded agent configurations for CLI', {\n\t\t\t\tagentCount: Object.keys(agents).length,\n\t\t\t\tagentNames: Object.keys(agents),\n\t\t\t})\n\t\t\treturn agents\n\t\t}\n\n\t\tconst dir = targetDir ?? path.join(process.cwd(), '.claude', 'agents')\n\t\tconst rendered = await this.renderAgentsToDisk(loadedAgents, dir)\n\t\tlogger.debug('Rendered agent files to disk for auto-discovery', {\n\t\t\tagentCount: rendered.length,\n\t\t\tagentNames: rendered,\n\t\t\ttargetDir: dir,\n\t\t})\n\t\treturn undefined\n\t}\n\n\t/**\n\t * Render loaded agents to disk as markdown files with YAML frontmatter.\n\t * Claude Code auto-discovers agents from .claude/agents/ directory.\n\t *\n\t * @param agents - Loaded agent configs (from loadAgents())\n\t * @param targetDir - Absolute path to target directory (e.g., <worktree>/.claude/agents/)\n\t * @returns Array of rendered filenames\n\t */\n\tasync renderAgentsToDisk(agents: AgentConfigs, targetDir: string): Promise<string[]> {\n\t\tawait fs.ensureDir(targetDir)\n\n\t\t// Clean existing iloom agent files to avoid stale agents from previous runs\n\t\tconst existingFiles = await fg('iloom-*.md', { cwd: targetDir, onlyFiles: true })\n\t\tfor (const file of existingFiles) {\n\t\t\tawait fs.remove(path.join(targetDir, file))\n\t\t}\n\n\t\tconst renderedFiles: string[] = []\n\t\tfor (const [agentName, config] of Object.entries(agents)) {\n\t\t\tconst safeName = path.basename(agentName)\n\t\t\tconst filename = `${safeName}.md`\n\t\t\t// Build YAML frontmatter\n\t\t\tconst frontmatterLines = ['---', `name: ${agentName}`, `description: ${config.description}`]\n\t\t\tif (config.tools) frontmatterLines.push(`tools: ${config.tools.join(', ')}`)\n\t\t\tfrontmatterLines.push(`model: ${config.model}`)\n\t\t\tif (config.color) frontmatterLines.push(`color: ${config.color}`)\n\t\t\tfrontmatterLines.push('---')\n\n\t\t\tconst content = frontmatterLines.join('\\n') + '\\n\\n' + config.prompt + '\\n'\n\t\t\tawait fs.writeFile(path.join(targetDir, filename), content, 'utf-8')\n\t\t\trenderedFiles.push(filename)\n\t\t}\n\t\treturn renderedFiles\n\t}\n}\n","/**\n * Custom YAML frontmatter parser for agent markdown files\n * Replaces gray-matter dependency with lightweight custom implementation\n */\n\ninterface ParseResult {\n\tdata: Record<string, string>\n\tcontent: string\n}\n\nexport class MarkdownAgentParser {\n\t/**\n\t * Parse markdown content with YAML frontmatter\n\t * @param content - Raw markdown file content\n\t * @returns Object with parsed frontmatter data and markdown body content\n\t * @throws Error if frontmatter is malformed or missing\n\t */\n\tstatic parse(content: string): ParseResult {\n\t\tconst lines = content.split('\\n')\n\n\t\t// Check for opening frontmatter delimiter\n\t\tif (lines[0]?.trim() !== '---') {\n\t\t\tthrow new Error('Missing opening frontmatter delimiter (---)')\n\t\t}\n\n\t\t// Find closing frontmatter delimiter\n\t\tlet closingDelimiterIndex = -1\n\t\tfor (let i = 1; i < lines.length; i++) {\n\t\t\tif (lines[i]?.trim() === '---') {\n\t\t\t\tclosingDelimiterIndex = i\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (closingDelimiterIndex === -1) {\n\t\t\tthrow new Error('Missing closing frontmatter delimiter (---)')\n\t\t}\n\n\t\t// Extract frontmatter lines (between the delimiters)\n\t\tconst frontmatterLines = lines.slice(1, closingDelimiterIndex)\n\n\t\t// Extract markdown body (after closing delimiter)\n\t\tconst bodyLines = lines.slice(closingDelimiterIndex + 1)\n\t\tconst markdownBody = bodyLines.join('\\n')\n\n\t\t// Parse YAML frontmatter into key-value pairs\n\t\tconst data = this.parseYaml(frontmatterLines.join('\\n'))\n\n\t\treturn {\n\t\t\tdata,\n\t\t\tcontent: markdownBody,\n\t\t}\n\t}\n\n\t/**\n\t * Parse simplified YAML into key-value object\n\t * Supports:\n\t * - Simple key: value pairs\n\t * - Multiline values with | indicator\n\t * - Values with special characters and newlines\n\t *\n\t * @param yaml - YAML string to parse\n\t * @returns Object with parsed key-value pairs\n\t */\n\tprivate static parseYaml(yaml: string): Record<string, string> {\n\t\tconst result: Record<string, string> = {}\n\t\tconst lines = yaml.split('\\n')\n\t\tlet currentKey: string | null = null\n\t\tlet currentValue: string[] = []\n\t\tlet isMultiline = false\n\n\t\tconst finalizeCurrent = (): void => {\n\t\t\tif (currentKey && currentValue.length > 0) {\n\t\t\t\tresult[currentKey] = currentValue.join('\\n').trim()\n\t\t\t\tcurrentKey = null\n\t\t\t\tcurrentValue = []\n\t\t\t}\n\t\t}\n\n\t\tfor (const line of lines) {\n\t\t\t// Skip empty lines when not in multiline mode\n\t\t\tif (!isMultiline && line.trim() === '') {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\t// Check if this is a new key-value pair\n\t\t\tconst keyValueMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\\s*:\\s*(.*)$/)\n\n\t\t\tif (keyValueMatch && !isMultiline) {\n\t\t\t\t// Finalize previous key if exists\n\t\t\t\tfinalizeCurrent()\n\n\t\t\t\tconst [, key, value] = keyValueMatch\n\t\t\t\tif (!key || value === undefined) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tcurrentKey = key\n\n\t\t\t\t// Check for multiline indicator\n\t\t\t\tif (value.trim() === '|') {\n\t\t\t\t\tisMultiline = true\n\t\t\t\t\tcurrentValue = []\n\t\t\t\t} else {\n\t\t\t\t\t// Single line value\n\t\t\t\t\tcurrentValue = [value]\n\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\tisMultiline = false\n\t\t\t\t}\n\t\t\t} else if (isMultiline && currentKey) {\n\t\t\t\t// Continuation of multiline value\n\t\t\t\t// Check if we've returned to normal indentation (new key)\n\t\t\t\tif (line.match(/^[a-zA-Z_][a-zA-Z0-9_-]*\\s*:/) && !line.startsWith(' ')) {\n\t\t\t\t\t// End of multiline, this is a new key\n\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\tisMultiline = false\n\n\t\t\t\t\t// Process this line as a new key\n\t\t\t\t\tconst match = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*)\\s*:\\s*(.*)$/)\n\t\t\t\t\tif (match) {\n\t\t\t\t\t\tconst [, key, value] = match\n\t\t\t\t\t\tif (key && value !== undefined) {\n\t\t\t\t\t\t\tcurrentKey = key\n\t\t\t\t\t\t\tcurrentValue = [value]\n\t\t\t\t\t\t\tfinalizeCurrent()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Remove leading spaces (common indentation) from multiline values\n\t\t\t\t\tconst trimmedLine = line.replace(/^ {2}/, '')\n\t\t\t\t\tcurrentValue.push(trimmedLine)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Finalize last key\n\t\tfinalizeCurrent()\n\n\t\treturn result\n\t}\n}\n"],"mappings":";;;;;;;;;;AAAA,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,OAAO,QAAQ;AACf,OAAO,QAAQ;;;ACKR,IAAM,sBAAN,MAA0B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhC,OAAO,MAAM,SAA8B;AAjB5C;AAkBE,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAGhC,UAAI,WAAM,CAAC,MAAP,mBAAU,YAAW,OAAO;AAC/B,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC9D;AAGA,QAAI,wBAAwB;AAC5B,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACtC,YAAI,WAAM,CAAC,MAAP,mBAAU,YAAW,OAAO;AAC/B,gCAAwB;AACxB;AAAA,MACD;AAAA,IACD;AAEA,QAAI,0BAA0B,IAAI;AACjC,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC9D;AAGA,UAAM,mBAAmB,MAAM,MAAM,GAAG,qBAAqB;AAG7D,UAAM,YAAY,MAAM,MAAM,wBAAwB,CAAC;AACvD,UAAM,eAAe,UAAU,KAAK,IAAI;AAGxC,UAAM,OAAO,KAAK,UAAU,iBAAiB,KAAK,IAAI,CAAC;AAEvD,WAAO;AAAA,MACN;AAAA,MACA,SAAS;AAAA,IACV;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,OAAe,UAAU,MAAsC;AAC9D,UAAM,SAAiC,CAAC;AACxC,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAI,aAA4B;AAChC,QAAI,eAAyB,CAAC;AAC9B,QAAI,cAAc;AAElB,UAAM,kBAAkB,MAAY;AACnC,UAAI,cAAc,aAAa,SAAS,GAAG;AAC1C,eAAO,UAAU,IAAI,aAAa,KAAK,IAAI,EAAE,KAAK;AAClD,qBAAa;AACb,uBAAe,CAAC;AAAA,MACjB;AAAA,IACD;AAEA,eAAW,QAAQ,OAAO;AAEzB,UAAI,CAAC,eAAe,KAAK,KAAK,MAAM,IAAI;AACvC;AAAA,MACD;AAGA,YAAM,gBAAgB,KAAK,MAAM,wCAAwC;AAEzE,UAAI,iBAAiB,CAAC,aAAa;AAElC,wBAAgB;AAEhB,cAAM,CAAC,EAAE,KAAK,KAAK,IAAI;AACvB,YAAI,CAAC,OAAO,UAAU,QAAW;AAChC;AAAA,QACD;AACA,qBAAa;AAGb,YAAI,MAAM,KAAK,MAAM,KAAK;AACzB,wBAAc;AACd,yBAAe,CAAC;AAAA,QACjB,OAAO;AAEN,yBAAe,CAAC,KAAK;AACrB,0BAAgB;AAChB,wBAAc;AAAA,QACf;AAAA,MACD,WAAW,eAAe,YAAY;AAGrC,YAAI,KAAK,MAAM,8BAA8B,KAAK,CAAC,KAAK,WAAW,GAAG,GAAG;AAExE,0BAAgB;AAChB,wBAAc;AAGd,gBAAM,QAAQ,KAAK,MAAM,wCAAwC;AACjE,cAAI,OAAO;AACV,kBAAM,CAAC,EAAE,KAAK,KAAK,IAAI;AACvB,gBAAI,OAAO,UAAU,QAAW;AAC/B,2BAAa;AACb,6BAAe,CAAC,KAAK;AACrB,8BAAgB;AAAA,YACjB;AAAA,UACD;AAAA,QACD,OAAO;AAEN,gBAAM,cAAc,KAAK,QAAQ,SAAS,EAAE;AAC5C,uBAAa,KAAK,WAAW;AAAA,QAC9B;AAAA,MACD;AAAA,IACD;AAGA,oBAAgB;AAEhB,WAAO;AAAA,EACR;AACD;;;ADlHO,IAAM,eAAN,MAAmB;AAAA,EAIzB,YAAY,UAAmB,iBAAyC;AACvE,SAAK,kBAAkB,mBAAmB,IAAI,sBAAsB;AACpE,QAAI,UAAU;AACb,WAAK,WAAW;AAAA,IACjB,OAAO;AAIN,YAAM,iBAAiB,YAAY;AACnC,YAAM,kBAAkB,cAAc,cAAc;AACpD,YAAM,UAAU,KAAK,QAAQ,eAAe;AAG5C,UAAI,eAAe,KAAK,KAAK,SAAS,QAAQ;AAC9C,UAAI,aAAa;AAEjB,aAAO,eAAe,KAAK,QAAQ,UAAU,GAAG;AAC/C,cAAM,gBAAgB,KAAK,KAAK,YAAY,QAAQ;AACpD,YAAI;AACH,qBAAW,aAAa;AACxB,yBAAe;AACf;AAAA,QACD,QAAQ;AACP,uBAAa,KAAK,QAAQ,UAAU;AAAA,QACrC;AAAA,MACD;AAEA,WAAK,WAAW;AAChB,aAAO,MAAM,4BAA4B,EAAE,UAAU,KAAK,SAAS,CAAC;AAAA,IACrE;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,WACL,UACA,mBACA,WAAqB,CAAC,MAAM,GACJ;AAExB,UAAM,aAAa,MAAM,GAAG,UAAU;AAAA,MACrC,KAAK,KAAK;AAAA,MACV,WAAW;AAAA,IACZ,CAAC;AAED,UAAM,SAAuB,CAAC;AAE9B,eAAW,YAAY,YAAY;AAClC,YAAM,YAAY,KAAK,KAAK,KAAK,UAAU,QAAQ;AAEnD,UAAI;AACH,cAAM,UAAU,MAAM,SAAS,WAAW,OAAO;AAGjD,cAAM,SAAS,KAAK,mBAAmB,SAAS,QAAQ;AACxD,cAAM,cAAc,OAAO;AAC3B,cAAM,YAAY,OAAO;AAGzB,aAAK,oBAAoB,aAAa,SAAS;AAE/C,eAAO,SAAS,IAAI;AACpB,eAAO,MAAM,iBAAiB,SAAS,EAAE;AAAA,MAC1C,SAAS,OAAO;AACf,eAAO,MAAM,6BAA6B,QAAQ,IAAI,EAAE,MAAM,CAAC;AAC/D,cAAM,IAAI;AAAA,UACT,6BAA6B,QAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,QACnG;AAAA,MACD;AAAA,IACD;AAGA,QAAI,mBAAmB;AAEtB,aAAO,OAAO,mBAAmB,6BAA6B,CAAC,CAAC,kBAAkB,YAAY,qCAAU,MAAM,CAAC;AAE/G,iBAAW,CAAC,WAAW,WAAW,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC9D,eAAO,SAAS,IAAI;AAAA,UACnB,GAAG;AAAA,UACH,QAAQ,KAAK,gBAAgB,oBAAoB,YAAY,QAAQ,iBAAiB;AAAA,QACvF;AACA,eAAO,MAAM,2CAA2C,SAAS,EAAE;AAAA,MACpE;AAAA,IACD;AAGA,QAAI,qCAAU,QAAQ;AACrB,iBAAW,CAAC,WAAW,aAAa,KAAK,OAAO,QAAQ,SAAS,MAAM,GAAG;AACzE,YAAI,OAAO,SAAS,KAAK,cAAc,OAAO;AAC7C,iBAAO,MAAM,wBAAwB,SAAS,KAAK,OAAO,SAAS,EAAE,KAAK,OAAO,cAAc,KAAK,EAAE;AACtG,iBAAO,SAAS,IAAI;AAAA,YACnB,GAAG,OAAO,SAAS;AAAA,YACnB,OAAO,cAAc;AAAA,UACtB;AAAA,QACD,WAAW,CAAC,OAAO,SAAS,GAAG;AAE9B,gBAAM,2BAA2B,CAAC,oBAAoB;AACtD,cAAI,CAAC,yBAAyB,SAAS,SAAS,GAAG;AAGlD,kBAAM,YAAY,KAAK,KAAK,KAAK,UAAU,GAAG,SAAS,KAAK;AAC5D,gBAAI;AACH,yBAAW,SAAS;AAAA,YACrB,QAAQ;AACP,qBAAO,KAAK,qCAAqC,SAAS,EAAE;AAAA,YAC7D;AAAA,UACD;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAEA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB,QAAqB,WAAyB;AACzE,UAAM,iBAAwC,CAAC,eAAe,UAAU,OAAO;AAE/E,eAAW,SAAS,gBAAgB;AACnC,UAAI,CAAC,OAAO,KAAK,GAAG;AACnB,cAAM,IAAI,MAAM,SAAS,SAAS,4BAA4B,KAAK,EAAE;AAAA,MACtE;AAAA,IACD;AAGA,QAAI,OAAO,UAAU,UAAa,CAAC,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/D,YAAM,IAAI,MAAM,SAAS,SAAS,yBAAyB;AAAA,IAC5D;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,mBAAmB,SAAiB,UAAyD;AACpG,QAAI;AAEH,YAAM,EAAE,MAAM,SAAS,aAAa,IAAI,oBAAoB,MAAM,OAAO;AAGzE,UAAI,CAAC,KAAK,MAAM;AACf,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAC/C;AACA,UAAI,CAAC,KAAK,aAAa;AACtB,cAAM,IAAI,MAAM,qCAAqC;AAAA,MACtD;AAEA,UAAI,CAAC,KAAK,OAAO;AAChB,cAAM,IAAI,MAAM,+BAA+B;AAAA,MAChD;AAGA,UAAI;AACJ,UAAI,KAAK,OAAO;AACf,gBAAQ,KAAK,MACX,MAAM,GAAG,EACT,IAAI,CAAC,SAAiB,KAAK,KAAK,CAAC,EACjC,OAAO,CAAC,SAAiB,KAAK,SAAS,CAAC;AAAA,MAC3C;AAGA,YAAM,cAAc,CAAC,UAAU,QAAQ,OAAO;AAC9C,UAAI,CAAC,YAAY,SAAS,KAAK,KAAK,GAAG;AACtC,eAAO;AAAA,UACN,SAAS,KAAK,IAAI,gBAAgB,KAAK,KAAK,4HACtB,YAAY,KAAK,IAAI,CAAC;AAAA,QAC7C;AAAA,MACD;AAGA,YAAM,SAAsB;AAAA,QAC3B,aAAa,KAAK;AAAA,QAClB,QAAQ,aAAa,KAAK;AAAA,QAC1B,OAAO,KAAK;AAAA,QACZ,GAAI,SAAS,EAAE,MAAM;AAAA,QACrB,GAAI,KAAK,SAAS,EAAE,OAAO,KAAK,MAAM;AAAA,MACvC;AAEA,aAAO,EAAE,QAAQ,MAAM,KAAK,KAAK;AAAA,IAClC,SAAS,OAAO;AACf,YAAM,IAAI;AAAA,QACT,kCAAkC,QAAQ,KAAK,iBAAiB,QAAQ,MAAM,UAAU,eAAe;AAAA,MACxG;AAAA,IACD;AAAA,EACD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,QAA+C;AAG3D,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,eACL,UACA,mBACA,UACA,WAC+C;AAC/C,UAAM,eAAe,MAAM,KAAK,WAAW,UAAU,mBAAmB,QAAQ;AAEhF,QAAI,QAAQ,aAAa,UAAU;AAClC,YAAM,SAAS,KAAK,aAAa,YAAY;AAC7C,aAAO,MAAM,uCAAuC;AAAA,QACnD,YAAY,OAAO,KAAK,MAAM,EAAE;AAAA,QAChC,YAAY,OAAO,KAAK,MAAM;AAAA,MAC/B,CAAC;AACD,aAAO;AAAA,IACR;AAEA,UAAM,MAAM,aAAa,KAAK,KAAK,QAAQ,IAAI,GAAG,WAAW,QAAQ;AACrE,UAAM,WAAW,MAAM,KAAK,mBAAmB,cAAc,GAAG;AAChE,WAAO,MAAM,mDAAmD;AAAA,MAC/D,YAAY,SAAS;AAAA,MACrB,YAAY;AAAA,MACZ,WAAW;AAAA,IACZ,CAAC;AACD,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAM,mBAAmB,QAAsB,WAAsC;AACpF,UAAM,GAAG,UAAU,SAAS;AAG5B,UAAM,gBAAgB,MAAM,GAAG,cAAc,EAAE,KAAK,WAAW,WAAW,KAAK,CAAC;AAChF,eAAW,QAAQ,eAAe;AACjC,YAAM,GAAG,OAAO,KAAK,KAAK,WAAW,IAAI,CAAC;AAAA,IAC3C;AAEA,UAAM,gBAA0B,CAAC;AACjC,eAAW,CAAC,WAAW,MAAM,KAAK,OAAO,QAAQ,MAAM,GAAG;AACzD,YAAM,WAAW,KAAK,SAAS,SAAS;AACxC,YAAM,WAAW,GAAG,QAAQ;AAE5B,YAAM,mBAAmB,CAAC,OAAO,SAAS,SAAS,IAAI,gBAAgB,OAAO,WAAW,EAAE;AAC3F,UAAI,OAAO,MAAO,kBAAiB,KAAK,UAAU,OAAO,MAAM,KAAK,IAAI,CAAC,EAAE;AAC3E,uBAAiB,KAAK,UAAU,OAAO,KAAK,EAAE;AAC9C,UAAI,OAAO,MAAO,kBAAiB,KAAK,UAAU,OAAO,KAAK,EAAE;AAChE,uBAAiB,KAAK,KAAK;AAE3B,YAAM,UAAU,iBAAiB,KAAK,IAAI,IAAI,SAAS,OAAO,SAAS;AACvE,YAAM,GAAG,UAAU,KAAK,KAAK,WAAW,QAAQ,GAAG,SAAS,OAAO;AACnE,oBAAc,KAAK,QAAQ;AAAA,IAC5B;AACA,WAAO;AAAA,EACR;AACD;","names":[]}
|