@band-app/server 0.22.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/dist/client/assets/DockviewBrowserContainer-Bh7ygcym.js +5 -0
  2. package/dist/client/assets/DockviewTerminalContainer-BA10dl2w.js +2 -0
  3. package/dist/client/assets/{TerminalPanel-C4ZPrnFP.js → TerminalPanel-C40mohhY.js} +3 -3
  4. package/dist/client/assets/{_basePickBy-iyhrrxG-.js → _basePickBy-BoN5C7c3.js} +1 -1
  5. package/dist/client/assets/{_baseUniq-B1WwbMDv.js → _baseUniq-hs8Z8eGG.js} +1 -1
  6. package/dist/client/assets/{arc-DjqQ6qnK.js → arc-DStHWz7g.js} +1 -1
  7. package/dist/client/assets/{architectureDiagram-VXUJARFQ-C03XQiLa.js → architectureDiagram-VXUJARFQ-BmuwLrzR.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-VD42YOAC-Zzrf5xcb.js → blockDiagram-VD42YOAC-CpfEplz4.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-YG6GDRKO-BYA4DXcg.js → c4Diagram-YG6GDRKO-DFNXKd12.js} +1 -1
  10. package/dist/client/assets/channel-cGiKwLh2.js +1 -0
  11. package/dist/client/assets/{chunk-4BX2VUAB-CPD6ENUL.js → chunk-4BX2VUAB-BhKLwyZj.js} +1 -1
  12. package/dist/client/assets/{chunk-55IACEB6-CrLS-6CW.js → chunk-55IACEB6--1nGJwoJ.js} +1 -1
  13. package/dist/client/assets/{chunk-B4BG7PRW-CgpQP0mz.js → chunk-B4BG7PRW-DfW_4HED.js} +1 -1
  14. package/dist/client/assets/{chunk-DI55MBZ5-IOlh3km5.js → chunk-DI55MBZ5-BBLPj3y_.js} +1 -1
  15. package/dist/client/assets/{chunk-FMBD7UC4-DFsVS8Jr.js → chunk-FMBD7UC4-22_QzB6-.js} +1 -1
  16. package/dist/client/assets/{chunk-QN33PNHL-CmVDL9Gh.js → chunk-QN33PNHL-BsNBNA8p.js} +1 -1
  17. package/dist/client/assets/{chunk-QZHKN3VN-B_Cnx6JN.js → chunk-QZHKN3VN-t5QozrKy.js} +1 -1
  18. package/dist/client/assets/{chunk-TZMSLE5B-DQbyM2Dh.js → chunk-TZMSLE5B-DTbuaeiD.js} +1 -1
  19. package/dist/client/assets/classDiagram-2ON5EDUG-aEV-2-qP.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-WZHVMYZB-aEV-2-qP.js +1 -0
  21. package/dist/client/assets/clone-CArWpwXp.js +1 -0
  22. package/dist/client/assets/{cose-bilkent-S5V4N54A-CTHDgB6u.js → cose-bilkent-S5V4N54A-HZO5t4GF.js} +1 -1
  23. package/dist/client/assets/{dagre-6UL2VRFP-UZkfCyUE.js → dagre-6UL2VRFP-DnOsaGGD.js} +1 -1
  24. package/dist/client/assets/{diagram-PSM6KHXK-DAlkSZ2c.js → diagram-PSM6KHXK-tirWXx7b.js} +1 -1
  25. package/dist/client/assets/{diagram-QEK2KX5R-CazlpGGg.js → diagram-QEK2KX5R-Cjtr8l3E.js} +1 -1
  26. package/dist/client/assets/{diagram-S2PKOQOG-COwMJUec.js → diagram-S2PKOQOG-CuNpvzLc.js} +1 -1
  27. package/dist/client/assets/{erDiagram-Q2GNP2WA-CXZvqia8.js → erDiagram-Q2GNP2WA-D2Rb5UvQ.js} +1 -1
  28. package/dist/client/assets/{flowDiagram-NV44I4VS-DA3lEpzG.js → flowDiagram-NV44I4VS-BSQxdSDJ.js} +1 -1
  29. package/dist/client/assets/{ganttDiagram-JELNMOA3-BWRgS4MP.js → ganttDiagram-JELNMOA3-Cj0PWn4F.js} +3 -3
  30. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-7FizCSrq.js → gitGraphDiagram-V2S2FVAM-DMoH-grQ.js} +1 -1
  31. package/dist/client/assets/{graph-4L_GoTFH.js → graph-B7ABrrXm.js} +1 -1
  32. package/dist/client/assets/{highlighted-body-B3W2YXNL-ydRS8Ic9.js → highlighted-body-B3W2YXNL-DCQslkUR.js} +1 -1
  33. package/dist/client/assets/{index-BgKMJy37.js → index-8PaDaRYT.js} +1 -1
  34. package/dist/client/assets/{index-Bq6PEMRy.js → index-9FCRbBun.js} +1 -1
  35. package/dist/client/assets/{index-DJqbRWRD.js → index-B22f7bFn.js} +1 -1
  36. package/dist/client/assets/{index-Bs4eGT35.js → index-BCA8lija.js} +1 -1
  37. package/dist/client/assets/{index-BaTM0g6E.js → index-BG3Ltnuv.js} +1 -1
  38. package/dist/client/assets/index-BQhRobL8.js +1 -0
  39. package/dist/client/assets/{index-Cp1FqGEW.js → index-BaT5I2xy.js} +1 -1
  40. package/dist/client/assets/{index-Csd34_1g.js → index-BsEwdsSv.js} +1 -1
  41. package/dist/client/assets/{index-B8VQmYG-.js → index-C99EKoUY.js} +1 -1
  42. package/dist/client/assets/{index-D2ogHyak.js → index-CBLjtUwT.js} +1 -1
  43. package/dist/client/assets/{index-C6FACjGj.js → index-COql1I_y.js} +1 -1
  44. package/dist/client/assets/{index-Cl0dKOpc.js → index-D9SknX6B.js} +1 -1
  45. package/dist/client/assets/{index-CPC-pCRk.js → index-DWj9bxNA.js} +1 -1
  46. package/dist/client/assets/{index--PCwWsYS.js → index-DWqvtyLc.js} +1 -1
  47. package/dist/client/assets/{index-DScY4DVi.js → index-DaWbWCgj.js} +1 -1
  48. package/dist/client/assets/{index-qf4lR_zM.js → index-Diyv48F3.js} +1 -1
  49. package/dist/client/assets/{index-SJ6t3qme.js → index-DjFlwM8l.js} +1 -1
  50. package/dist/client/assets/{index-DTonRA2E.js → index-Myu-_U8q.js} +1 -1
  51. package/dist/client/assets/{infoDiagram-HS3SLOUP-CB9FyKi7.js → infoDiagram-HS3SLOUP-C_wVpnnp.js} +1 -1
  52. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-C_bPulxt.js → journeyDiagram-XKPGCS4Q-DcF--XQH.js} +1 -1
  53. package/dist/client/assets/{kanban-definition-3W4ZIXB7-CGLwqWR-.js → kanban-definition-3W4ZIXB7-BA1w8rep.js} +1 -1
  54. package/dist/client/assets/{layout-XjqfGmSW.js → layout-DVMDYrln.js} +1 -1
  55. package/dist/client/assets/{main-FwGkrDro.js → main-B6t1j7Kr.js} +231 -231
  56. package/dist/client/assets/main-i-GTiqUd.css +1 -0
  57. package/dist/client/assets/{mindmap-definition-VGOIOE7T-DRNRxvpy.js → mindmap-definition-VGOIOE7T-C1vA0wr2.js} +1 -1
  58. package/dist/client/assets/{pieDiagram-ADFJNKIX-Co4AML3R.js → pieDiagram-ADFJNKIX-Q71p26az.js} +2 -2
  59. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-DjuSOXov.js → quadrantDiagram-AYHSOK5B-Bxcd0mzk.js} +1 -1
  60. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-Cl5py0JI.js → requirementDiagram-UZGBJVZJ-DWqCIKiG.js} +1 -1
  61. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-BNJImcEG.js → sankeyDiagram-TZEHDZUN-D9rSnLVX.js} +1 -1
  62. package/dist/client/assets/{sequenceDiagram-WL72ISMW-Bd3PTcpW.js → sequenceDiagram-WL72ISMW-Co2Jz6Fl.js} +1 -1
  63. package/dist/client/assets/{square-terminal-CiX1sbUO.js → square-terminal-C3zI_mkt.js} +1 -1
  64. package/dist/client/assets/{stateDiagram-FKZM4ZOC-DXdFd6-L.js → stateDiagram-FKZM4ZOC-CXLDkeLY.js} +1 -1
  65. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-R8LzGctw.js +1 -0
  66. package/dist/client/assets/{timeline-definition-IT6M3QCI-8CA5Ftj2.js → timeline-definition-IT6M3QCI-BXxZZYsm.js} +1 -1
  67. package/dist/client/assets/{treemap-GDKQZRPO-GQ5N0K_o.js → treemap-GDKQZRPO-BgMoU0kM.js} +1 -1
  68. package/dist/client/assets/workspace._workspaceId-Bww_ZNFK.js +2 -0
  69. package/dist/client/assets/{workspace._workspaceId-D0sPlrId.js → workspace._workspaceId-C_KGLGyB.js} +1 -1
  70. package/dist/client/assets/{xychartDiagram-PRI3JC2R-DzcmFrfB.js → xychartDiagram-PRI3JC2R-BQxVaOKh.js} +1 -1
  71. package/dist/migrations/20260703151516_add_worktree_name/migration.sql +2 -0
  72. package/dist/migrations/20260703151516_add_worktree_name/snapshot.json +1167 -0
  73. package/dist/openapi.json +184 -16
  74. package/dist/server/assets/{DockviewBrowserContainer-DvltiWxV.js → DockviewBrowserContainer-C6QVux14.js} +16 -3
  75. package/dist/server/assets/{DockviewTerminalContainer-YGo8Zbx1.js → DockviewTerminalContainer-OevWE65L.js} +29 -6
  76. package/dist/server/assets/{TerminalPanel-Bd0_i38P.js → TerminalPanel-BhOjwcFW.js} +3 -2
  77. package/dist/server/assets/{_basePickBy-BBas4T8q.js → _basePickBy-DVK5KtlH.js} +2 -2
  78. package/dist/server/assets/{_baseUniq-Bb-AXRqu.js → _baseUniq-DSFYYhGd.js} +1 -1
  79. package/dist/server/assets/_tanstack-start-manifest_v-C_7Mj4aJ.js +4 -0
  80. package/dist/server/assets/{arc-CNbGanI8.js → arc-BpwEbxUR.js} +1 -1
  81. package/dist/server/assets/{architecture-7HQA4BMR-BBpvCcgY.js → architecture-7HQA4BMR-CNyHLOO7.js} +6 -6
  82. package/dist/server/assets/{architectureDiagram-VXUJARFQ-CSgRy1oF.js → architectureDiagram-VXUJARFQ-DVUpIskI.js} +6 -6
  83. package/dist/server/assets/{blockDiagram-VD42YOAC-BZ551zIx.js → blockDiagram-VD42YOAC-CRv2pc0L.js} +6 -6
  84. package/dist/server/assets/{c4Diagram-YG6GDRKO-BpFPiRxu.js → c4Diagram-YG6GDRKO-CBv74bWb.js} +2 -2
  85. package/dist/server/assets/{channel-BakvXn0q.js → channel-C_c7u4ky.js} +1 -1
  86. package/dist/server/assets/{chunk-4BX2VUAB-iq_ixzMT.js → chunk-4BX2VUAB-85OXnz_P.js} +1 -1
  87. package/dist/server/assets/{chunk-55IACEB6-BTsLLiUt.js → chunk-55IACEB6-Cl8taExZ.js} +1 -1
  88. package/dist/server/assets/{chunk-B4BG7PRW-rFWSSos9.js → chunk-B4BG7PRW-C7W_R9n6.js} +4 -4
  89. package/dist/server/assets/{chunk-DI55MBZ5-C6HYpEOk.js → chunk-DI55MBZ5-CTi30KuT.js} +3 -3
  90. package/dist/server/assets/{chunk-FMBD7UC4-CWm7G-kI.js → chunk-FMBD7UC4-CsuoPD3I.js} +1 -1
  91. package/dist/server/assets/{chunk-QN33PNHL-C-sH07qa.js → chunk-QN33PNHL-BHHMj_a1.js} +1 -1
  92. package/dist/server/assets/{chunk-QZHKN3VN-DBYpRTmd.js → chunk-QZHKN3VN-DwwXlOCl.js} +1 -1
  93. package/dist/server/assets/{chunk-TZMSLE5B-D374mW8S.js → chunk-TZMSLE5B-ECyN9wrL.js} +1 -1
  94. package/dist/server/assets/{classDiagram-v2-WZHVMYZB-DV-SD-4W.js → classDiagram-2ON5EDUG-qbF8ds74.js} +5 -5
  95. package/dist/server/assets/{classDiagram-2ON5EDUG-DV-SD-4W.js → classDiagram-v2-WZHVMYZB-qbF8ds74.js} +5 -5
  96. package/dist/server/assets/{clone-DVtsQqal.js → clone-BCajbdd5.js} +1 -1
  97. package/dist/server/assets/{cose-bilkent-S5V4N54A-XbCluv3z.js → cose-bilkent-S5V4N54A-D5-w_t4l.js} +1 -1
  98. package/dist/server/assets/{dagre-6UL2VRFP-CuR4BisU.js → dagre-6UL2VRFP-CCIdAwdB.js} +6 -6
  99. package/dist/server/assets/{diagram-PSM6KHXK-CV_nySOq.js → diagram-PSM6KHXK-CWGITxy9.js} +7 -7
  100. package/dist/server/assets/{diagram-QEK2KX5R-Noar7MQT.js → diagram-QEK2KX5R-B07zrGgY.js} +6 -6
  101. package/dist/server/assets/{diagram-S2PKOQOG-B2BacNFz.js → diagram-S2PKOQOG-XGIpbjo1.js} +6 -6
  102. package/dist/server/assets/{erDiagram-Q2GNP2WA-B5Os4Fa-.js → erDiagram-Q2GNP2WA-DYHtO3j9.js} +4 -4
  103. package/dist/server/assets/{flowDiagram-NV44I4VS-DjQR68un.js → flowDiagram-NV44I4VS-Cs7hS9X4.js} +5 -5
  104. package/dist/server/assets/{ganttDiagram-JELNMOA3-B5uPZ6pu.js → ganttDiagram-JELNMOA3-BhLp8xvm.js} +1 -1
  105. package/dist/server/assets/{gitGraph-G5XIXVHT-6ZMiJWQT.js → gitGraph-G5XIXVHT-B46gW1OX.js} +6 -6
  106. package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-DDF08l5z.js → gitGraphDiagram-V2S2FVAM-CZHNGOm0.js} +7 -7
  107. package/dist/server/assets/{graph-bRh_VJvO.js → graph-4bVECaJM.js} +2 -2
  108. package/dist/server/assets/{highlighted-body-B3W2YXNL-BI_Gmrii.js → highlighted-body-B3W2YXNL-DSf8s2aV.js} +1 -1
  109. package/dist/server/assets/{index-Bdft7sx8.js → index-14dCbIAi.js} +5 -5
  110. package/dist/server/assets/{index-Dyd5DTki.js → index-1OK7lyTa.js} +2 -2
  111. package/dist/server/assets/{index-y2Y1JSaD.js → index-8EiXP0Bf.js} +2 -2
  112. package/dist/server/assets/{index-BlZ00-BN.js → index-B72BPMJQ.js} +3 -3
  113. package/dist/server/assets/{index-K_Bo1J5h.js → index-BLv-1MtR.js} +5 -5
  114. package/dist/server/assets/{index-auM21h5r.js → index-BRzkEVRG.js} +1 -1
  115. package/dist/server/assets/{index-BKTDd3Bk.js → index-C7lRWZi8.js} +4 -4
  116. package/dist/server/assets/{index-VS9oMvxO.js → index-CDG7KvBY.js} +2 -2
  117. package/dist/server/assets/{index-C-y9iHQ0.js → index-CHvqm6Lz.js} +5 -5
  118. package/dist/server/assets/{index-CWdeYFNF.js → index-CKPuU6Za.js} +2 -2
  119. package/dist/server/assets/{index-RnzJqolD.js → index-CWr-Kh5M.js} +2 -2
  120. package/dist/server/assets/{index-D2pPyR7I.js → index-D2uLA4oe.js} +2 -2
  121. package/dist/server/assets/{index-DDZbXJFy.js → index-DAq8fRkd.js} +2 -2
  122. package/dist/server/assets/{index-5xKUZpsF.js → index-Dz2mzfvS.js} +2 -2
  123. package/dist/server/assets/{index-6TVwGkMb.js → index-Tq3ajWxh.js} +2 -2
  124. package/dist/server/assets/{index-DpTDX5JD.js → index-U3tOcUUV.js} +2 -2
  125. package/dist/server/assets/{index-CTIw5jsP.js → index-pFRKwTv2.js} +2 -2
  126. package/dist/server/assets/{index-CUQ92e7X.js → index-rT9xGtRW.js} +3 -3
  127. package/dist/server/assets/{info-VBDWY6EO-JLouBLo5.js → info-VBDWY6EO-DrELfFR0.js} +6 -6
  128. package/dist/server/assets/{infoDiagram-HS3SLOUP-zmvy_WJR.js → infoDiagram-HS3SLOUP-D40Crb-p.js} +5 -5
  129. package/dist/server/assets/{journeyDiagram-XKPGCS4Q-DyzviNdt.js → journeyDiagram-XKPGCS4Q-dtlVBwV2.js} +4 -4
  130. package/dist/server/assets/{kanban-definition-3W4ZIXB7-DOBL7QMj.js → kanban-definition-3W4ZIXB7-72vgA7Jl.js} +2 -2
  131. package/dist/server/assets/{layout-B_Ylwhz8.js → layout-DJ0Eul-X.js} +4 -4
  132. package/dist/server/assets/{mermaid-3ZIDBTTL-D1krx3WU.js → mermaid-3ZIDBTTL-DGEHf_at.js} +1 -1
  133. package/dist/server/assets/{mermaid-parser.core-B3d8rAVm.js → mermaid-parser.core-C1UfVEF8.js} +11 -11
  134. package/dist/server/assets/{mindmap-definition-VGOIOE7T-Kacyqp9Z.js → mindmap-definition-VGOIOE7T-DYfEp2uH.js} +3 -3
  135. package/dist/server/assets/{packet-DYOGHKS2-Bl6AuzeP.js → packet-DYOGHKS2-IHYchS32.js} +6 -6
  136. package/dist/server/assets/{pie-VRWISCQL-DTulKqSB.js → pie-VRWISCQL-R6SvOU4g.js} +6 -6
  137. package/dist/server/assets/{pieDiagram-ADFJNKIX-EBslGQgI.js → pieDiagram-ADFJNKIX-EgffZsud.js} +7 -7
  138. package/dist/server/assets/{quadrantDiagram-AYHSOK5B-BKSWYe6P.js → quadrantDiagram-AYHSOK5B-n2oJWllV.js} +1 -1
  139. package/dist/server/assets/{radar-ZZBFDIW7-C5ulLYDn.js → radar-ZZBFDIW7-BX2ya_Na.js} +6 -6
  140. package/dist/server/assets/{requirementDiagram-UZGBJVZJ-B7nRcnKx.js → requirementDiagram-UZGBJVZJ-CzCXruFj.js} +3 -3
  141. package/dist/server/assets/{router-hdCv0b-L.js → router-BC8bCsa3.js} +1100 -725
  142. package/dist/server/assets/{sankeyDiagram-TZEHDZUN-Dq6Q_X6w.js → sankeyDiagram-TZEHDZUN-C0GqwqSS.js} +1 -1
  143. package/dist/server/assets/{sequenceDiagram-WL72ISMW-CDfofz-s.js → sequenceDiagram-WL72ISMW-BfX0R0LP.js} +3 -3
  144. package/dist/server/assets/{square-terminal-D7R89vxW.js → square-terminal-BWcJU95Z.js} +1 -1
  145. package/dist/server/assets/{stateDiagram-FKZM4ZOC-BQdH_sw5.js → stateDiagram-FKZM4ZOC-QowlLVwh.js} +8 -8
  146. package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-BTwyLH9n.js → stateDiagram-v2-4FDKWEC3-DVHzQlOF.js} +4 -4
  147. package/dist/server/assets/{timeline-definition-IT6M3QCI-BLfNWXx-.js → timeline-definition-IT6M3QCI-DUoaC7rz.js} +2 -2
  148. package/dist/server/assets/{treemap-GDKQZRPO-DYGhrk03.js → treemap-GDKQZRPO-B5KIzomx.js} +6 -6
  149. package/dist/server/assets/{workspace._workspaceId-C9ijioXa.js → workspace._workspaceId-DRK2dblR.js} +101 -11
  150. package/dist/server/assets/{workspace._workspaceId-BrMajMrS.js → workspace._workspaceId-hnIpuUNX.js} +1 -1
  151. package/dist/server/assets/{xychartDiagram-PRI3JC2R-CTiLODEl.js → xychartDiagram-PRI3JC2R-aNxYxejD.js} +1 -1
  152. package/dist/server/server.js +2 -2
  153. package/dist/start-server.mjs +736 -512
  154. package/package.json +4 -4
  155. package/dist/client/assets/DockviewBrowserContainer-AeGrBvbe.js +0 -5
  156. package/dist/client/assets/DockviewTerminalContainer-CEcmk81d.js +0 -2
  157. package/dist/client/assets/channel-ByfqtAS4.js +0 -1
  158. package/dist/client/assets/classDiagram-2ON5EDUG-CmzSv5tz.js +0 -1
  159. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CmzSv5tz.js +0 -1
  160. package/dist/client/assets/clone-D6Np9jJP.js +0 -1
  161. package/dist/client/assets/index-p4yr3DW9.js +0 -1
  162. package/dist/client/assets/main-CBlP-xQr.css +0 -1
  163. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-kbB9WbNB.js +0 -1
  164. package/dist/client/assets/workspace._workspaceId-C_iuy4p6.js +0 -2
  165. package/dist/server/assets/_tanstack-start-manifest_v-DJ7xH6AI.js +0 -4
@@ -6501,11 +6501,11 @@ var require_tools = __commonJS({
6501
6501
  }
6502
6502
  }
6503
6503
  }
6504
- function buildFormatters(level, bindings, log46) {
6504
+ function buildFormatters(level, bindings, log47) {
6505
6505
  return {
6506
6506
  level,
6507
6507
  bindings,
6508
- log: log46
6508
+ log: log47
6509
6509
  };
6510
6510
  }
6511
6511
  function normalizeDestFileDescriptor(destination) {
@@ -6888,11 +6888,11 @@ var require_proto = __commonJS({
6888
6888
  }
6889
6889
  } else instance[serializersSym] = serializers;
6890
6890
  if (options2.hasOwnProperty("formatters")) {
6891
- const { level, bindings: chindings, log: log46 } = options2.formatters;
6891
+ const { level, bindings: chindings, log: log47 } = options2.formatters;
6892
6892
  instance[formattersSym] = buildFormatters(
6893
6893
  level || formatters.level,
6894
6894
  chindings || resetChildingsFormatter,
6895
- log46 || formatters.log
6895
+ log47 || formatters.log
6896
6896
  );
6897
6897
  } else {
6898
6898
  instance[formattersSym] = buildFormatters(
@@ -30213,7 +30213,7 @@ var init_claude_code = __esm({
30213
30213
  }
30214
30214
  }
30215
30215
  async listSessions(dir) {
30216
- log2.info({ dir }, "listSessions");
30216
+ log2.debug({ dir }, "listSessions");
30217
30217
  const sessions = await c7$({ dir });
30218
30218
  const filtered = sessions.filter((s6) => s6.cwd === dir);
30219
30219
  const lastPrompts = await Promise.all(
@@ -32358,7 +32358,7 @@ var init_codex = __esm({
32358
32358
  };
32359
32359
  }
32360
32360
  async listSessions(dir) {
32361
- log4.info({ dir }, "listSessions");
32361
+ log4.debug({ dir }, "listSessions");
32362
32362
  const sessions = await readCodexSessions();
32363
32363
  return sessions.filter((s6) => s6.cwd === dir).sort((a6, b10) => b10.lastModified - a6.lastModified);
32364
32364
  }
@@ -33244,7 +33244,7 @@ var init_opencode = __esm({
33244
33244
  }
33245
33245
  async listSessions(dir) {
33246
33246
  const sessions = await fetchOpenCodeSessions(this.executablePath, dir);
33247
- log6.info({ dir, count: sessions.length }, "listSessions");
33247
+ log6.debug({ dir, count: sessions.length }, "listSessions");
33248
33248
  return sessions.map((s6) => ({
33249
33249
  sessionId: s6.id,
33250
33250
  summary: s6.title || "Untitled session",
@@ -87212,11 +87212,11 @@ var require_core = __commonJS({
87212
87212
  Ajv2.ValidationError = validation_error_1.default;
87213
87213
  Ajv2.MissingRefError = ref_error_1.default;
87214
87214
  exports.default = Ajv2;
87215
- function checkOptions(checkOpts, options2, msg, log46 = "error") {
87215
+ function checkOptions(checkOpts, options2, msg, log47 = "error") {
87216
87216
  for (const key in checkOpts) {
87217
87217
  const opt = key;
87218
87218
  if (opt in options2)
87219
- this.logger[log46](`${msg}: option ${key}. ${checkOpts[opt]}`);
87219
+ this.logger[log47](`${msg}: option ${key}. ${checkOpts[opt]}`);
87220
87220
  }
87221
87221
  }
87222
87222
  function getSchEnv(keyRef) {
@@ -101797,6 +101797,16 @@ var projects = sqliteTable("projects", {
101797
101797
  var worktrees = sqliteTable("worktrees", {
101798
101798
  id: integer2("id").primaryKey({ autoIncrement: true }),
101799
101799
  projectName: text2("project_name").notNull().references(() => projects.name, { onDelete: "cascade" }),
101800
+ // Immutable workspace identity, set once at creation to the (slugified)
101801
+ // branch name. The workspace id is derived from this (`toWorkspaceId`),
101802
+ // NOT from `branch` — so switching the git branch inside the worktree
101803
+ // doesn't change the id (and everything keyed by it) or the projects-list
101804
+ // label. Sync updates `branch` to track git; it never touches `name`.
101805
+ // Backfilled to `branch` for pre-existing rows by the migration.
101806
+ name: text2("name").notNull(),
101807
+ // Live git branch checked out in the worktree. Reconciled against git by
101808
+ // `syncWorktrees` and used as the target of git operations. Distinct from
101809
+ // `name` above once the branch is switched.
101800
101810
  branch: text2("branch").notNull(),
101801
101811
  path: text2("path").notNull(),
101802
101812
  head: text2("head"),
@@ -102529,16 +102539,89 @@ function listenerCount() {
102529
102539
  // src/server/infra/setup/setup-runner.ts
102530
102540
  import { spawn as spawn5 } from "node:child_process";
102531
102541
 
102542
+ // src/server/infra/process/path.ts
102543
+ import { execFile as execFile3 } from "node:child_process";
102544
+ import { existsSync as existsSync4 } from "node:fs";
102545
+ import { delimiter } from "node:path";
102546
+ function defaultShell() {
102547
+ if (process.env.SHELL) return process.env.SHELL;
102548
+ if (process.platform === "win32") return process.env.ComSpec || "cmd.exe";
102549
+ for (const candidate of ["/bin/zsh", "/bin/bash", "/bin/sh"]) {
102550
+ if (existsSync4(candidate)) return candidate;
102551
+ }
102552
+ return "/bin/sh";
102553
+ }
102554
+ var cachedBinDirs = null;
102555
+ function extraBinDirs() {
102556
+ if (cachedBinDirs) return cachedBinDirs;
102557
+ if (process.platform === "darwin") {
102558
+ cachedBinDirs = ["/opt/homebrew/bin", "/usr/local/bin"];
102559
+ } else if (process.platform === "linux") {
102560
+ const dirs = [];
102561
+ const linuxbrew = "/home/linuxbrew/.linuxbrew/bin";
102562
+ if (existsSync4(linuxbrew)) dirs.push(linuxbrew);
102563
+ dirs.push("/usr/local/bin");
102564
+ cachedBinDirs = dirs;
102565
+ } else {
102566
+ cachedBinDirs = [];
102567
+ }
102568
+ return cachedBinDirs;
102569
+ }
102570
+ function prependBinDirs(path3) {
102571
+ return [...extraBinDirs(), ...path3 ? [path3] : []].join(delimiter);
102572
+ }
102573
+ var cachedShellPath = null;
102574
+ async function shellPath() {
102575
+ if (cachedShellPath) return cachedShellPath;
102576
+ const shell = defaultShell();
102577
+ try {
102578
+ const result = await new Promise((resolve12, reject) => {
102579
+ execFile3(shell, ["-li", "-c", "echo $PATH"], { timeout: 5e3 }, (err, stdout) => {
102580
+ if (err) {
102581
+ reject(err);
102582
+ return;
102583
+ }
102584
+ resolve12(stdout.trim());
102585
+ });
102586
+ });
102587
+ if (result) {
102588
+ cachedShellPath = result;
102589
+ return result;
102590
+ }
102591
+ } catch {
102592
+ }
102593
+ const fallback = prependBinDirs(process.env.PATH);
102594
+ cachedShellPath = fallback;
102595
+ return fallback;
102596
+ }
102597
+ async function whichBinary(name3) {
102598
+ const resolvedPath = await shellPath();
102599
+ try {
102600
+ const result = await new Promise((resolve12, reject) => {
102601
+ execFile3("which", [name3], { env: { ...process.env, PATH: resolvedPath } }, (err, stdout) => {
102602
+ if (err) {
102603
+ reject(err);
102604
+ return;
102605
+ }
102606
+ resolve12(stdout.trim());
102607
+ });
102608
+ });
102609
+ return result || null;
102610
+ } catch {
102611
+ return null;
102612
+ }
102613
+ }
102614
+
102532
102615
  // src/server/infra/setup/project-config.ts
102533
102616
  init_src();
102534
102617
  init_zod();
102535
- import { existsSync as existsSync4, readFileSync as readFileSync6 } from "node:fs";
102618
+ import { existsSync as existsSync5, readFileSync as readFileSync6 } from "node:fs";
102536
102619
  import { join as join14 } from "node:path";
102537
102620
  var log10 = createLogger("project-config");
102538
102621
  function loadProjectConfig(worktreePath, projectPath) {
102539
102622
  for (const base2 of [worktreePath, projectPath]) {
102540
102623
  const configPath = join14(base2, ".band", "config.json");
102541
- if (existsSync4(configPath)) {
102624
+ if (existsSync5(configPath)) {
102542
102625
  try {
102543
102626
  return JSON.parse(readFileSync6(configPath, "utf-8"));
102544
102627
  } catch {
@@ -102550,7 +102633,7 @@ function loadProjectConfig(worktreePath, projectPath) {
102550
102633
  var CopyFilesSchema = external_exports.array(external_exports.string()).optional();
102551
102634
  function getCopyFiles(projectPath) {
102552
102635
  const configPath = join14(projectPath, ".band", "config.json");
102553
- if (!existsSync4(configPath)) return null;
102636
+ if (!existsSync5(configPath)) return null;
102554
102637
  let raw;
102555
102638
  try {
102556
102639
  raw = JSON.parse(readFileSync6(configPath, "utf-8"));
@@ -102589,7 +102672,7 @@ function runSetup(workspaceId, worktreePath, projectPath, onComplete) {
102589
102672
  cwd: worktreePath,
102590
102673
  env: {
102591
102674
  ...parentEnv,
102592
- PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`
102675
+ PATH: prependBinDirs(process.env.PATH)
102593
102676
  },
102594
102677
  stdio: ["ignore", "pipe", "pipe"]
102595
102678
  });
@@ -111512,11 +111595,27 @@ function DialogOverlay2({
111512
111595
  }
111513
111596
  );
111514
111597
  }
111598
+ var DIALOG_CONTENT_VARIANTS = {
111599
+ default: "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
111600
+ "bottom-sheet": [
111601
+ // Shared
111602
+ "fixed z-50 flex flex-col bg-background shadow-lg duration-200 outline-none",
111603
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:animate-in data-[state=open]:fade-in-0",
111604
+ // Mobile (< lg): bottom drawer
111605
+ "inset-x-0 bottom-0 w-full max-w-none rounded-t-2xl border border-b-0 p-6",
111606
+ "max-h-[calc(100dvh-env(safe-area-inset-top)-1.5rem)]",
111607
+ "max-lg:data-[state=open]:slide-in-from-bottom max-lg:data-[state=closed]:slide-out-to-bottom",
111608
+ // Desktop (lg+): revert to the centred modal
111609
+ "lg:inset-auto lg:top-[50%] lg:left-[50%] lg:bottom-auto lg:w-full lg:max-w-lg lg:max-h-[85vh] lg:translate-x-[-50%] lg:translate-y-[-50%] lg:rounded-lg lg:border-b",
111610
+ "lg:data-[state=open]:zoom-in-95 lg:data-[state=closed]:zoom-out-95"
111611
+ ].join(" ")
111612
+ };
111515
111613
  function DialogContent2({
111516
111614
  className,
111517
111615
  overlayClassName,
111518
111616
  children,
111519
111617
  showCloseButton = true,
111618
+ variant = "default",
111520
111619
  ...props
111521
111620
  }) {
111522
111621
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(DialogPortal2, { "data-slot": "dialog-portal", children: [
@@ -111525,10 +111624,8 @@ function DialogContent2({
111525
111624
  dist_exports2.Content,
111526
111625
  {
111527
111626
  "data-slot": "dialog-content",
111528
- className: cn(
111529
- "fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg duration-200 outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 sm:max-w-lg",
111530
- className
111531
- ),
111627
+ "data-variant": variant,
111628
+ className: cn(DIALOG_CONTENT_VARIANTS[variant], className),
111532
111629
  ...props,
111533
111630
  children: [
111534
111631
  children,
@@ -111698,19 +111795,22 @@ var import_jsx_runtime37 = __toESM(require_jsx_runtime(), 1);
111698
111795
  // ../../packages/ui/src/components/select.tsx
111699
111796
  var import_jsx_runtime38 = __toESM(require_jsx_runtime(), 1);
111700
111797
 
111701
- // ../../packages/ui/src/components/spinner.tsx
111798
+ // ../../packages/ui/src/components/sheet.tsx
111702
111799
  var import_jsx_runtime39 = __toESM(require_jsx_runtime(), 1);
111703
111800
 
111704
- // ../../packages/ui/src/components/switch.tsx
111801
+ // ../../packages/ui/src/components/spinner.tsx
111705
111802
  var import_jsx_runtime40 = __toESM(require_jsx_runtime(), 1);
111706
111803
 
111707
- // ../../packages/ui/src/components/tooltip.tsx
111804
+ // ../../packages/ui/src/components/switch.tsx
111708
111805
  var import_jsx_runtime41 = __toESM(require_jsx_runtime(), 1);
111806
+
111807
+ // ../../packages/ui/src/components/tooltip.tsx
111808
+ var import_jsx_runtime42 = __toESM(require_jsx_runtime(), 1);
111709
111809
  function Tooltip2({ ...props }) {
111710
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(dist_exports8.Root, { "data-slot": "tooltip", ...props });
111810
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(dist_exports8.Root, { "data-slot": "tooltip", ...props });
111711
111811
  }
111712
111812
  function TooltipTrigger2({ ...props }) {
111713
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(dist_exports8.Trigger, { "data-slot": "tooltip-trigger", ...props });
111813
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(dist_exports8.Trigger, { "data-slot": "tooltip-trigger", ...props });
111714
111814
  }
111715
111815
  function TooltipContent2({
111716
111816
  className,
@@ -111718,7 +111818,7 @@ function TooltipContent2({
111718
111818
  children,
111719
111819
  ...props
111720
111820
  }) {
111721
- return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(dist_exports8.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
111821
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(dist_exports8.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(
111722
111822
  dist_exports8.Content,
111723
111823
  {
111724
111824
  "data-slot": "tooltip-content",
@@ -111730,7 +111830,7 @@ function TooltipContent2({
111730
111830
  ...props,
111731
111831
  children: [
111732
111832
  children,
111733
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(dist_exports8.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
111833
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(dist_exports8.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" })
111734
111834
  ]
111735
111835
  }
111736
111836
  ) });
@@ -113873,7 +113973,7 @@ var QueryClient = class {
113873
113973
 
113874
113974
  // ../../node_modules/.pnpm/@tanstack+react-query@5.90.21_react@19.2.4/node_modules/@tanstack/react-query/build/modern/QueryClientProvider.js
113875
113975
  var React31 = __toESM(require_react(), 1);
113876
- var import_jsx_runtime42 = __toESM(require_jsx_runtime(), 1);
113976
+ var import_jsx_runtime43 = __toESM(require_jsx_runtime(), 1);
113877
113977
  var QueryClientContext = React31.createContext(
113878
113978
  void 0
113879
113979
  );
@@ -113953,7 +114053,7 @@ function useRawDashboardStore() {
113953
114053
  }
113954
114054
 
113955
114055
  // src/dashboard/context.tsx
113956
- var import_jsx_runtime43 = __toESM(require_jsx_runtime(), 1);
114056
+ var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
113957
114057
  var DashboardContext = (0, import_react5.createContext)(null);
113958
114058
  function useAdapter() {
113959
114059
  const ctx = (0, import_react5.useContext)(DashboardContext);
@@ -113979,15 +114079,18 @@ function useRemoveWorkspace() {
113979
114079
  const openWorkspace = useDashboardStore((s6) => s6.openWorkspace);
113980
114080
  const store2 = useRawDashboardStore();
113981
114081
  return useMutation({
113982
- mutationFn: ({ project, branch }) => adapter.removeWorkspace(project, branch),
113983
- onSuccess: (_data, { project, branch }) => {
114082
+ mutationFn: ({ project, name: name3 }) => adapter.removeWorkspace(project, name3),
114083
+ onSuccess: (_data, { project, name: name3 }) => {
113984
114084
  queryClient2.invalidateQueries({ queryKey: queryKeys.projects });
113985
- const deletedWorkspaceId = toWorkspaceId(project, branch);
114085
+ const deletedWorkspaceId = toWorkspaceId(project, name3);
113986
114086
  if (store2.getState().activeWorkspaceId === deletedWorkspaceId) {
113987
114087
  const projects2 = queryClient2.getQueryData(queryKeys.projects);
113988
114088
  const projectInfo = projects2?.find((p6) => p6.name === project);
113989
114089
  if (projectInfo) {
113990
- openWorkspace(toWorkspaceId(project, projectInfo.defaultBranch));
114090
+ const mainWt = projectInfo.worktrees.find(
114091
+ (wt) => wt.name === projectInfo.defaultBranch || wt.branch === projectInfo.defaultBranch
114092
+ );
114093
+ openWorkspace(toWorkspaceId(project, mainWt?.name ?? projectInfo.defaultBranch));
113991
114094
  }
113992
114095
  }
113993
114096
  },
@@ -113998,14 +114101,14 @@ function useRemoveWorkspace() {
113998
114101
  }
113999
114102
 
114000
114103
  // src/dashboard/components/AddProjectDialog.tsx
114001
- var import_jsx_runtime44 = __toESM(require_jsx_runtime(), 1);
114104
+ var import_jsx_runtime45 = __toESM(require_jsx_runtime(), 1);
114002
114105
 
114003
114106
  // src/dashboard/components/AgentStatusIndicator.tsx
114004
114107
  var import_lucide_react2 = __toESM(require_lucide_react(), 1);
114005
- var import_jsx_runtime45 = __toESM(require_jsx_runtime(), 1);
114108
+ var import_jsx_runtime46 = __toESM(require_jsx_runtime(), 1);
114006
114109
  function AgentStatusIndicator({ agent, isActive }) {
114007
114110
  if (!agent || agent.status !== "working" && agent.status !== "needs_attention") {
114008
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
114111
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
114009
114112
  import_lucide_react2.GitBranch,
114010
114113
  {
114011
114114
  className: `size-3 shrink-0 ${isActive ? "text-primary" : "text-muted-foreground"}`
@@ -114016,18 +114119,18 @@ function AgentStatusIndicator({ agent, isActive }) {
114016
114119
  const color = isWorking ? "bg-status-working" : "bg-status-needs-attention";
114017
114120
  const tooltip = isWorking ? "Agent running..." : "Needs your attention";
114018
114121
  const animation = isWorking ? "" : "animate-status-pulse";
114019
- return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(Tooltip2, { children: [
114020
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: `inline-block size-2 shrink-0 rounded-full ${color} ${animation}` }) }),
114021
- /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TooltipContent2, { side: "top", children: tooltip })
114122
+ return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(Tooltip2, { children: [
114123
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: `inline-block size-2 shrink-0 rounded-full ${color} ${animation}` }) }),
114124
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(TooltipContent2, { side: "top", children: tooltip })
114022
114125
  ] });
114023
114126
  }
114024
114127
 
114025
114128
  // src/dashboard/components/agent-icons.tsx
114026
- var import_jsx_runtime46 = __toESM(require_jsx_runtime(), 1);
114129
+ var import_jsx_runtime47 = __toESM(require_jsx_runtime(), 1);
114027
114130
 
114028
114131
  // src/dashboard/components/CIStatusIndicator.tsx
114029
114132
  var import_lucide_react3 = __toESM(require_lucide_react(), 1);
114030
- var import_jsx_runtime47 = __toESM(require_jsx_runtime(), 1);
114133
+ var import_jsx_runtime48 = __toESM(require_jsx_runtime(), 1);
114031
114134
  function CIStatusIndicator({ ci }) {
114032
114135
  const capabilities = useCapabilities();
114033
114136
  const handleOpenUrl = (url, e2) => {
@@ -114037,63 +114140,63 @@ function CIStatusIndicator({ ci }) {
114037
114140
  const clickable = !!ci.url && !!capabilities.openUrl;
114038
114141
  const cursorClass = clickable ? "cursor-pointer" : "";
114039
114142
  if (ci.state === "merged") {
114040
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(Tooltip2, { children: [
114041
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
114143
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(Tooltip2, { children: [
114144
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
114042
114145
  import_lucide_react3.GitMerge,
114043
114146
  {
114044
114147
  className: `size-3.5 shrink-0 text-violet-600 dark:text-violet-400 ${cursorClass}`,
114045
114148
  onClick: (e2) => handleOpenUrl(ci.url, e2)
114046
114149
  }
114047
114150
  ) }),
114048
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipContent2, { children: "Merged" })
114151
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipContent2, { children: "Merged" })
114049
114152
  ] });
114050
114153
  }
114051
114154
  if (ci.state === "success") {
114052
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(Tooltip2, { children: [
114053
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
114155
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(Tooltip2, { children: [
114156
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
114054
114157
  import_lucide_react3.CircleCheck,
114055
114158
  {
114056
114159
  className: `size-3.5 shrink-0 text-green-600 dark:text-green-400 ${cursorClass}`,
114057
114160
  onClick: (e2) => handleOpenUrl(ci.url, e2)
114058
114161
  }
114059
114162
  ) }),
114060
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipContent2, { children: "CI passed" })
114163
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipContent2, { children: "CI passed" })
114061
114164
  ] });
114062
114165
  }
114063
114166
  if (ci.state === "failure") {
114064
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(Tooltip2, { children: [
114065
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
114167
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(Tooltip2, { children: [
114168
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
114066
114169
  import_lucide_react3.CircleAlert,
114067
114170
  {
114068
114171
  className: `size-3.5 shrink-0 text-red-600 dark:text-red-400 ${cursorClass}`,
114069
114172
  onClick: (e2) => handleOpenUrl(ci.url, e2)
114070
114173
  }
114071
114174
  ) }),
114072
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipContent2, { children: "CI failed" })
114175
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipContent2, { children: "CI failed" })
114073
114176
  ] });
114074
114177
  }
114075
114178
  if (ci.state === "running" || ci.state === "pending") {
114076
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(Tooltip2, { children: [
114077
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
114179
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(Tooltip2, { children: [
114180
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
114078
114181
  import_lucide_react3.Loader,
114079
114182
  {
114080
114183
  className: `size-3.5 shrink-0 text-yellow-600 dark:text-yellow-400 animate-spin ${cursorClass}`,
114081
114184
  onClick: (e2) => handleOpenUrl(ci.url, e2)
114082
114185
  }
114083
114186
  ) }),
114084
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipContent2, { children: ci.state === "running" ? "CI running" : "CI pending" })
114187
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipContent2, { children: ci.state === "running" ? "CI running" : "CI pending" })
114085
114188
  ] });
114086
114189
  }
114087
114190
  if (ci.state === "cancelled") {
114088
- return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(Tooltip2, { children: [
114089
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
114191
+ return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(Tooltip2, { children: [
114192
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
114090
114193
  import_lucide_react3.Ban,
114091
114194
  {
114092
114195
  className: `size-3.5 shrink-0 text-gray-600 dark:text-gray-400 ${cursorClass}`,
114093
114196
  onClick: (e2) => handleOpenUrl(ci.url, e2)
114094
114197
  }
114095
114198
  ) }),
114096
- /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(TooltipContent2, { children: "CI cancelled" })
114199
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(TooltipContent2, { children: "CI cancelled" })
114097
114200
  ] });
114098
114201
  }
114099
114202
  return null;
@@ -114442,19 +114545,19 @@ function legacyCopy(text3) {
114442
114545
  var setSelectionTooltip = StateEffect.define();
114443
114546
 
114444
114547
  // src/dashboard/components/CodeMirrorEditor.tsx
114445
- var import_jsx_runtime48 = __toESM(require_jsx_runtime(), 1);
114548
+ var import_jsx_runtime49 = __toESM(require_jsx_runtime(), 1);
114446
114549
 
114447
114550
  // src/dashboard/components/CodeMirrorViewer.tsx
114448
114551
  var import_react9 = __toESM(require_react(), 1);
114449
- var import_jsx_runtime49 = __toESM(require_jsx_runtime(), 1);
114552
+ var import_jsx_runtime50 = __toESM(require_jsx_runtime(), 1);
114450
114553
 
114451
114554
  // src/dashboard/components/CommandPaletteDialog.tsx
114452
114555
  var import_react10 = __toESM(require_react(), 1);
114453
- var import_jsx_runtime50 = __toESM(require_jsx_runtime(), 1);
114556
+ var import_jsx_runtime51 = __toESM(require_jsx_runtime(), 1);
114454
114557
 
114455
114558
  // src/dashboard/components/CommitDialog.tsx
114456
114559
  var import_react11 = __toESM(require_react(), 1);
114457
- var import_jsx_runtime51 = __toESM(require_jsx_runtime(), 1);
114560
+ var import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1);
114458
114561
 
114459
114562
  // src/dashboard/components/DashboardShell.tsx
114460
114563
  var import_react25 = __toESM(require_react(), 1);
@@ -114493,7 +114596,7 @@ var import_react22 = __toESM(require_react(), 1);
114493
114596
  var import_react19 = __toESM(require_react(), 1);
114494
114597
 
114495
114598
  // src/dashboard/components/DeleteWorkspaceDialog.tsx
114496
- var import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1);
114599
+ var import_jsx_runtime53 = __toESM(require_jsx_runtime(), 1);
114497
114600
 
114498
114601
  // src/dashboard/components/NewWorkspaceForm.tsx
114499
114602
  var import_react20 = __toESM(require_react(), 1);
@@ -114504,17 +114607,17 @@ function slugifyBranchName(input) {
114504
114607
  }
114505
114608
 
114506
114609
  // src/dashboard/components/NewWorkspaceForm.tsx
114507
- var import_jsx_runtime53 = __toESM(require_jsx_runtime(), 1);
114610
+ var import_jsx_runtime54 = __toESM(require_jsx_runtime(), 1);
114508
114611
 
114509
114612
  // src/dashboard/components/PromoteToGitDialog.tsx
114510
- var import_jsx_runtime54 = __toESM(require_jsx_runtime(), 1);
114613
+ var import_jsx_runtime55 = __toESM(require_jsx_runtime(), 1);
114511
114614
 
114512
114615
  // src/dashboard/components/WorkspaceCard.tsx
114513
114616
  var import_lucide_react5 = __toESM(require_lucide_react(), 1);
114514
114617
  var import_react21 = __toESM(require_react(), 1);
114515
114618
 
114516
114619
  // src/dashboard/components/GitStatusIndicator.tsx
114517
- var import_jsx_runtime55 = __toESM(require_jsx_runtime(), 1);
114620
+ var import_jsx_runtime56 = __toESM(require_jsx_runtime(), 1);
114518
114621
  function GitStatusIndicator({ git }) {
114519
114622
  const parts = [];
114520
114623
  if (git.conflict) {
@@ -114546,27 +114649,27 @@ function GitStatusIndicator({ git }) {
114546
114649
  });
114547
114650
  }
114548
114651
  if (parts.length === 0) return null;
114549
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(Tooltip2, { children: [
114550
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "inline-flex items-center gap-0.5 font-mono text-[11px] leading-none shrink-0 pr-0.5", children: parts.map((p6) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: p6.color, children: p6.text }, p6.text)) }) }),
114551
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(TooltipContent2, { children: parts.map((p6) => p6.tooltip).join(", ") })
114652
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Tooltip2, { children: [
114653
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "inline-flex items-center gap-0.5 font-mono text-[11px] leading-none shrink-0 pr-0.5", children: parts.map((p6) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: p6.color, children: p6.text }, p6.text)) }) }),
114654
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TooltipContent2, { children: parts.map((p6) => p6.tooltip).join(", ") })
114552
114655
  ] });
114553
114656
  }
114554
114657
 
114555
114658
  // src/dashboard/components/SetupStatusIndicator.tsx
114556
114659
  var import_lucide_react4 = __toESM(require_lucide_react(), 1);
114557
- var import_jsx_runtime56 = __toESM(require_jsx_runtime(), 1);
114660
+ var import_jsx_runtime57 = __toESM(require_jsx_runtime(), 1);
114558
114661
  function SetupStatusIndicator({ setup }) {
114559
114662
  if (!setup) return null;
114560
114663
  if (setup.state === "running") {
114561
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Tooltip2, { children: [
114562
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react4.Loader, { className: "size-3.5 shrink-0 text-blue-600 dark:text-blue-400 animate-spin" }) }),
114563
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TooltipContent2, { side: "top", children: "Setting up workspace..." })
114664
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip2, { children: [
114665
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react4.Loader, { className: "size-3.5 shrink-0 text-blue-600 dark:text-blue-400 animate-spin" }) }),
114666
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent2, { side: "top", children: "Setting up workspace..." })
114564
114667
  ] });
114565
114668
  }
114566
114669
  if (setup.state === "failed") {
114567
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Tooltip2, { children: [
114568
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react4.CircleAlert, { className: "size-3.5 shrink-0 text-red-600 dark:text-red-400" }) }),
114569
- /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(TooltipContent2, { side: "top", children: [
114670
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip2, { children: [
114671
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react4.CircleAlert, { className: "size-3.5 shrink-0 text-red-600 dark:text-red-400" }) }),
114672
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(TooltipContent2, { side: "top", children: [
114570
114673
  "Setup failed",
114571
114674
  setup.error ? `: ${setup.error}` : ""
114572
114675
  ] })
@@ -114576,7 +114679,7 @@ function SetupStatusIndicator({ setup }) {
114576
114679
  }
114577
114680
 
114578
114681
  // src/dashboard/components/WorkspaceCard.tsx
114579
- var import_jsx_runtime57 = __toESM(require_jsx_runtime(), 1);
114682
+ var import_jsx_runtime58 = __toESM(require_jsx_runtime(), 1);
114580
114683
  var RECENT_ACTIVATION_WINDOW_MS = 300;
114581
114684
  var recentlyActivatedWorkspaceId = null;
114582
114685
  var recentlyActivatedTimer = null;
@@ -114620,7 +114723,7 @@ var WorkspaceCard = (0, import_react21.memo)(function WorkspaceCard2({
114620
114723
  const gitPush = useDashboardStore((s6) => s6.gitPush);
114621
114724
  const removeWorkspaceMutation = useRemoveWorkspace();
114622
114725
  const isPinned = worktree.pinned;
114623
- const workspaceId = toWorkspaceId(projectName, worktree.branch);
114726
+ const workspaceId = toWorkspaceId(projectName, worktree.name);
114624
114727
  const isActive = useDashboardStore((s6) => s6.activeWorkspaceId === workspaceId);
114625
114728
  const href = capabilities.getWorkspaceHref?.(workspaceId);
114626
114729
  (0, import_react21.useEffect)(() => {
@@ -114637,7 +114740,7 @@ var WorkspaceCard = (0, import_react21.memo)(function WorkspaceCard2({
114637
114740
  openWorkspace(workspaceId);
114638
114741
  }
114639
114742
  };
114640
- const className = `@container group flex flex-row items-center justify-between pl-3 pr-2 py-1 min-h-9 min-w-0 overflow-hidden cursor-pointer select-none touch-manipulation transition-colors hover:bg-accent/50 [@media(pointer:coarse)]:min-h-11 [@media(pointer:coarse)]:py-2 ${isActive ? "border-l-2 border-l-primary" : ""} ${isFocused ? "ring-2 ring-inset ring-ring" : ""} ${href ? "no-underline text-inherit" : ""}`;
114743
+ const className = `@container group flex flex-row items-center justify-between rounded-md pl-3 pr-2 py-1 min-h-9 min-w-0 overflow-hidden cursor-pointer select-none touch-manipulation transition-colors hover:bg-accent/50 [@media(pointer:coarse)]:min-h-11 [@media(pointer:coarse)]:py-2 ${isActive ? "bg-primary/15 hover:bg-primary/15" : isFocused ? "bg-accent" : ""} ${href ? "no-underline text-inherit" : ""}`;
114641
114744
  const containerProps = {
114642
114745
  ref: cardRef,
114643
114746
  className,
@@ -114670,70 +114773,70 @@ var WorkspaceCard = (0, import_react21.memo)(function WorkspaceCard2({
114670
114773
  const hasUnpushedCommits = (branchStatus?.git.ahead ?? 0) > 0;
114671
114774
  const handleDelete = () => {
114672
114775
  if (!hasUnmergedPR && !isDirty2 && !hasUnpushedCommits) {
114673
- removeWorkspaceMutation.mutate({ project: projectName, branch: worktree.branch });
114776
+ removeWorkspaceMutation.mutate({ project: projectName, name: worktree.name });
114674
114777
  } else {
114675
114778
  onShowDeleteDialog({
114676
114779
  projectName,
114677
- branch: worktree.branch,
114780
+ name: worktree.name,
114678
114781
  isUnmerged: hasUnmergedPR,
114679
114782
  isDirty: isDirty2,
114680
114783
  hasUnpushedCommits
114681
114784
  });
114682
114785
  }
114683
114786
  };
114684
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenu2, { children: [
114685
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ContextMenuTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { ...containerProps, children: [
114686
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Tooltip2, { delayDuration: 800, children: [
114687
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center gap-2 min-w-0 overflow-hidden", children: [
114688
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(AgentStatusIndicator, { agent: status?.agent, isActive }),
114689
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
114787
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenu2, { children: [
114788
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ContextMenuTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { ...containerProps, children: [
114789
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Tooltip2, { delayDuration: 800, children: [
114790
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "flex items-center gap-2 min-w-0 overflow-hidden", children: [
114791
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(AgentStatusIndicator, { agent: status?.agent, isActive }),
114792
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
114690
114793
  "span",
114691
114794
  {
114692
114795
  className: `text-sm truncate ${isActive ? "font-bold text-foreground" : "font-medium text-muted-foreground"}`,
114693
- children: showProjectName ? `${projectName}/${worktree.branch}` : worktree.branch
114796
+ children: showProjectName ? `${projectName}/${worktree.name}` : worktree.name
114694
114797
  }
114695
114798
  )
114696
114799
  ] }) }),
114697
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TooltipContent2, { side: "right", children: `${projectName}/${worktree.branch}` })
114800
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(TooltipContent2, { side: "right", children: `${projectName}/${worktree.name}` })
114698
114801
  ] }),
114699
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "hidden @[10rem]:flex group-hover:flex items-center gap-2 shrink-0 ml-auto pl-2", children: [
114700
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(SetupStatusIndicator, { setup: setupStatus }),
114701
- !isPlain && branchStatus && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(GitStatusIndicator, { git: branchStatus.git }),
114702
- !isPlain && branchStatus && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(CIStatusIndicator, { ci: branchStatus.ci })
114802
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)("div", { className: "hidden @[10rem]:flex group-hover:flex items-center gap-2 shrink-0 ml-auto pl-2", children: [
114803
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(SetupStatusIndicator, { setup: setupStatus }),
114804
+ !isPlain && branchStatus && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(GitStatusIndicator, { git: branchStatus.git }),
114805
+ !isPlain && branchStatus && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(CIStatusIndicator, { ci: branchStatus.ci })
114703
114806
  ] })
114704
114807
  ] }) }),
114705
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuContent2, { children: [
114706
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => onTogglePinned(projectName, worktree.branch, isPinned), children: [
114707
- isPinned ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.PinOff, {}) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.Pin, {}),
114808
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuContent2, { children: [
114809
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => onTogglePinned(projectName, worktree.name, isPinned), children: [
114810
+ isPinned ? /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.PinOff, {}) : /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.Pin, {}),
114708
114811
  isPinned ? "Unpin workspace" : "Pin workspace"
114709
114812
  ] }),
114710
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(ContextMenuSeparator2, {}),
114711
- capabilities.copyPath && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => navigator.clipboard.writeText(worktree.path), children: [
114712
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.Clipboard, {}),
114813
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(ContextMenuSeparator2, {}),
114814
+ capabilities.copyPath && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => navigator.clipboard.writeText(worktree.path), children: [
114815
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.Clipboard, {}),
114713
114816
  "Copy path"
114714
114817
  ] }),
114715
- capabilities.revealInFinder && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => capabilities.revealInFinder(worktree.path), children: [
114716
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.FolderOpen, {}),
114818
+ capabilities.revealInFinder && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => capabilities.revealInFinder(worktree.path), children: [
114819
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.FolderOpen, {}),
114717
114820
  "Open in Finder"
114718
114821
  ] }),
114719
- worktree.hasSetup && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => runScript(worktree.path, "setup"), children: [
114720
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.Play, {}),
114822
+ worktree.hasSetup && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => runScript(worktree.path, "setup"), children: [
114823
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.Play, {}),
114721
114824
  "Run setup"
114722
114825
  ] }),
114723
- worktree.hasTeardown && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => runScript(worktree.path, "teardown"), children: [
114724
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.Square, {}),
114826
+ worktree.hasTeardown && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => runScript(worktree.path, "teardown"), children: [
114827
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.Square, {}),
114725
114828
  "Run teardown"
114726
114829
  ] }),
114727
- !isPlain && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => gitPull(projectName, worktree.branch), children: [
114728
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.ArrowDownToLine, {}),
114830
+ !isPlain && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => gitPull(projectName, worktree.name), children: [
114831
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.ArrowDownToLine, {}),
114729
114832
  "Git pull"
114730
114833
  ] }),
114731
- !isPlain && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { onClick: () => gitPush(projectName, worktree.branch), children: [
114732
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.ArrowUpFromLine, {}),
114834
+ !isPlain && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { onClick: () => gitPush(projectName, worktree.name), children: [
114835
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.ArrowUpFromLine, {}),
114733
114836
  "Git push"
114734
114837
  ] }),
114735
- !isPlain && worktree.branch !== defaultBranch && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(ContextMenuItem2, { variant: "destructive", onClick: handleDelete, children: [
114736
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react5.Trash2, {}),
114838
+ !isPlain && worktree.name !== defaultBranch && /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(ContextMenuItem2, { variant: "destructive", onClick: handleDelete, children: [
114839
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(import_lucide_react5.Trash2, {}),
114737
114840
  "Delete workspace"
114738
114841
  ] })
114739
114842
  ] })
@@ -114741,7 +114844,7 @@ var WorkspaceCard = (0, import_react21.memo)(function WorkspaceCard2({
114741
114844
  });
114742
114845
 
114743
114846
  // src/dashboard/components/ProjectList.tsx
114744
- var import_jsx_runtime58 = __toESM(require_jsx_runtime(), 1);
114847
+ var import_jsx_runtime59 = __toESM(require_jsx_runtime(), 1);
114745
114848
 
114746
114849
  // src/dashboard/components/SettingsPage.tsx
114747
114850
  var import_react24 = __toESM(require_react(), 1);
@@ -114750,16 +114853,16 @@ var import_react24 = __toESM(require_react(), 1);
114750
114853
  var import_react23 = __toESM(require_react(), 1);
114751
114854
 
114752
114855
  // src/dashboard/components/settings/SettingsRow.tsx
114753
- var import_jsx_runtime59 = __toESM(require_jsx_runtime(), 1);
114856
+ var import_jsx_runtime60 = __toESM(require_jsx_runtime(), 1);
114754
114857
 
114755
114858
  // src/dashboard/components/settings/SettingsSection.tsx
114756
- var import_jsx_runtime60 = __toESM(require_jsx_runtime(), 1);
114859
+ var import_jsx_runtime61 = __toESM(require_jsx_runtime(), 1);
114757
114860
 
114758
114861
  // src/dashboard/components/SettingsPage.tsx
114759
- var import_jsx_runtime61 = __toESM(require_jsx_runtime(), 1);
114862
+ var import_jsx_runtime62 = __toESM(require_jsx_runtime(), 1);
114760
114863
 
114761
114864
  // src/dashboard/components/DashboardShell.tsx
114762
- var import_jsx_runtime62 = __toESM(require_jsx_runtime(), 1);
114865
+ var import_jsx_runtime63 = __toESM(require_jsx_runtime(), 1);
114763
114866
  var isElectron = typeof window !== "undefined" && "__BAND_DESKTOP__" in window;
114764
114867
 
114765
114868
  // src/dashboard/components/DiffView.tsx
@@ -115025,18 +115128,18 @@ function joinWorkspacePath(workspaceRoot, relativePath) {
115025
115128
  }
115026
115129
 
115027
115130
  // src/dashboard/components/FileStatusBadge.tsx
115028
- var import_jsx_runtime63 = __toESM(require_jsx_runtime(), 1);
115131
+ var import_jsx_runtime64 = __toESM(require_jsx_runtime(), 1);
115029
115132
 
115030
115133
  // src/dashboard/components/ChangesFileTree.tsx
115031
- var import_jsx_runtime64 = __toESM(require_jsx_runtime(), 1);
115134
+ var import_jsx_runtime65 = __toESM(require_jsx_runtime(), 1);
115032
115135
 
115033
115136
  // src/dashboard/components/RevertFileDialog.tsx
115034
- var import_jsx_runtime65 = __toESM(require_jsx_runtime(), 1);
115137
+ var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1);
115035
115138
 
115036
115139
  // src/dashboard/components/SearchBar.tsx
115037
115140
  var import_lucide_react6 = __toESM(require_lucide_react(), 1);
115038
115141
  var import_react33 = __toESM(require_react(), 1);
115039
- var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1);
115142
+ var import_jsx_runtime67 = __toESM(require_jsx_runtime(), 1);
115040
115143
  var DEFAULT_VISIBLE_OPTIONS = ["caseSensitive", "wholeWord", "regex"];
115041
115144
  function ToggleButton({
115042
115145
  active,
@@ -115044,7 +115147,7 @@ function ToggleButton({
115044
115147
  title,
115045
115148
  children
115046
115149
  }) {
115047
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
115150
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
115048
115151
  "button",
115049
115152
  {
115050
115153
  type: "button",
@@ -115085,13 +115188,13 @@ var SearchBar = (0, import_react33.forwardRef)(function SearchBar2({
115085
115188
  const toggleRegex = (0, import_react33.useCallback)(() => {
115086
115189
  onOptionsChange({ ...options2, regex: !options2.regex });
115087
115190
  }, [options2, onOptionsChange]);
115088
- return /* @__PURE__ */ (0, import_jsx_runtime66.jsxs)(
115191
+ return /* @__PURE__ */ (0, import_jsx_runtime67.jsxs)(
115089
115192
  "div",
115090
115193
  {
115091
115194
  className: `flex shrink-0 items-center gap-1.5 border-b border-border bg-muted/30 px-3 py-1.5 ${className ?? ""}`,
115092
115195
  children: [
115093
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.Search, { className: "size-3.5 shrink-0 text-muted-foreground" }),
115094
- /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
115196
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.Search, { className: "size-3.5 shrink-0 text-muted-foreground" }),
115197
+ /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
115095
115198
  "input",
115096
115199
  {
115097
115200
  ref: inputRef,
@@ -115112,11 +115215,11 @@ var SearchBar = (0, import_react33.forwardRef)(function SearchBar2({
115112
115215
  }
115113
115216
  }
115114
115217
  ),
115115
- showCase && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ToggleButton, { active: options2.caseSensitive, onClick: toggleCase, title: "Match Case", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.CaseSensitive, { className: "size-4" }) }),
115116
- showWholeWord && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ToggleButton, { active: options2.wholeWord, onClick: toggleWholeWord, title: "Match Whole Word", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.WholeWord, { className: "size-4" }) }),
115117
- showRegex && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(ToggleButton, { active: options2.regex, onClick: toggleRegex, title: "Use Regular Expression", children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.Regex, { className: "size-4" }) }),
115118
- matchInfo && query && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: matchInfo.total > 0 ? `${matchInfo.current} of ${matchInfo.total}` : "No results" }),
115119
- onPrevious && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
115218
+ showCase && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ToggleButton, { active: options2.caseSensitive, onClick: toggleCase, title: "Match Case", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.CaseSensitive, { className: "size-4" }) }),
115219
+ showWholeWord && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ToggleButton, { active: options2.wholeWord, onClick: toggleWholeWord, title: "Match Whole Word", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.WholeWord, { className: "size-4" }) }),
115220
+ showRegex && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(ToggleButton, { active: options2.regex, onClick: toggleRegex, title: "Use Regular Expression", children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.Regex, { className: "size-4" }) }),
115221
+ matchInfo && query && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)("span", { className: "shrink-0 text-xs text-muted-foreground tabular-nums", children: matchInfo.total > 0 ? `${matchInfo.current} of ${matchInfo.total}` : "No results" }),
115222
+ onPrevious && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
115120
115223
  "button",
115121
115224
  {
115122
115225
  type: "button",
@@ -115124,10 +115227,10 @@ var SearchBar = (0, import_react33.forwardRef)(function SearchBar2({
115124
115227
  disabled: !matchInfo || matchInfo.total === 0,
115125
115228
  className: "inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:text-foreground disabled:opacity-30",
115126
115229
  title: "Previous match (Shift+Enter)",
115127
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.ChevronUp, { className: "size-3.5" })
115230
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.ChevronUp, { className: "size-3.5" })
115128
115231
  }
115129
115232
  ),
115130
- onNext && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
115233
+ onNext && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
115131
115234
  "button",
115132
115235
  {
115133
115236
  type: "button",
@@ -115135,17 +115238,17 @@ var SearchBar = (0, import_react33.forwardRef)(function SearchBar2({
115135
115238
  disabled: !matchInfo || matchInfo.total === 0,
115136
115239
  className: "inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:text-foreground disabled:opacity-30",
115137
115240
  title: "Next match (Enter)",
115138
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.ChevronDown, { className: "size-3.5" })
115241
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.ChevronDown, { className: "size-3.5" })
115139
115242
  }
115140
115243
  ),
115141
- onClose && /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(
115244
+ onClose && /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(
115142
115245
  "button",
115143
115246
  {
115144
115247
  type: "button",
115145
115248
  onClick: onClose,
115146
115249
  className: "inline-flex size-6 items-center justify-center rounded text-muted-foreground hover:text-foreground",
115147
115250
  title: "Close (Escape)",
115148
- children: /* @__PURE__ */ (0, import_jsx_runtime66.jsx)(import_lucide_react6.X, { className: "size-3.5" })
115251
+ children: /* @__PURE__ */ (0, import_jsx_runtime67.jsx)(import_lucide_react6.X, { className: "size-3.5" })
115149
115252
  }
115150
115253
  )
115151
115254
  ]
@@ -115154,7 +115257,7 @@ var SearchBar = (0, import_react33.forwardRef)(function SearchBar2({
115154
115257
  });
115155
115258
 
115156
115259
  // src/dashboard/components/DiffView.tsx
115157
- var import_jsx_runtime67 = __toESM(require_jsx_runtime(), 1);
115260
+ var import_jsx_runtime68 = __toESM(require_jsx_runtime(), 1);
115158
115261
  var diffTheme = EditorView.theme({
115159
115262
  ".cm-insertedLine": { backgroundColor: "rgba(34, 197, 94, 0.1)" },
115160
115263
  ".cm-deletedLine": { backgroundColor: "rgba(239, 68, 68, 0.1)" },
@@ -115206,7 +115309,7 @@ var diffTheme = EditorView.theme({
115206
115309
  // src/dashboard/components/FileBrowser.tsx
115207
115310
  var import_lucide_react7 = __toESM(require_lucide_react(), 1);
115208
115311
  var import_react35 = __toESM(require_react(), 1);
115209
- var import_jsx_runtime68 = __toESM(require_jsx_runtime(), 1);
115312
+ var import_jsx_runtime69 = __toESM(require_jsx_runtime(), 1);
115210
115313
  var expandedStateCache = /* @__PURE__ */ new Map();
115211
115314
  var dirContentsCache = /* @__PURE__ */ new Map();
115212
115315
  function getCachedExpanded(wsId) {
@@ -115287,21 +115390,21 @@ function EntryNameInput({
115287
115390
  }
115288
115391
  };
115289
115392
  const Icon = kind === "directory" ? import_lucide_react7.Folder : import_lucide_react7.File;
115290
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex w-full flex-col", style: { paddingLeft: `${depth * indent + basePad}px` }, children: [
115291
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115393
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex w-full flex-col", style: { paddingLeft: `${depth * indent + basePad}px` }, children: [
115394
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115292
115395
  "div",
115293
115396
  {
115294
115397
  className: `flex items-center ${compact ? "h-[28px] gap-1 pr-3 text-[13px]" : "h-[32px] gap-1.5 pr-4 text-[15px]"}`,
115295
115398
  style: { height },
115296
115399
  children: [
115297
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "size-3.5 shrink-0" }),
115298
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115400
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "size-3.5 shrink-0" }),
115401
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115299
115402
  Icon,
115300
115403
  {
115301
115404
  className: kind === "directory" ? "size-4 shrink-0 text-blue-600 dark:text-blue-400" : "size-4 shrink-0 text-muted-foreground"
115302
115405
  }
115303
115406
  ),
115304
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115407
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115305
115408
  "input",
115306
115409
  {
115307
115410
  ref: inputRef,
@@ -115338,7 +115441,7 @@ function EntryNameInput({
115338
115441
  ]
115339
115442
  }
115340
115443
  ),
115341
- error2 && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115444
+ error2 && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115342
115445
  "div",
115343
115446
  {
115344
115447
  className: "pointer-events-none text-xs text-destructive",
@@ -115406,7 +115509,7 @@ function TreeNode2({
115406
115509
  onOpenFilePinned(entryPath);
115407
115510
  }
115408
115511
  };
115409
- const button = /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115512
+ const button = /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115410
115513
  "button",
115411
115514
  {
115412
115515
  ref: isSelected ? selectedRef : void 0,
@@ -115420,15 +115523,15 @@ function TreeNode2({
115420
115523
  className: `flex w-full items-center text-left select-none hover:bg-accent/50 [-webkit-touch-callout:none] ${compact ? "h-[28px] gap-1 pr-3 text-[13px]" : "h-[32px] gap-1.5 pr-4 text-[15px]"} ${isSelected ? "bg-blue-500/30 text-foreground outline outline-1 -outline-offset-1 outline-blue-400/60 hover:bg-blue-500/30 dark:bg-blue-500/40 dark:outline-blue-400/70 dark:hover:bg-blue-500/40" : ""} ${isCut ? "opacity-50" : ""}`,
115421
115524
  style: { paddingLeft: `${depth * indent + basePad}px` },
115422
115525
  children: [
115423
- isDir ? isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ChevronDown, { className: "size-3.5 shrink-0 text-muted-foreground/70" }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ChevronRight, { className: "size-3.5 shrink-0 text-muted-foreground/70" }) : /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "size-3.5 shrink-0" }),
115526
+ isDir ? isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ChevronDown, { className: "size-3.5 shrink-0 text-muted-foreground/70" }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ChevronRight, { className: "size-3.5 shrink-0 text-muted-foreground/70" }) : /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "size-3.5 shrink-0" }),
115424
115527
  isDir ? (() => {
115425
115528
  const FolderIcon = getFolderIcon(entry.name, isExpanded);
115426
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FolderIcon, { className: "size-4 shrink-0" });
115529
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FolderIcon, { className: "size-4 shrink-0" });
115427
115530
  })() : (() => {
115428
115531
  const FileIcon = getFileIcon(entry.name);
115429
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(FileIcon, { className: "size-4 shrink-0" });
115532
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(FileIcon, { className: "size-4 shrink-0" });
115430
115533
  })(),
115431
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { className: "min-w-0 flex-1 truncate", children: entry.name })
115534
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { className: "min-w-0 flex-1 truncate", children: entry.name })
115432
115535
  ]
115433
115536
  }
115434
115537
  );
@@ -115450,7 +115553,7 @@ function TreeNode2({
115450
115553
  // a padding div with `depth={0}` would double-apply `basePad`, shifting
115451
115554
  // the input ~4px to the right and giving it visibly less horizontal
115452
115555
  // room than the rest of the tree.
115453
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115556
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115454
115557
  EntryNameInput,
115455
115558
  {
115456
115559
  kind: isDir ? "directory" : "file",
@@ -115464,97 +115567,97 @@ function TreeNode2({
115464
115567
  },
115465
115568
  `rename-${entryPath}`
115466
115569
  )
115467
- ) : /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115570
+ ) : /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115468
115571
  ContextMenu2,
115469
115572
  {
115470
115573
  onOpenChange: (open3) => {
115471
115574
  if (open3) onSelectRow(entryPath, isDir ? "directory" : "file");
115472
115575
  },
115473
115576
  children: [
115474
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuTrigger2, { asChild: true, children: button }),
115475
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuContent2, { onCloseAutoFocus: menu.flush, children: [
115476
- isDir && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
115477
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115577
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuTrigger2, { asChild: true, children: button }),
115578
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuContent2, { onCloseAutoFocus: menu.flush, children: [
115579
+ isDir && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
115580
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115478
115581
  ContextMenuItem2,
115479
115582
  {
115480
115583
  onSelect: () => menu.queue(() => onRequestNewEntry(entryPath, "file")),
115481
115584
  children: [
115482
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.File, { className: "size-4" }),
115585
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.File, { className: "size-4" }),
115483
115586
  "New File"
115484
115587
  ]
115485
115588
  }
115486
115589
  ),
115487
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115590
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115488
115591
  ContextMenuItem2,
115489
115592
  {
115490
115593
  onSelect: () => menu.queue(() => onRequestNewEntry(entryPath, "directory")),
115491
115594
  children: [
115492
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.FolderPlus, { className: "size-4" }),
115595
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.FolderPlus, { className: "size-4" }),
115493
115596
  "New Folder"
115494
115597
  ]
115495
115598
  }
115496
115599
  ),
115497
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuSeparator2, {})
115600
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuSeparator2, {})
115498
115601
  ] }),
115499
- canCut && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115602
+ canCut && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115500
115603
  ContextMenuItem2,
115501
115604
  {
115502
115605
  onSelect: () => menu.queue(() => onCut(entryPath, isDir ? "directory" : "file")),
115503
115606
  children: [
115504
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.Scissors, { className: "size-4" }),
115607
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.Scissors, { className: "size-4" }),
115505
115608
  "Cut"
115506
115609
  ]
115507
115610
  }
115508
115611
  ),
115509
- canCopy && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115612
+ canCopy && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115510
115613
  ContextMenuItem2,
115511
115614
  {
115512
115615
  onSelect: () => menu.queue(() => onCopy(entryPath, isDir ? "directory" : "file")),
115513
115616
  children: [
115514
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.Copy, { className: "size-4" }),
115617
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.Copy, { className: "size-4" }),
115515
115618
  "Copy"
115516
115619
  ]
115517
115620
  }
115518
115621
  ),
115519
- isDir && canPaste && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuItem2, { onSelect: () => menu.queue(() => void onPaste(entryPath)), children: [
115520
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ClipboardPaste, { className: "size-4" }),
115622
+ isDir && canPaste && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuItem2, { onSelect: () => menu.queue(() => void onPaste(entryPath)), children: [
115623
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ClipboardPaste, { className: "size-4" }),
115521
115624
  "Paste"
115522
115625
  ] }),
115523
- (canCut || canCopy || isDir && canPaste) && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuSeparator2, {}),
115524
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115626
+ (canCut || canCopy || isDir && canPaste) && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuSeparator2, {}),
115627
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115525
115628
  ContextMenuItem2,
115526
115629
  {
115527
115630
  "data-testid": "file-tree__copy-relative-path",
115528
115631
  onSelect: () => menu.queue(() => void writeClipboardText(entryPath)),
115529
115632
  children: [
115530
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ClipboardCopy, { className: "size-4" }),
115633
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ClipboardCopy, { className: "size-4" }),
115531
115634
  "Copy relative path"
115532
115635
  ]
115533
115636
  }
115534
115637
  ),
115535
- workspacePath && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115638
+ workspacePath && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115536
115639
  ContextMenuItem2,
115537
115640
  {
115538
115641
  "data-testid": "file-tree__copy-absolute-path",
115539
115642
  onSelect: () => menu.queue(() => void writeClipboardText(joinWorkspacePath(workspacePath, entryPath))),
115540
115643
  children: [
115541
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ClipboardCopy, { className: "size-4" }),
115644
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ClipboardCopy, { className: "size-4" }),
115542
115645
  "Copy absolute path"
115543
115646
  ]
115544
115647
  }
115545
115648
  ),
115546
- (canRename || canDelete) && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuSeparator2, {}),
115547
- canRename && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuItem2, { onSelect: () => menu.queue(() => onRequestRename(entryPath)), children: [
115548
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.Pencil, { className: "size-4" }),
115649
+ (canRename || canDelete) && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuSeparator2, {}),
115650
+ canRename && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuItem2, { onSelect: () => menu.queue(() => onRequestRename(entryPath)), children: [
115651
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.Pencil, { className: "size-4" }),
115549
115652
  "Rename"
115550
115653
  ] }),
115551
- canDelete && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
115654
+ canDelete && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
115552
115655
  ContextMenuItem2,
115553
115656
  {
115554
115657
  variant: "destructive",
115555
115658
  onSelect: () => menu.queue(() => onRequestDelete(entryPath, isDir ? "directory" : "file")),
115556
115659
  children: [
115557
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.Trash2, { className: "size-4" }),
115660
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.Trash2, { className: "size-4" }),
115558
115661
  "Delete"
115559
115662
  ]
115560
115663
  }
@@ -115564,13 +115667,13 @@ function TreeNode2({
115564
115667
  }
115565
115668
  );
115566
115669
  const showInlineInput = newEntry?.parentPath === entryPath;
115567
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
115670
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
115568
115671
  row,
115569
115672
  isExpanded && (() => {
115570
115673
  const splitIdx = children?.findIndex((c2) => c2.type === "file") ?? -1;
115571
115674
  const folderChildren = splitIdx === -1 ? children ?? [] : (children ?? []).slice(0, splitIdx);
115572
115675
  const fileChildren = splitIdx === -1 ? [] : (children ?? []).slice(splitIdx);
115573
- const renderChild = (child) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115676
+ const renderChild = (child) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115574
115677
  TreeNode2,
115575
115678
  {
115576
115679
  entry: child,
@@ -115608,7 +115711,7 @@ function TreeNode2({
115608
115711
  },
115609
115712
  child.name
115610
115713
  );
115611
- const newEntryInput = showInlineInput ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115714
+ const newEntryInput = showInlineInput ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115612
115715
  EntryNameInput,
115613
115716
  {
115614
115717
  kind: newEntry.kind,
@@ -115620,9 +115723,9 @@ function TreeNode2({
115620
115723
  },
115621
115724
  `new-${newEntry.kind}-${entryPath}`
115622
115725
  ) : null;
115623
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
115726
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
115624
115727
  showInlineInput && newEntry.kind === "directory" && newEntryInput,
115625
- isLoading && !children?.length && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115728
+ isLoading && !children?.length && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115626
115729
  "div",
115627
115730
  {
115628
115731
  className: `flex items-center text-muted-foreground/70 ${compact ? "text-[13px]" : "text-[15px]"}`,
@@ -115633,7 +115736,7 @@ function TreeNode2({
115633
115736
  children: "Loading\u2026"
115634
115737
  }
115635
115738
  ),
115636
- !isLoading && !showInlineInput && children && children.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
115739
+ !isLoading && !showInlineInput && children && children.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
115637
115740
  "div",
115638
115741
  {
115639
115742
  className: `flex items-center italic text-muted-foreground/50 ${compact ? "text-[13px]" : "text-[15px]"}`,
@@ -116079,7 +116182,7 @@ var FileBrowser = (0, import_react35.forwardRef)(function FileBrowser2({
116079
116182
  );
116080
116183
  const rootMenu = useDeferredMenuAction();
116081
116184
  if (!adapter.listWorkspaceFiles) {
116082
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "File browsing not supported" });
116185
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "File browsing not supported" });
116083
116186
  }
116084
116187
  const rootEntries = dirContents.get("") ?? [];
116085
116188
  const rootLoading = loadingPaths.has("");
@@ -116116,20 +116219,20 @@ var FileBrowser = (0, import_react35.forwardRef)(function FileBrowser2({
116116
116219
  void pasteInto(resolveDefaultTarget());
116117
116220
  }
116118
116221
  };
116119
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex h-full flex-col overflow-hidden", onKeyDown: handleKeyDown, children: [
116120
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(
116222
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex h-full flex-col overflow-hidden", onKeyDown: handleKeyDown, children: [
116223
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(
116121
116224
  ContextMenu2,
116122
116225
  {
116123
116226
  onOpenChange: (open3) => {
116124
116227
  if (open3) clearTreeSelection();
116125
116228
  },
116126
116229
  children: [
116127
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "min-h-0 flex-1 overflow-y-auto py-1 pl-px", children: [
116230
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuTrigger2, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "min-h-0 flex-1 overflow-y-auto py-1 pl-px", children: [
116128
116231
  (() => {
116129
116232
  const rootSplitIdx = rootEntries.findIndex((e2) => e2.type === "file");
116130
116233
  const rootFolders = rootSplitIdx === -1 ? rootEntries : rootEntries.slice(0, rootSplitIdx);
116131
116234
  const rootFiles = rootSplitIdx === -1 ? [] : rootEntries.slice(rootSplitIdx);
116132
- const renderRow = (entry) => /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
116235
+ const renderRow = (entry) => /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
116133
116236
  TreeNode2,
116134
116237
  {
116135
116238
  entry,
@@ -116167,7 +116270,7 @@ var FileBrowser = (0, import_react35.forwardRef)(function FileBrowser2({
116167
116270
  },
116168
116271
  entry.name
116169
116272
  );
116170
- const rootInput = showRootInput ? /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
116273
+ const rootInput = showRootInput ? /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
116171
116274
  EntryNameInput,
116172
116275
  {
116173
116276
  kind: newEntry.kind,
@@ -116179,30 +116282,30 @@ var FileBrowser = (0, import_react35.forwardRef)(function FileBrowser2({
116179
116282
  },
116180
116283
  `new-${newEntry.kind}-root`
116181
116284
  ) : null;
116182
- return /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
116285
+ return /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
116183
116286
  showRootInput && newEntry.kind === "directory" && rootInput,
116184
- rootLoading && rootEntries.length === 0 && !showRootInput && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "Loading\u2026" }),
116185
- !rootLoading && rootEntries.length === 0 && !showRootInput && /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "Empty directory" }),
116287
+ rootLoading && rootEntries.length === 0 && !showRootInput && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "Loading\u2026" }),
116288
+ !rootLoading && rootEntries.length === 0 && !showRootInput && /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "flex h-32 items-center justify-center text-sm text-muted-foreground", children: "Empty directory" }),
116186
116289
  rootFolders.map(renderRow),
116187
116290
  showRootInput && newEntry.kind === "file" && rootInput,
116188
116291
  rootFiles.map(renderRow)
116189
116292
  ] });
116190
116293
  })(),
116191
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("div", { className: "min-h-[40px] flex-1" })
116294
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("div", { className: "min-h-[40px] flex-1" })
116192
116295
  ] }) }),
116193
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuContent2, { onCloseAutoFocus: rootMenu.flush, children: [
116194
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => requestNewEntry("", "file")), children: [
116195
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.File, { className: "size-4" }),
116296
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuContent2, { onCloseAutoFocus: rootMenu.flush, children: [
116297
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => requestNewEntry("", "file")), children: [
116298
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.File, { className: "size-4" }),
116196
116299
  "New File"
116197
116300
  ] }),
116198
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => requestNewEntry("", "directory")), children: [
116199
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.FolderPlus, { className: "size-4" }),
116301
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => requestNewEntry("", "directory")), children: [
116302
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.FolderPlus, { className: "size-4" }),
116200
116303
  "New Folder"
116201
116304
  ] }),
116202
- canPaste && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(import_jsx_runtime68.Fragment, { children: [
116203
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(ContextMenuSeparator2, {}),
116204
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => void pasteInto("")), children: [
116205
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.ClipboardPaste, { className: "size-4" }),
116305
+ canPaste && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(import_jsx_runtime69.Fragment, { children: [
116306
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(ContextMenuSeparator2, {}),
116307
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(ContextMenuItem2, { onSelect: () => rootMenu.queue(() => void pasteInto("")), children: [
116308
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.ClipboardPaste, { className: "size-4" }),
116206
116309
  "Paste"
116207
116310
  ] })
116208
116311
  ] })
@@ -116210,42 +116313,42 @@ var FileBrowser = (0, import_react35.forwardRef)(function FileBrowser2({
116210
116313
  ]
116211
116314
  }
116212
116315
  ),
116213
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
116316
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
116214
116317
  Dialog2,
116215
116318
  {
116216
116319
  open: pendingDelete !== null,
116217
116320
  onOpenChange: (open3) => {
116218
116321
  if (!open3) cancelDelete();
116219
116322
  },
116220
- children: /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(DialogContent2, { className: "sm:max-w-[425px]", onClick: (e2) => e2.stopPropagation(), children: [
116221
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(DialogHeader, { children: [
116222
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(DialogTitle2, { children: [
116323
+ children: /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(DialogContent2, { className: "sm:max-w-[425px]", onClick: (e2) => e2.stopPropagation(), children: [
116324
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(DialogHeader, { children: [
116325
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(DialogTitle2, { children: [
116223
116326
  "Delete ",
116224
116327
  pendingDelete?.kind === "directory" ? "folder" : "file"
116225
116328
  ] }),
116226
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(DialogDescription2, { children: [
116329
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(DialogDescription2, { children: [
116227
116330
  "Are you sure you want to delete ",
116228
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("strong", { children: pendingDelete?.path }),
116331
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("strong", { children: pendingDelete?.path }),
116229
116332
  "?"
116230
116333
  ] })
116231
116334
  ] }),
116232
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex flex-col gap-2 text-sm", children: [
116233
- pendingDelete?.kind === "directory" && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-yellow-500/30 bg-yellow-500/10 p-3", children: [
116234
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 text-yellow-500 mt-0.5" }),
116235
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "The folder and all of its contents will be deleted from disk. This cannot be undone." })
116335
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex flex-col gap-2 text-sm", children: [
116336
+ pendingDelete?.kind === "directory" && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-yellow-500/30 bg-yellow-500/10 p-3", children: [
116337
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 text-yellow-500 mt-0.5" }),
116338
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "The folder and all of its contents will be deleted from disk. This cannot be undone." })
116236
116339
  ] }),
116237
- pendingDelete?.kind === "file" && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-yellow-500/30 bg-yellow-500/10 p-3", children: [
116238
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 text-yellow-500 mt-0.5" }),
116239
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: "The file will be deleted from disk. This cannot be undone." })
116340
+ pendingDelete?.kind === "file" && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-yellow-500/30 bg-yellow-500/10 p-3", children: [
116341
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 text-yellow-500 mt-0.5" }),
116342
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: "The file will be deleted from disk. This cannot be undone." })
116240
116343
  ] }),
116241
- deleteError && /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 p-3 text-destructive", children: [
116242
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 mt-0.5" }),
116243
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)("span", { children: deleteError })
116344
+ deleteError && /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)("div", { className: "flex items-start gap-2 rounded-md border border-destructive/30 bg-destructive/10 p-3 text-destructive", children: [
116345
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(import_lucide_react7.AlertTriangle, { className: "size-4 shrink-0 mt-0.5" }),
116346
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)("span", { children: deleteError })
116244
116347
  ] })
116245
116348
  ] }),
116246
- /* @__PURE__ */ (0, import_jsx_runtime68.jsxs)(DialogFooter, { children: [
116247
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(Button, { variant: "ghost", onClick: cancelDelete, disabled: deleteSubmitting, children: "Cancel" }),
116248
- /* @__PURE__ */ (0, import_jsx_runtime68.jsx)(
116349
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsxs)(DialogFooter, { children: [
116350
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(Button, { variant: "ghost", onClick: cancelDelete, disabled: deleteSubmitting, children: "Cancel" }),
116351
+ /* @__PURE__ */ (0, import_jsx_runtime69.jsx)(
116249
116352
  Button,
116250
116353
  {
116251
116354
  variant: "destructive",
@@ -116266,32 +116369,32 @@ var import_react38 = __toESM(require_react(), 1);
116266
116369
 
116267
116370
  // src/dashboard/components/ImagePreview.tsx
116268
116371
  var import_react36 = __toESM(require_react(), 1);
116269
- var import_jsx_runtime69 = __toESM(require_jsx_runtime(), 1);
116372
+ var import_jsx_runtime70 = __toESM(require_jsx_runtime(), 1);
116270
116373
 
116271
116374
  // src/dashboard/components/LanguagePickerDialog.tsx
116272
116375
  var import_react37 = __toESM(require_react(), 1);
116273
- var import_jsx_runtime70 = __toESM(require_jsx_runtime(), 1);
116376
+ var import_jsx_runtime71 = __toESM(require_jsx_runtime(), 1);
116274
116377
 
116275
116378
  // src/dashboard/components/PdfPreview.tsx
116276
- var import_jsx_runtime71 = __toESM(require_jsx_runtime(), 1);
116379
+ var import_jsx_runtime72 = __toESM(require_jsx_runtime(), 1);
116277
116380
 
116278
116381
  // src/dashboard/components/FileViewer.tsx
116279
- var import_jsx_runtime72 = __toESM(require_jsx_runtime(), 1);
116382
+ var import_jsx_runtime73 = __toESM(require_jsx_runtime(), 1);
116280
116383
 
116281
116384
  // src/dashboard/components/QuickOpenDialog.tsx
116282
116385
  var import_react39 = __toESM(require_react(), 1);
116283
- var import_jsx_runtime73 = __toESM(require_jsx_runtime(), 1);
116386
+ var import_jsx_runtime74 = __toESM(require_jsx_runtime(), 1);
116284
116387
 
116285
116388
  // src/dashboard/components/SearchFilesDialog.tsx
116286
116389
  var import_react40 = __toESM(require_react(), 1);
116287
- var import_jsx_runtime74 = __toESM(require_jsx_runtime(), 1);
116390
+ var import_jsx_runtime75 = __toESM(require_jsx_runtime(), 1);
116288
116391
 
116289
116392
  // src/dashboard/components/WorkspacePickerDialog.tsx
116290
116393
  var import_react41 = __toESM(require_react(), 1);
116291
- var import_jsx_runtime75 = __toESM(require_jsx_runtime(), 1);
116394
+ var import_jsx_runtime76 = __toESM(require_jsx_runtime(), 1);
116292
116395
 
116293
116396
  // src/dashboard/components/WorkspaceTabNav.tsx
116294
- var import_jsx_runtime76 = __toESM(require_jsx_runtime(), 1);
116397
+ var import_jsx_runtime77 = __toESM(require_jsx_runtime(), 1);
116295
116398
 
116296
116399
  // src/dashboard/hooks/use-editor-history.ts
116297
116400
  var import_react42 = __toESM(require_react(), 1);
@@ -118540,7 +118643,7 @@ var cmdClickLinkPlugin = ViewPlugin.fromClass(
118540
118643
 
118541
118644
  // src/server/infra/git/git-client.ts
118542
118645
  init_src();
118543
- import { execFile as execFile3 } from "node:child_process";
118646
+ import { execFile as execFile4 } from "node:child_process";
118544
118647
  import { readFile, stat as stat3 } from "node:fs/promises";
118545
118648
  import { join as join15 } from "node:path";
118546
118649
  var log11 = createLogger("git");
@@ -118599,15 +118702,13 @@ async function resolveDetachedBranch(worktreePath) {
118599
118702
  }
118600
118703
  function gitCmd() {
118601
118704
  const env = { ...process.env };
118602
- if (env.PATH) {
118603
- env.PATH = `/opt/homebrew/bin:/usr/local/bin:${env.PATH}`;
118604
- }
118705
+ env.PATH = prependBinDirs(env.PATH);
118605
118706
  return { command: "git", env };
118606
118707
  }
118607
118708
  function execGit(args, cwd) {
118608
118709
  const { command, env } = gitCmd();
118609
118710
  return new Promise((resolve12, reject) => {
118610
- execFile3(command, args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
118711
+ execFile4(command, args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
118611
118712
  if (err) {
118612
118713
  reject(new Error(stderr || err.message));
118613
118714
  return;
@@ -118618,11 +118719,9 @@ function execGit(args, cwd) {
118618
118719
  }
118619
118720
  function execGh(args, cwd) {
118620
118721
  const env = { ...process.env };
118621
- if (env.PATH) {
118622
- env.PATH = `/opt/homebrew/bin:/usr/local/bin:${env.PATH}`;
118623
- }
118722
+ env.PATH = prependBinDirs(env.PATH);
118624
118723
  return new Promise((resolve12, reject) => {
118625
- execFile3("gh", args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
118724
+ execFile4("gh", args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
118626
118725
  if (err) {
118627
118726
  reject(new Error(stderr || err.message));
118628
118727
  return;
@@ -118857,15 +118956,15 @@ function parseBatchedCIResponse(data, aliases, defaultBranches) {
118857
118956
  }
118858
118957
 
118859
118958
  // src/server/infra/db/queries/projects.ts
118860
- import { existsSync as existsSync5 } from "node:fs";
118959
+ import { existsSync as existsSync6 } from "node:fs";
118861
118960
  import { join as join16 } from "node:path";
118862
118961
  function reconcileKindForProject(project) {
118863
- if (!existsSync5(project.path)) return false;
118864
- const detectedKind = existsSync5(join16(project.path, ".git")) ? "git" : "plain";
118962
+ if (!existsSync6(project.path)) return false;
118963
+ const detectedKind = existsSync6(join16(project.path, ".git")) ? "git" : "plain";
118865
118964
  if (detectedKind === project.kind) return false;
118866
118965
  project.kind = detectedKind;
118867
118966
  if (detectedKind === "plain") {
118868
- project.worktrees = [{ branch: "main", path: project.path, pinned: false }];
118967
+ project.worktrees = [{ name: "main", branch: "main", path: project.path, pinned: false }];
118869
118968
  }
118870
118969
  return true;
118871
118970
  }
@@ -118883,6 +118982,10 @@ var ProjectQueries = class {
118883
118982
  for (const row of worktreeRows) {
118884
118983
  const list2 = wtByProject.get(row.projectName) ?? [];
118885
118984
  list2.push({
118985
+ // Defensive `|| branch`: a row written before the `name` column
118986
+ // existed (backfilled by migration) should never be empty, but fall
118987
+ // back to branch so identity stays stable even if it somehow is.
118988
+ name: row.name || row.branch,
118886
118989
  branch: row.branch,
118887
118990
  path: row.path,
118888
118991
  head: row.head ?? void 0,
@@ -118931,6 +119034,7 @@ var ProjectQueries = class {
118931
119034
  for (const wt of project.worktrees) {
118932
119035
  tx.insert(worktrees).values({
118933
119036
  projectName: project.name,
119037
+ name: wt.name,
118934
119038
  branch: wt.branch,
118935
119039
  path: wt.path,
118936
119040
  head: wt.head ?? null,
@@ -119046,14 +119150,19 @@ var WorkspaceQueries = class {
119046
119150
  * Resolve a workspace ID back to its on-disk identity (project, branch,
119047
119151
  * worktree path) by scanning the `worktrees` table.
119048
119152
  *
119049
- * The match expression mirrors `toWorkspaceId(project, branch)`:
119050
- * `${project}-${branch.replaceAll("/", "-")}`
119051
- * SQLite's `REPLACE(str, "/", "-")` is also a replace-all, so this is
119052
- * bit-identical to the JS computation. Pushing the match down into SQL
119053
- * lets us read at most one row instead of fanning out the projects +
119054
- * worktrees tree just to find a single workspace (the previous
119055
- * `loadState()`-based implementation walked every project's worktree
119056
- * list to find the match in JS).
119153
+ * The match expression mirrors `toWorkspaceId(project, name)`:
119154
+ * `${project}-${name.replaceAll("/", "-")}`
119155
+ * where `name` is the immutable workspace identity (see the `worktrees`
119156
+ * schema), NOT the live `branch`. SQLite's `REPLACE(str, "/", "-")` is
119157
+ * also a replace-all, so this is bit-identical to the JS computation.
119158
+ * Pushing the match down into SQL lets us read at most one row instead of
119159
+ * fanning out the projects + worktrees tree just to find a single
119160
+ * workspace (the previous `loadState()`-based implementation walked every
119161
+ * project's worktree list to find the match in JS).
119162
+ *
119163
+ * The returned `branch` is the live git branch, still useful to callers
119164
+ * that want the current checkout — identity is by `name`, git ops by
119165
+ * `branch`.
119057
119166
  *
119058
119167
  * Called from two places today: the workspace-status upsert path in
119059
119168
  * `lib/state.ts::upsertWorkspaceStatus` (via the private
@@ -119063,7 +119172,7 @@ var WorkspaceQueries = class {
119063
119172
  * loading the full project tree.
119064
119173
  *
119065
119174
  * TODO: `toWorkspaceId`'s encoding is not injective — project `foo-bar` +
119066
- * branch `main` and project `foo` + branch `bar/main` both serialize to
119175
+ * name `main` and project `foo` + name `bar/main` both serialize to
119067
119176
  * `foo-bar-main`. `.get()` returns whichever row SQLite finds first, and
119068
119177
  * the sanity check below cannot disambiguate (both candidates satisfy
119069
119178
  * it). Fixing this requires changing the workspace-id encoding, which is
@@ -119073,12 +119182,13 @@ var WorkspaceQueries = class {
119073
119182
  const db2 = getDb();
119074
119183
  const row = db2.select({
119075
119184
  project: worktrees.projectName,
119185
+ name: worktrees.name,
119076
119186
  branch: worktrees.branch,
119077
119187
  worktreePath: worktrees.path
119078
119188
  }).from(worktrees).where(
119079
- sql`${worktrees.projectName} || '-' || REPLACE(${worktrees.branch}, '/', '-') = ${workspaceId}`
119189
+ sql`${worktrees.projectName} || '-' || REPLACE(${worktrees.name}, '/', '-') = ${workspaceId}`
119080
119190
  ).get();
119081
- if (row && toWorkspaceId(row.project, row.branch) === workspaceId) {
119191
+ if (row && toWorkspaceId(row.project, row.name) === workspaceId) {
119082
119192
  return { project: row.project, branch: row.branch, worktreePath: row.worktreePath };
119083
119193
  }
119084
119194
  return null;
@@ -119201,7 +119311,7 @@ function resolveWorkspaceIdByCwd(cwd) {
119201
119311
  for (const proj of state.projects) {
119202
119312
  for (const wt of proj.worktrees) {
119203
119313
  if (cwd === wt.path || cwd.startsWith(`${wt.path}/`)) {
119204
- return toWorkspaceId(proj.name, wt.branch);
119314
+ return toWorkspaceId(proj.name, wt.name);
119205
119315
  }
119206
119316
  }
119207
119317
  }
@@ -119275,13 +119385,17 @@ async function reconcileOneProject(project) {
119275
119385
  let diskWorktrees;
119276
119386
  try {
119277
119387
  const gitWorktrees = await listWorktrees(project.path);
119278
- const pinnedByBranch = new Map(project.worktrees.map((wt) => [wt.branch, wt.pinned]));
119279
- diskWorktrees = gitWorktrees.filter((wt) => !wt.isBare).map((wt) => ({
119280
- branch: wt.branch,
119281
- path: wt.path,
119282
- head: wt.head,
119283
- pinned: pinnedByBranch.get(wt.branch) ?? false
119284
- }));
119388
+ const existingByPath = new Map(project.worktrees.map((wt) => [wt.path, wt]));
119389
+ diskWorktrees = gitWorktrees.filter((wt) => !wt.isBare).map((wt) => {
119390
+ const existing = existingByPath.get(wt.path);
119391
+ return {
119392
+ name: existing?.name ?? wt.branch,
119393
+ branch: wt.branch,
119394
+ path: wt.path,
119395
+ head: wt.head,
119396
+ pinned: existing?.pinned ?? false
119397
+ };
119398
+ });
119285
119399
  } catch {
119286
119400
  if (project.hasOrigin) {
119287
119401
  setProjectHasOrigin(project.name, false);
@@ -119332,6 +119446,7 @@ var pollerState = {
119332
119446
  tickCount: 0,
119333
119447
  activity: "active"
119334
119448
  };
119449
+ var lastCIPollErrorByHost = /* @__PURE__ */ new Map();
119335
119450
  function getWorkspaces() {
119336
119451
  const state = loadState();
119337
119452
  const workspaces = [];
@@ -119339,7 +119454,7 @@ function getWorkspaces() {
119339
119454
  if (project.kind === "plain") continue;
119340
119455
  for (const wt of project.worktrees) {
119341
119456
  workspaces.push({
119342
- workspaceId: toWorkspaceId(project.name, wt.branch),
119457
+ workspaceId: toWorkspaceId(project.name, wt.name),
119343
119458
  project: project.name,
119344
119459
  branch: wt.branch,
119345
119460
  defaultBranch: project.defaultBranch,
@@ -119420,6 +119535,7 @@ async function getBatchedCIStatuses(workspaces) {
119420
119535
  }
119421
119536
  }
119422
119537
  if (resolved.length === 0) {
119538
+ lastCIPollErrorByHost.clear();
119423
119539
  const results = /* @__PURE__ */ new Map();
119424
119540
  for (const ws of workspaces) {
119425
119541
  results.set(ws.workspaceId, { state: "none" });
@@ -119466,13 +119582,21 @@ async function getBatchedCIStatuses(workspaces) {
119466
119582
  allResults.set(g15.ws.workspaceId, status);
119467
119583
  }
119468
119584
  }
119585
+ lastCIPollErrorByHost.delete(host);
119469
119586
  } catch (err) {
119470
- console.error(
119471
- `CI poll: GraphQL query failed for host (${group.length} workspaces):`,
119472
- err instanceof Error ? err.message : err
119473
- );
119587
+ const message = err instanceof Error ? err.message : String(err);
119588
+ if (lastCIPollErrorByHost.get(host) !== message) {
119589
+ lastCIPollErrorByHost.set(host, message);
119590
+ console.error(
119591
+ `CI poll: GraphQL query failed for host (${group.length} workspaces):`,
119592
+ message
119593
+ );
119594
+ }
119474
119595
  }
119475
119596
  }
119597
+ for (const host of [...lastCIPollErrorByHost.keys()]) {
119598
+ if (!byHost.has(host)) lastCIPollErrorByHost.delete(host);
119599
+ }
119476
119600
  for (const ws of workspaces) {
119477
119601
  if (!allResults.has(ws.workspaceId)) {
119478
119602
  allResults.set(ws.workspaceId, { state: "none" });
@@ -120412,7 +120536,7 @@ init_src();
120412
120536
  init_zod();
120413
120537
  import { execFile as execFile6 } from "node:child_process";
120414
120538
  import { randomUUID as randomUUID3 } from "node:crypto";
120415
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3 } from "node:fs";
120539
+ import { existsSync as existsSync9, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3 } from "node:fs";
120416
120540
  import { rm } from "node:fs/promises";
120417
120541
  import { join as join20 } from "node:path";
120418
120542
  import { promisify as promisify2 } from "node:util";
@@ -120683,52 +120807,6 @@ init_src();
120683
120807
  import { spawn as spawn6 } from "node:child_process";
120684
120808
  import { dirname as dirname2, join as join17, resolve as resolve3 } from "node:path";
120685
120809
  import { fileURLToPath } from "node:url";
120686
-
120687
- // src/server/infra/process/path.ts
120688
- import { execFile as execFile4 } from "node:child_process";
120689
- var cachedShellPath = null;
120690
- async function shellPath() {
120691
- if (cachedShellPath) return cachedShellPath;
120692
- const shell = process.env.SHELL || "/bin/zsh";
120693
- try {
120694
- const result = await new Promise((resolve12, reject) => {
120695
- execFile4(shell, ["-li", "-c", "echo $PATH"], { timeout: 5e3 }, (err, stdout) => {
120696
- if (err) {
120697
- reject(err);
120698
- return;
120699
- }
120700
- resolve12(stdout.trim());
120701
- });
120702
- });
120703
- if (result) {
120704
- cachedShellPath = result;
120705
- return result;
120706
- }
120707
- } catch {
120708
- }
120709
- const fallback = `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH || ""}`;
120710
- cachedShellPath = fallback;
120711
- return fallback;
120712
- }
120713
- async function whichBinary(name3) {
120714
- const resolvedPath = await shellPath();
120715
- try {
120716
- const result = await new Promise((resolve12, reject) => {
120717
- execFile4("which", [name3], { env: { ...process.env, PATH: resolvedPath } }, (err, stdout) => {
120718
- if (err) {
120719
- reject(err);
120720
- return;
120721
- }
120722
- resolve12(stdout.trim());
120723
- });
120724
- });
120725
- return result || null;
120726
- } catch {
120727
- return null;
120728
- }
120729
- }
120730
-
120731
- // src/server/infra/lsp/lsp-manager.ts
120732
120810
  var workspaceQueries = new WorkspaceQueries();
120733
120811
  var __dirname2 = dirname2(fileURLToPath(import.meta.url));
120734
120812
  var log16 = createLogger("lsp");
@@ -120828,7 +120906,7 @@ init_src();
120828
120906
  import { execFile as execFile5 } from "node:child_process";
120829
120907
  import {
120830
120908
  copyFileSync as copyFileSync2,
120831
- existsSync as existsSync6,
120909
+ existsSync as existsSync7,
120832
120910
  globSync,
120833
120911
  mkdirSync as mkdirSync4,
120834
120912
  readFileSync as readFileSync7,
@@ -120961,7 +121039,7 @@ function resolveFromConfig(projectPath, missing) {
120961
121039
  }
120962
121040
  async function resolveFromWorktreeInclude(projectPath) {
120963
121041
  const includePath = join18(projectPath, ".worktreeinclude");
120964
- if (!existsSync6(includePath)) return [];
121042
+ if (!existsSync7(includePath)) return [];
120965
121043
  const includeContent = readFileSync7(includePath, "utf-8");
120966
121044
  const hasPatterns = includeContent.split(/\r?\n/).some((line2) => {
120967
121045
  const trimmed = line2.trim();
@@ -122559,6 +122637,92 @@ var CronjobService = class {
122559
122637
  };
122560
122638
  var cronjobService = new CronjobService();
122561
122639
 
122640
+ // src/server/services/panel-focus-service.ts
122641
+ init_src();
122642
+ var log21 = createLogger("panel-focus-service");
122643
+ var PANEL_FOCUS_TYPE = "panel_focus";
122644
+ function focusRowId(workspaceId) {
122645
+ return `${PANEL_FOCUS_TYPE}:${workspaceId}`;
122646
+ }
122647
+ var PanelFocusService = class {
122648
+ /** workspaceId → last-focused panel ids. */
122649
+ focus = /* @__PURE__ */ new Map();
122650
+ /**
122651
+ * Workspaces whose focus row has been loaded from the DB into `focus`.
122652
+ * Separate from the map's own key presence because a workspace can have a
122653
+ * loaded-but-empty record (row absent) — we still don't want to re-hit the
122654
+ * DB on every read.
122655
+ */
122656
+ hydrated = /* @__PURE__ */ new Set();
122657
+ /** Workspaces that already have a `panel_states` row (drives insert vs update). */
122658
+ persisted = /* @__PURE__ */ new Set();
122659
+ /**
122660
+ * Load a workspace's focus row from the DB on first access. Cheap and
122661
+ * idempotent — subsequent calls short-circuit on the `hydrated` set.
122662
+ */
122663
+ ensureHydrated(workspaceId) {
122664
+ if (this.hydrated.has(workspaceId)) return;
122665
+ this.hydrated.add(workspaceId);
122666
+ const rows = listPanelStatesForWorkspace(workspaceId, PANEL_FOCUS_TYPE);
122667
+ const row = rows[0];
122668
+ if (!row) return;
122669
+ this.persisted.add(workspaceId);
122670
+ try {
122671
+ const parsed = JSON.parse(row.state);
122672
+ this.focus.set(workspaceId, {
122673
+ chat: parsed.chat,
122674
+ terminal: parsed.terminal,
122675
+ browser: parsed.browser
122676
+ });
122677
+ } catch (err) {
122678
+ log21.warn({ workspaceId, err }, "failed to parse persisted panel focus; ignoring");
122679
+ }
122680
+ }
122681
+ /** Get the last-focused panel ids for a workspace. */
122682
+ get(workspaceId) {
122683
+ this.ensureHydrated(workspaceId);
122684
+ return { ...this.focus.get(workspaceId) ?? {} };
122685
+ }
122686
+ /**
122687
+ * Record that `panelId` is the last-focused panel of `panelType` in
122688
+ * `workspaceId`. Write-through: updates the in-memory map and upserts the
122689
+ * backing `panel_states` row.
122690
+ */
122691
+ set(workspaceId, panelType, panelId) {
122692
+ this.ensureHydrated(workspaceId);
122693
+ const current2 = this.focus.get(workspaceId) ?? {};
122694
+ if (current2[panelType] === panelId) return;
122695
+ const next = { ...current2, [panelType]: panelId };
122696
+ this.focus.set(workspaceId, next);
122697
+ const now = Date.now();
122698
+ const state = JSON.stringify(next);
122699
+ if (this.persisted.has(workspaceId)) {
122700
+ updatePanelState(focusRowId(workspaceId), { state, updatedAt: now });
122701
+ } else {
122702
+ insertPanelState({
122703
+ id: focusRowId(workspaceId),
122704
+ workspaceId,
122705
+ panelType: PANEL_FOCUS_TYPE,
122706
+ state,
122707
+ createdAt: now,
122708
+ updatedAt: now
122709
+ });
122710
+ this.persisted.add(workspaceId);
122711
+ }
122712
+ }
122713
+ /**
122714
+ * Drop all focus tracking for a workspace. Called from the workspace delete
122715
+ * path so the row doesn't outlive the workspace.
122716
+ */
122717
+ remove(workspaceId) {
122718
+ this.focus.delete(workspaceId);
122719
+ this.hydrated.delete(workspaceId);
122720
+ this.persisted.delete(workspaceId);
122721
+ deletePanelState(focusRowId(workspaceId));
122722
+ }
122723
+ };
122724
+ var panelFocusService = new PanelFocusService();
122725
+
122562
122726
  // src/server/services/terminal-service.ts
122563
122727
  init_src();
122564
122728
  init_zod();
@@ -122566,10 +122730,10 @@ init_zod();
122566
122730
  // src/server/infra/terminals/terminal-pool.ts
122567
122731
  init_src();
122568
122732
  import { randomUUID as randomUUID2 } from "node:crypto";
122569
- import { existsSync as existsSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
122733
+ import { existsSync as existsSync8, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
122570
122734
  import { tmpdir } from "node:os";
122571
122735
  import { join as join19, sep as sep3 } from "node:path";
122572
- var log21 = createLogger("terminal-pool");
122736
+ var log22 = createLogger("terminal-pool");
122573
122737
  var MAX_SCROLLBACK_SIZE = 1e5;
122574
122738
  var TerminalPool = class {
122575
122739
  /** terminalId -> session */
@@ -122586,7 +122750,7 @@ var TerminalPool = class {
122586
122750
  * stays oblivious to the workspace registry.
122587
122751
  */
122588
122752
  async spawn(workspaceId, terminalId, workspaceRoot, options2) {
122589
- const shell = process.env.SHELL || "/bin/zsh";
122753
+ const shell = defaultShell();
122590
122754
  const resolvedPath = await shellPath();
122591
122755
  const env = {};
122592
122756
  for (const [key, value] of Object.entries(process.env)) {
@@ -122607,24 +122771,24 @@ var TerminalPool = class {
122607
122771
  if (options2?.cwd) {
122608
122772
  const resolved = join19(workspaceRoot, options2.cwd);
122609
122773
  if (resolved !== workspaceRoot && !resolved.startsWith(workspaceRoot + sep3)) {
122610
- log21.warn(
122774
+ log22.warn(
122611
122775
  "Ignoring cwd %s \u2014 resolves outside workspace root %s",
122612
122776
  options2.cwd,
122613
122777
  workspaceRoot
122614
122778
  );
122615
- } else if (existsSync7(resolved)) {
122779
+ } else if (existsSync8(resolved)) {
122616
122780
  cwd = resolved;
122617
122781
  } else {
122618
- log21.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
122782
+ log22.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
122619
122783
  }
122620
122784
  }
122621
- if (!existsSync7(cwd)) {
122785
+ if (!existsSync8(cwd)) {
122622
122786
  throw new Error(`Workspace directory does not exist: ${cwd}`);
122623
122787
  }
122624
- if (!existsSync7(shell)) {
122788
+ if (!existsSync8(shell)) {
122625
122789
  throw new Error(`Shell not found: ${shell}`);
122626
122790
  }
122627
- log21.debug(
122791
+ log22.debug(
122628
122792
  "Spawning shell %s in %s for terminal %s (PATH=%s)",
122629
122793
  shell,
122630
122794
  cwd,
@@ -122643,7 +122807,7 @@ var TerminalPool = class {
122643
122807
  });
122644
122808
  } catch (err) {
122645
122809
  const msg = err instanceof Error ? err.message : String(err);
122646
- log21.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
122810
+ log22.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
122647
122811
  throw err;
122648
122812
  }
122649
122813
  const session = { pty: ptyProcess, scrollback: "", workspaceId };
@@ -122673,7 +122837,7 @@ var TerminalPool = class {
122673
122837
  }
122674
122838
  });
122675
122839
  ptyProcess.onExit(() => {
122676
- log21.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
122840
+ log22.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
122677
122841
  this.terminals.delete(terminalId);
122678
122842
  this.outputListeners.delete(terminalId);
122679
122843
  const set = this.workspaceTerminals.get(workspaceId);
@@ -122728,7 +122892,7 @@ var TerminalPool = class {
122728
122892
  `, { encoding: "utf-8", mode: 384, flag: "wx" });
122729
122893
  session.autoRunFile = cmdFile;
122730
122894
  } catch (err) {
122731
- log21.warn(
122895
+ log22.warn(
122732
122896
  "autoRunCommand: temp-file staging failed (%s); writing command directly",
122733
122897
  err instanceof Error ? err.message : String(err)
122734
122898
  );
@@ -122746,7 +122910,7 @@ var TerminalPool = class {
122746
122910
  try {
122747
122911
  pty.write(sourceLine);
122748
122912
  } catch (err) {
122749
- log21.warn("autoRunCommand: failed to inject command line (%s)", err);
122913
+ log22.warn("autoRunCommand: failed to inject command line (%s)", err);
122750
122914
  }
122751
122915
  };
122752
122916
  let dataDisposed = false;
@@ -122925,7 +123089,7 @@ function removeTerminalFromLayout(workspaceId, terminalId) {
122925
123089
  }
122926
123090
 
122927
123091
  // src/server/services/terminal-service.ts
122928
- var log22 = createLogger("terminal-service");
123092
+ var log23 = createLogger("terminal-service");
122929
123093
  var TerminalPaneConfigSchema = external_exports.object({
122930
123094
  name: external_exports.string().optional(),
122931
123095
  command: external_exports.string().optional(),
@@ -123083,7 +123247,7 @@ var TerminalService = class {
123083
123247
  if (!terminalBlock) return null;
123084
123248
  const result = WorkspaceTerminalConfigSchema.safeParse(terminalBlock);
123085
123249
  if (!result.success) {
123086
- log22.warn(
123250
+ log23.warn(
123087
123251
  "Invalid workspace.terminal config: %s",
123088
123252
  result.error.issues.map((i2) => `${i2.path.join(".")}: ${i2.message}`).join("; ")
123089
123253
  );
@@ -123096,7 +123260,7 @@ var terminalService = new TerminalService();
123096
123260
 
123097
123261
  // src/server/services/workspace-service.ts
123098
123262
  var execFileAsync2 = promisify2(execFile6);
123099
- var log23 = createLogger("workspace-service");
123263
+ var log24 = createLogger("workspace-service");
123100
123264
  var workspaceVia = external_exports.enum(["chat", "terminal"]);
123101
123265
  var workspaceCreateInput = external_exports.object({
123102
123266
  project: external_exports.string(),
@@ -123116,16 +123280,20 @@ var workspaceCreateInput = external_exports.object({
123116
123280
  });
123117
123281
  var workspaceRemoveInput = external_exports.object({
123118
123282
  project: external_exports.string(),
123119
- branch: external_exports.string()
123283
+ // Workspace identity (the immutable `name`), NOT the live git branch. The
123284
+ // live branch to delete is resolved from the worktree row.
123285
+ name: external_exports.string()
123120
123286
  });
123121
123287
  var workspaceSetPinnedInput = external_exports.object({
123122
123288
  project: external_exports.string(),
123123
- branch: external_exports.string(),
123289
+ // Workspace identity (immutable `name`), not the live git branch.
123290
+ name: external_exports.string(),
123124
123291
  pinned: external_exports.boolean()
123125
123292
  });
123126
123293
  var workspaceGitInput = external_exports.object({
123127
123294
  project: external_exports.string(),
123128
- branch: external_exports.string()
123295
+ // Workspace identity (immutable `name`), not the live git branch.
123296
+ name: external_exports.string()
123129
123297
  });
123130
123298
  var workspaceRunScriptInput = external_exports.object({
123131
123299
  path: external_exports.string(),
@@ -123179,7 +123347,7 @@ var WorkspaceService = class {
123179
123347
  const state = loadState();
123180
123348
  for (const project of state.projects) {
123181
123349
  for (const worktree of project.worktrees) {
123182
- if (toWorkspaceId(project.name, worktree.branch) === workspaceId) {
123350
+ if (toWorkspaceId(project.name, worktree.name) === workspaceId) {
123183
123351
  return { project, worktree };
123184
123352
  }
123185
123353
  }
@@ -123255,7 +123423,9 @@ var WorkspaceService = class {
123255
123423
  `Project "${input.project}" is a plain (non-git) folder and cannot have additional workspaces. Promote it to git (right-click the project \u2192 "Promote to git") to enable branches.`
123256
123424
  );
123257
123425
  }
123258
- const existing = project.worktrees.find((wt) => wt.branch === input.branch);
123426
+ const existing = project.worktrees.find(
123427
+ (wt) => wt.name === input.branch || wt.branch === input.branch
123428
+ );
123259
123429
  if (existing) {
123260
123430
  return { ok: true, path: existing.path };
123261
123431
  }
@@ -123274,16 +123444,21 @@ var WorkspaceService = class {
123274
123444
  } catch (e2) {
123275
123445
  throw new Error(e2 instanceof Error ? e2.message : String(e2));
123276
123446
  }
123277
- project.worktrees.push({ branch: input.branch, path: worktreePath, pinned: false });
123447
+ project.worktrees.push({
123448
+ name: input.branch,
123449
+ branch: input.branch,
123450
+ path: worktreePath,
123451
+ pinned: false
123452
+ });
123278
123453
  saveState(state);
123279
123454
  const workspaceId = toWorkspaceId(input.project, input.branch);
123280
123455
  try {
123281
123456
  const copied = await copyWorkspaceFiles(project.path, worktreePath);
123282
123457
  if (copied.length > 0) {
123283
- log23.info({ workspaceId, count: copied.length }, "copied workspace files into new worktree");
123458
+ log24.info({ workspaceId, count: copied.length }, "copied workspace files into new worktree");
123284
123459
  }
123285
123460
  } catch (err) {
123286
- log23.warn({ err, workspaceId }, "copyWorkspaceFiles raised \u2014 continuing");
123461
+ log24.warn({ err, workspaceId }, "copyWorkspaceFiles raised \u2014 continuing");
123287
123462
  }
123288
123463
  const defaultChat = chatService.getOrCreateDefault(workspaceId);
123289
123464
  let via = input.via ?? "chat";
@@ -123296,7 +123471,7 @@ var WorkspaceService = class {
123296
123471
  adapter.abort?.();
123297
123472
  if (!invocation || invocation.unsupported) {
123298
123473
  const reason = invocation?.reason ?? "adapter does not expose cliInvocation";
123299
- log23.warn(
123474
+ log24.warn(
123300
123475
  { workspaceId, agentId: input.codingAgentId, reason },
123301
123476
  "via=terminal requested but adapter does not support it; falling back to chat"
123302
123477
  );
@@ -123306,7 +123481,7 @@ var WorkspaceService = class {
123306
123481
  terminalId = randomUUID3();
123307
123482
  }
123308
123483
  } catch (err) {
123309
- log23.warn(
123484
+ log24.warn(
123310
123485
  {
123311
123486
  err: err instanceof Error ? err.message : String(err),
123312
123487
  workspaceId,
@@ -123324,7 +123499,7 @@ var WorkspaceService = class {
123324
123499
  }).then(() => {
123325
123500
  emit({ kind: "terminal-created", workspaceId, terminalId });
123326
123501
  }).catch((err) => {
123327
- log23.error(
123502
+ log24.error(
123328
123503
  {
123329
123504
  err: err instanceof Error ? err.message : String(err),
123330
123505
  workspaceId,
@@ -123395,7 +123570,7 @@ var WorkspaceService = class {
123395
123570
  const terminalId = randomUUID3();
123396
123571
  await terminalService.spawn(chat.workspaceId, terminalId, { command });
123397
123572
  emit({ kind: "terminal-created", workspaceId: chat.workspaceId, terminalId });
123398
- log23.info(
123573
+ log24.info(
123399
123574
  { chatId, workspaceId: chat.workspaceId, terminalId },
123400
123575
  "continue chat session in terminal"
123401
123576
  );
@@ -123433,11 +123608,16 @@ var WorkspaceService = class {
123433
123608
  `Project "${input.project}" is a plain (non-git) project. Remove the project instead of the workspace.`
123434
123609
  );
123435
123610
  }
123611
+ const wtRow = project.worktrees.find((wt) => wt.name === input.name);
123612
+ if (!wtRow) {
123613
+ throw new WorkspaceNotFoundError(input.name);
123614
+ }
123615
+ const currentBranch = wtRow.branch;
123436
123616
  const { command, env: gitEnv } = gitCmd();
123437
123617
  const worktrees2 = await listWorktrees(project.path);
123438
- const match = worktrees2.find((wt) => wt.branch === input.branch);
123618
+ const match = worktrees2.find((wt) => wt.branch === currentBranch);
123439
123619
  if (!match) {
123440
- throw new WorkspaceNotFoundError(input.branch);
123620
+ throw new WorkspaceNotFoundError(input.name);
123441
123621
  }
123442
123622
  const worktreePath = match.path;
123443
123623
  let teardownCmd;
@@ -123448,9 +123628,9 @@ var WorkspaceService = class {
123448
123628
  }
123449
123629
  } catch {
123450
123630
  }
123451
- project.worktrees = project.worktrees.filter((wt) => wt.branch !== input.branch);
123631
+ project.worktrees = project.worktrees.filter((wt) => wt.name !== input.name);
123452
123632
  saveState(state);
123453
- const workspaceId = toWorkspaceId(input.project, input.branch);
123633
+ const workspaceId = toWorkspaceId(input.project, input.name);
123454
123634
  try {
123455
123635
  unlinkSync3(join20(bandHome(), "workspace-prompts", `${workspaceId}.json`));
123456
123636
  } catch {
@@ -123461,35 +123641,36 @@ var WorkspaceService = class {
123461
123641
  browserService.removeAllForWorkspace(workspaceId);
123462
123642
  terminalService.killWorkspace(workspaceId);
123463
123643
  terminalService.deleteLayout(workspaceId);
123644
+ panelFocusService.remove(workspaceId);
123464
123645
  killWorkspaceServers(workspaceId);
123465
123646
  cronjobService.removeForKey(workspaceId);
123466
123647
  try {
123467
123648
  const deletedTasks = new TaskQueries().deleteWorkspaceTasks(workspaceId);
123468
123649
  if (deletedTasks > 0) {
123469
- log23.info({ workspaceId, count: deletedTasks }, "deleted workspace tasks on removal");
123650
+ log24.info({ workspaceId, count: deletedTasks }, "deleted workspace tasks on removal");
123470
123651
  }
123471
123652
  } catch (err) {
123472
- log23.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
123653
+ log24.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
123473
123654
  }
123474
123655
  try {
123475
123656
  const deletedEvents = this.usageEventQueries.deleteWorkspaceEvents(workspaceId);
123476
123657
  if (deletedEvents > 0) {
123477
- log23.info(
123658
+ log24.info(
123478
123659
  { workspaceId, count: deletedEvents },
123479
123660
  "deleted workspace usage events on removal"
123480
123661
  );
123481
123662
  }
123482
123663
  } catch (err) {
123483
- log23.error({ workspaceId, err }, "failed to delete workspace usage events on removal");
123664
+ log24.error({ workspaceId, err }, "failed to delete workspace usage events on removal");
123484
123665
  }
123485
123666
  try {
123486
123667
  this.usageScanStateQueries.deleteWorkspace(workspaceId);
123487
123668
  } catch (err) {
123488
- log23.error({ workspaceId, err }, "failed to delete workspace usage scan state on removal");
123669
+ log24.error({ workspaceId, err }, "failed to delete workspace usage scan state on removal");
123489
123670
  }
123490
123671
  emit({ kind: "remove", workspaceId });
123491
123672
  const projPath = project.path;
123492
- const branchToDelete = match.branch.startsWith(DETACHED_BRANCH_PREFIX) ? null : input.branch;
123673
+ const branchToDelete = match.branch.startsWith(DETACHED_BRANCH_PREFIX) ? null : currentBranch;
123493
123674
  setImmediate(() => {
123494
123675
  (async () => {
123495
123676
  if (teardownCmd) {
@@ -123498,13 +123679,13 @@ var WorkspaceService = class {
123498
123679
  cwd: worktreePath,
123499
123680
  env: {
123500
123681
  ...process.env,
123501
- PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env.PATH}`
123682
+ PATH: prependBinDirs(process.env.PATH)
123502
123683
  },
123503
123684
  encoding: "utf-8",
123504
123685
  timeout: 6e4
123505
123686
  });
123506
123687
  } catch (err) {
123507
- log23.warn({ err, workspaceId }, "teardown script failed");
123688
+ log24.warn({ err, workspaceId }, "teardown script failed");
123508
123689
  }
123509
123690
  }
123510
123691
  try {
@@ -123517,7 +123698,7 @@ var WorkspaceService = class {
123517
123698
  try {
123518
123699
  await rm(worktreePath, { recursive: true, force: true });
123519
123700
  } catch (err) {
123520
- log23.warn({ err, workspaceId, worktreePath }, "manual worktree rm failed");
123701
+ log24.warn({ err, workspaceId, worktreePath }, "manual worktree rm failed");
123521
123702
  }
123522
123703
  try {
123523
123704
  await execFileAsync2(command, ["worktree", "prune"], {
@@ -123526,7 +123707,7 @@ var WorkspaceService = class {
123526
123707
  encoding: "utf-8"
123527
123708
  });
123528
123709
  } catch (err) {
123529
- log23.warn({ err, workspaceId }, "git worktree prune failed");
123710
+ log24.warn({ err, workspaceId }, "git worktree prune failed");
123530
123711
  }
123531
123712
  }
123532
123713
  if (branchToDelete) {
@@ -123540,7 +123721,7 @@ var WorkspaceService = class {
123540
123721
  }
123541
123722
  }
123542
123723
  })().catch((err) => {
123543
- log23.error({ err, workspaceId }, "background workspace cleanup failed");
123724
+ log24.error({ err, workspaceId }, "background workspace cleanup failed");
123544
123725
  });
123545
123726
  });
123546
123727
  return { ok: true };
@@ -123564,9 +123745,9 @@ var WorkspaceService = class {
123564
123745
  `Project "${input.project}" is a plain (non-git) project. Pinning is not available.`
123565
123746
  );
123566
123747
  }
123567
- const worktree = project.worktrees.find((w2) => w2.branch === input.branch);
123748
+ const worktree = project.worktrees.find((w2) => w2.name === input.name);
123568
123749
  if (!worktree) {
123569
- throw new WorkspaceNotFoundError(input.branch);
123750
+ throw new WorkspaceNotFoundError(input.name);
123570
123751
  }
123571
123752
  worktree.pinned = input.pinned;
123572
123753
  saveState(state);
@@ -123581,10 +123762,10 @@ var WorkspaceService = class {
123581
123762
  * case and a thrown error would surface as a red toast.
123582
123763
  */
123583
123764
  async gitPull(input) {
123584
- const workspaceId = toWorkspaceId(input.project, input.branch);
123765
+ const workspaceId = toWorkspaceId(input.project, input.name);
123585
123766
  const workspace = this.resolve(workspaceId);
123586
123767
  if (!workspace) {
123587
- throw new WorkspaceNotFoundError(input.branch);
123768
+ throw new WorkspaceNotFoundError(input.name);
123588
123769
  }
123589
123770
  if (workspace.project.kind === "plain") {
123590
123771
  throw new PlainProjectError(
@@ -123611,10 +123792,10 @@ var WorkspaceService = class {
123611
123792
  * a second failing push.
123612
123793
  */
123613
123794
  async gitPush(input) {
123614
- const workspaceId = toWorkspaceId(input.project, input.branch);
123795
+ const workspaceId = toWorkspaceId(input.project, input.name);
123615
123796
  const workspace = this.resolve(workspaceId);
123616
123797
  if (!workspace) {
123617
- throw new WorkspaceNotFoundError(input.branch);
123798
+ throw new WorkspaceNotFoundError(input.name);
123618
123799
  }
123619
123800
  if (workspace.project.kind === "plain") {
123620
123801
  throw new PlainProjectError(
@@ -123629,7 +123810,7 @@ var WorkspaceService = class {
123629
123810
  if (!/has no upstream branch/i.test(msg)) {
123630
123811
  throw err;
123631
123812
  }
123632
- await execGit(["push", "--set-upstream", "origin", input.branch], cwd);
123813
+ await execGit(["push", "--set-upstream", "origin", workspace.worktree.branch], cwd);
123633
123814
  }
123634
123815
  return { ok: true };
123635
123816
  }
@@ -123833,7 +124014,7 @@ var WorkspaceService = class {
123833
124014
  */
123834
124015
  async runScript(input) {
123835
124016
  const scriptPath = join20(input.path, ".band", input.scriptType);
123836
- if (!existsSync8(scriptPath)) {
124017
+ if (!existsSync9(scriptPath)) {
123837
124018
  throw new Error(`Script "${input.scriptType}" not found`);
123838
124019
  }
123839
124020
  try {
@@ -123847,7 +124028,7 @@ var WorkspaceService = class {
123847
124028
  var workspaceService = new WorkspaceService();
123848
124029
 
123849
124030
  // src/server/services/task-service.ts
123850
- var log24 = createLogger("task-service");
124031
+ var log25 = createLogger("task-service");
123851
124032
  var taskQueries = new TaskQueries();
123852
124033
  function listFiles(dir) {
123853
124034
  try {
@@ -123940,7 +124121,7 @@ function persistTask(task) {
123940
124121
  chatId: task.chatId
123941
124122
  });
123942
124123
  } catch (err) {
123943
- log24.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
124124
+ log25.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
123944
124125
  }
123945
124126
  }
123946
124127
  function broadcast(chatId, chunk) {
@@ -123964,7 +124145,7 @@ function broadcast(chatId, chunk) {
123964
124145
  }
123965
124146
  const subs = listeners2.get(chatId);
123966
124147
  if (!subs || subs.size === 0) {
123967
- log24.warn({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
124148
+ log25.debug({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
123968
124149
  return;
123969
124150
  }
123970
124151
  for (const listener of subs) {
@@ -124028,7 +124209,7 @@ function submitTask(options2) {
124028
124209
  });
124029
124210
  }
124030
124211
  runTask(chatId, task).catch((err) => {
124031
- log24.error({ chatId, err }, "task execution failed");
124212
+ log25.error({ chatId, err }, "task execution failed");
124032
124213
  if (task.status === "running") {
124033
124214
  task.status = "failed";
124034
124215
  task.completedAt = Date.now();
@@ -124070,7 +124251,7 @@ function abortTask(chatId) {
124070
124251
  chatService.updateStatus(chatId, "idle");
124071
124252
  const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
124072
124253
  emit({ kind: "update", status: updated });
124073
- log24.info({ chatId }, "task aborted by user");
124254
+ log25.info({ chatId }, "task aborted by user");
124074
124255
  return true;
124075
124256
  }
124076
124257
  function cancelTask(taskId) {
@@ -124095,7 +124276,7 @@ function cancelTask(taskId) {
124095
124276
  chatService.updateStatus(chatId, "idle");
124096
124277
  const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
124097
124278
  emit({ kind: "update", status: updated });
124098
- log24.info({ chatId, taskId }, "task cancelled (was running in-memory)");
124279
+ log25.info({ chatId, taskId }, "task cancelled (was running in-memory)");
124099
124280
  return { cancelled: true, workspaceId: task.workspaceId };
124100
124281
  }
124101
124282
  }
@@ -124103,7 +124284,7 @@ function cancelTask(taskId) {
124103
124284
  if (record2) {
124104
124285
  const updated = upsertWorkspaceStatus(record2.workspaceId, { status: "waiting" });
124105
124286
  emit({ kind: "update", status: updated });
124106
- log24.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
124287
+ log25.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
124107
124288
  return { cancelled: true, workspaceId: record2.workspaceId };
124108
124289
  }
124109
124290
  return { cancelled: false };
@@ -124123,7 +124304,7 @@ async function runTask(chatId, task) {
124123
124304
  const taskAgentId = task.codingAgentId;
124124
124305
  const resolvedAgentId = taskAgentId ?? chatSession?.agent;
124125
124306
  const needsReplace = taskAgentId && taskAgentId !== chatSession?.agent;
124126
- log24.info(
124307
+ log25.info(
124127
124308
  { chatId, taskAgentId, chatAgent: chatSession?.agent, resolvedAgentId, needsReplace },
124128
124309
  "resolving agent for task"
124129
124310
  );
@@ -124170,7 +124351,7 @@ async function runTask(chatId, task) {
124170
124351
  [File sharing: to send a file to the user, write or copy it to ${sharedDir}/ and it will appear as a downloadable file card in the chat.]`;
124171
124352
  const effectivePrompt = task.sessionId ? task.agentPrompt : task.agentPrompt + fileSharingHint;
124172
124353
  for await (const event of agent.runSession(effectivePrompt, task.sessionId, sessionOptions)) {
124173
- log24.info({ chatId, eventType: event.type }, "task event");
124354
+ log25.info({ chatId, eventType: event.type }, "task event");
124174
124355
  switch (event.type) {
124175
124356
  case "session-start": {
124176
124357
  task.sessionId = event.sessionId;
@@ -124370,7 +124551,7 @@ async function runTask(chatId, task) {
124370
124551
  break;
124371
124552
  }
124372
124553
  case "session-id-resolved": {
124373
- log24.info(
124554
+ log25.info(
124374
124555
  { chatId, previous: event.previousSessionId, resolved: event.resolvedSessionId },
124375
124556
  "session ID resolved"
124376
124557
  );
@@ -124473,7 +124654,7 @@ ${queued.text}`;
124473
124654
  });
124474
124655
  autoStarted = true;
124475
124656
  } catch (err) {
124476
- log24.warn({ chatId, err }, "failed to auto-start queued task");
124657
+ log25.warn({ chatId, err }, "failed to auto-start queued task");
124477
124658
  }
124478
124659
  }
124479
124660
  }
@@ -124648,7 +124829,7 @@ var taskService = new TaskService();
124648
124829
  var HISTORY_PAGE_SIZE = 50;
124649
124830
 
124650
124831
  // src/api/chat-events.ts
124651
- var log25 = createLogger("chat-events");
124832
+ var log26 = createLogger("chat-events");
124652
124833
  var COLD_REPLAY_LIMIT = HISTORY_PAGE_SIZE;
124653
124834
  async function handleChatEvents(req, res, chatId) {
124654
124835
  const url = new URL(req.url, `http://${req.headers.host}`);
@@ -124729,7 +124910,7 @@ async function handleChatEvents(req, res, chatId) {
124729
124910
  chatWorkspaceId: chat?.workspaceId ?? explicitWorkspaceId,
124730
124911
  agentTypeHint: chat?.agent
124731
124912
  }).catch((err) => {
124732
- log25.warn({ chatId, err }, "replay phase failed; continuing to live tail");
124913
+ log26.warn({ chatId, err }, "replay phase failed; continuing to live tail");
124733
124914
  });
124734
124915
  try {
124735
124916
  while (!res.destroyed && !writer.closed) {
@@ -124809,7 +124990,7 @@ async function replayPast(opts) {
124809
124990
  }
124810
124991
  }
124811
124992
  } catch (err) {
124812
- log25.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
124993
+ log26.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
124813
124994
  }
124814
124995
  }
124815
124996
  if (!jsonlEmittedAny && buf) {
@@ -124856,7 +125037,7 @@ async function replayPast(opts) {
124856
125037
  }
124857
125038
  }
124858
125039
  } catch (err) {
124859
- log25.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
125040
+ log26.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
124860
125041
  }
124861
125042
  }
124862
125043
  if (buf) {
@@ -124964,7 +125145,7 @@ function chunkToChatEvent(chunk, _sessionId) {
124964
125145
 
124965
125146
  // src/api/chat-history.ts
124966
125147
  init_src();
124967
- var log26 = createLogger("chat-history");
125148
+ var log27 = createLogger("chat-history");
124968
125149
  var DEFAULT_PAGE_LIMIT = HISTORY_PAGE_SIZE;
124969
125150
  var MAX_PAGE_LIMIT = 200;
124970
125151
  var MAX_CHAT_ID_LENGTH = 200;
@@ -125027,7 +125208,7 @@ async function handleChatHistory(req, res, chatId) {
125027
125208
  oldestOffset: result.firstOffset
125028
125209
  });
125029
125210
  } catch (err) {
125030
- log26.warn(
125211
+ log27.warn(
125031
125212
  { chatId: chatId.slice(0, 8), err: err instanceof Error ? err.message : String(err) },
125032
125213
  "chat-history: failed to read older page"
125033
125214
  );
@@ -125067,7 +125248,7 @@ async function saveUploadedFilesDetailed(fileParts) {
125067
125248
  }
125068
125249
 
125069
125250
  // src/api/chat-submit.ts
125070
- var log27 = createLogger("chat-submit");
125251
+ var log28 = createLogger("chat-submit");
125071
125252
  function readBody(req) {
125072
125253
  return new Promise((resolve12, reject) => {
125073
125254
  const chunks = [];
@@ -125104,7 +125285,7 @@ async function handleChatSubmit(req, res, chatId) {
125104
125285
  if (files && files.length > 0) {
125105
125286
  savedFiles = await saveUploadedFilesDetailed(files);
125106
125287
  if (savedFiles.length !== files.length) {
125107
- log27.warn(
125288
+ log28.warn(
125108
125289
  { chatId, submitted: files.length, saved: savedFiles.length },
125109
125290
  "chat-submit: some file uploads were dropped (malformed data URL?)"
125110
125291
  );
@@ -125134,7 +125315,7 @@ ${text3}`;
125134
125315
  model,
125135
125316
  codingAgentId
125136
125317
  });
125137
- log27.info({ chatId, workspaceId }, "chat-submit: task started");
125318
+ log28.info({ chatId, workspaceId }, "chat-submit: task started");
125138
125319
  sendJson2(res, 200, { ok: true, queued: false });
125139
125320
  } catch (err) {
125140
125321
  if (err instanceof TaskConflictError) {
@@ -125149,7 +125330,7 @@ ${text3}`;
125149
125330
  }))
125150
125331
  }
125151
125332
  });
125152
- log27.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
125333
+ log28.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
125153
125334
  sendJson2(res, 200, { ok: true, queued: true });
125154
125335
  return;
125155
125336
  }
@@ -125157,7 +125338,7 @@ ${text3}`;
125157
125338
  sendJson2(res, 404, { error: err.message });
125158
125339
  return;
125159
125340
  }
125160
- log27.error({ chatId, err }, "chat-submit: unexpected error");
125341
+ log28.error({ chatId, err }, "chat-submit: unexpected error");
125161
125342
  sendJson2(res, 500, { error: "Internal server error" });
125162
125343
  }
125163
125344
  }
@@ -136563,7 +136744,7 @@ import { extname as extname2, isAbsolute as isAbsolute2 } from "node:path";
136563
136744
 
136564
136745
  // src/server/infra/browser-host/host-state.ts
136565
136746
  init_src();
136566
- var log28 = createLogger("browser-host");
136747
+ var log29 = createLogger("browser-host");
136567
136748
  var DESKTOP_CDP_HOST = "127.0.0.1";
136568
136749
  var DESKTOP_CDP_PORT = 9223;
136569
136750
  var globalAny = globalThis;
@@ -136614,7 +136795,7 @@ async function ensureCdpTargetId(bandTabId) {
136614
136795
  reject: rejectFn,
136615
136796
  timeoutId
136616
136797
  });
136617
- log28.info(
136798
+ log29.info(
136618
136799
  "ensureCdpTargetId emitting ensureView for %s (url=%s, listeners=%d)",
136619
136800
  bandTabId,
136620
136801
  tab.url,
@@ -136628,13 +136809,13 @@ async function ensureCdpTargetId(bandTabId) {
136628
136809
  url: tab.url
136629
136810
  });
136630
136811
  } catch (err) {
136631
- log28.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
136812
+ log29.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
136632
136813
  }
136633
136814
  }
136634
136815
  return promise;
136635
136816
  }
136636
136817
  function resolveTargetReady(bandTabId, cdpTargetId) {
136637
- log28.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
136818
+ log29.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
136638
136819
  targetIdByBandTabId.set(bandTabId, cdpTargetId);
136639
136820
  const pending2 = pendingEnsures.get(bandTabId);
136640
136821
  if (pending2) {
@@ -136644,7 +136825,7 @@ function resolveTargetReady(bandTabId, cdpTargetId) {
136644
136825
  }
136645
136826
  }
136646
136827
  function markTargetDestroyed(bandTabId) {
136647
- log28.info("markTargetDestroyed %s", bandTabId);
136828
+ log29.info("markTargetDestroyed %s", bandTabId);
136648
136829
  targetIdByBandTabId.delete(bandTabId);
136649
136830
  const pending2 = pendingEnsures.get(bandTabId);
136650
136831
  if (pending2) {
@@ -136655,10 +136836,10 @@ function markTargetDestroyed(bandTabId) {
136655
136836
  }
136656
136837
  function onEnsureView(listener) {
136657
136838
  ensureListeners.add(listener);
136658
- log28.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
136839
+ log29.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
136659
136840
  return () => {
136660
136841
  ensureListeners.delete(listener);
136661
- log28.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
136842
+ log29.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
136662
136843
  if (ensureListeners.size === 0) {
136663
136844
  for (const [bandTabId, pending2] of pendingEnsures) {
136664
136845
  clearTimeout(pending2.timeoutId);
@@ -136698,7 +136879,7 @@ var t2 = initTRPC.context().create();
136698
136879
  var publicProcedure = t2.procedure;
136699
136880
 
136700
136881
  // src/server/api/browser-host/router.ts
136701
- var log29 = createLogger("trpc.browser-host");
136882
+ var log30 = createLogger("trpc.browser-host");
136702
136883
  var MAX_FILE_SIZE = 1024 * 1024;
136703
136884
  var LANG_MAP = {
136704
136885
  ".js": "javascript",
@@ -136821,7 +137002,7 @@ var browserHostRouter = t2.router({
136821
137002
  // can confirm in the server log that the bridge component actually
136822
137003
  // executed. Drop once the experiment is stable.
136823
137004
  ping: publicProcedure.input(external_exports.object({ where: external_exports.string() })).mutation(({ input }) => {
136824
- log29.info("browserHost.ping from %s", input.where);
137005
+ log30.info("browserHost.ping from %s", input.where);
136825
137006
  return { ok: true };
136826
137007
  }),
136827
137008
  ensureView: publicProcedure.subscription(async function* (opts) {
@@ -136941,7 +137122,7 @@ var chatRouter = t2.router({
136941
137122
  // src/server/api/chats/router.ts
136942
137123
  init_src();
136943
137124
  init_zod();
136944
- var log30 = createLogger("chats-router");
137125
+ var log31 = createLogger("chats-router");
136945
137126
  var chatLayoutRouter = t2.router({
136946
137127
  get: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string() })).query(({ input }) => {
136947
137128
  return { tree: chatService.getLayout(input.workspaceId) };
@@ -137086,7 +137267,7 @@ var chatsRouter = t2.router({
137086
137267
  summary = info?.summary;
137087
137268
  lastModified = info?.lastModified;
137088
137269
  } catch (err) {
137089
- log30.warn(
137270
+ log31.warn(
137090
137271
  { chatId: input.chatId, sessionId: input.sessionId, err },
137091
137272
  "setActiveSession: getSessionInfo failed"
137092
137273
  );
@@ -137391,7 +137572,7 @@ function throwAsTRPCError(err) {
137391
137572
  init_zod();
137392
137573
 
137393
137574
  // src/server/services/editor-service.ts
137394
- import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync8 } from "node:fs";
137575
+ import { existsSync as existsSync11, realpathSync as realpathSync5, statSync as statSync8 } from "node:fs";
137395
137576
  import { isAbsolute as isAbsolute4, join as join25, resolve as resolve6, sep as sep4 } from "node:path";
137396
137577
 
137397
137578
  // src/server/services/file-watcher.ts
@@ -137488,10 +137669,10 @@ function subscribeToFileChanges(workspaceId, listener) {
137488
137669
 
137489
137670
  // src/server/services/formatter.ts
137490
137671
  init_src();
137491
- import { existsSync as existsSync9, realpathSync as realpathSync4 } from "node:fs";
137672
+ import { existsSync as existsSync10, realpathSync as realpathSync4 } from "node:fs";
137492
137673
  import { basename, dirname as dirname5, isAbsolute as isAbsolute3, join as join24, resolve as resolvePath } from "node:path";
137493
137674
  import prettier from "prettier";
137494
- var log31 = createLogger("formatter");
137675
+ var log32 = createLogger("formatter");
137495
137676
  var FormatterError = class extends Error {
137496
137677
  code;
137497
137678
  detail;
@@ -137515,7 +137696,7 @@ async function formatFile(worktreePath, filePath, content2, options2 = {}) {
137515
137696
  const ignorePath = resolvePath(worktreePath, ".prettierignore");
137516
137697
  const info = await prettier.getFileInfo(absFile, {
137517
137698
  resolveConfig: true,
137518
- ignorePath: existsSync9(ignorePath) ? ignorePath : void 0
137699
+ ignorePath: existsSync10(ignorePath) ? ignorePath : void 0
137519
137700
  });
137520
137701
  if (info.ignored) {
137521
137702
  return {
@@ -137546,7 +137727,7 @@ async function formatFile(worktreePath, filePath, content2, options2 = {}) {
137546
137727
  }
137547
137728
  const changed = formatted !== content2;
137548
137729
  if (changed) {
137549
- log31.info(
137730
+ log32.info(
137550
137731
  "Formatted %s with parser=%s (%d bytes in)",
137551
137732
  absFile,
137552
137733
  info.inferredParser,
@@ -137699,7 +137880,7 @@ var EditorOpenError = class extends Error {
137699
137880
  }
137700
137881
  };
137701
137882
  function canonicalizeMaybeMissing(p6) {
137702
- if (existsSync10(p6)) {
137883
+ if (existsSync11(p6)) {
137703
137884
  try {
137704
137885
  return realpathSync5(p6);
137705
137886
  } catch {
@@ -137709,7 +137890,7 @@ function canonicalizeMaybeMissing(p6) {
137709
137890
  const parts = p6.split(sep4);
137710
137891
  for (let i2 = parts.length - 1; i2 > 0; i2--) {
137711
137892
  const prefix = parts.slice(0, i2).join(sep4) || sep4;
137712
- if (existsSync10(prefix)) {
137893
+ if (existsSync11(prefix)) {
137713
137894
  try {
137714
137895
  const canonicalPrefix = realpathSync5(prefix);
137715
137896
  return join25(canonicalPrefix, ...parts.slice(i2));
@@ -138101,8 +138282,19 @@ var SystemService = class {
138101
138282
  * `$PATH` (typically via `shellPath()`) so `brew` itself is locatable
138102
138283
  * even when the Node process inherited a stripped-down PATH from
138103
138284
  * launchd / Electron.
138285
+ *
138286
+ * Homebrew is macOS-only here: a stock Linux host has no `brew`, so
138287
+ * shelling out to it would fail with an opaque ENOENT. Guard on
138288
+ * `darwin` and surface a distro-appropriate hint on every other
138289
+ * platform — the message bubbles up to the dashboard's install flow as
138290
+ * a normal error instead of a crash.
138104
138291
  */
138105
138292
  async installCloudflared(resolvedPath) {
138293
+ if (process.platform !== "darwin") {
138294
+ throw new Error(
138295
+ "Automatic cloudflared install is only supported on macOS (via Homebrew). On Linux, install it with your package manager (e.g. `sudo apt install cloudflared` or `sudo dnf install cloudflared`) or download it from https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/ and re-open the tunnel."
138296
+ );
138297
+ }
138106
138298
  await brewInstall("cloudflared", resolvedPath);
138107
138299
  }
138108
138300
  /**
@@ -138241,7 +138433,7 @@ init_zod();
138241
138433
 
138242
138434
  // src/server/services/model-refresh-service.ts
138243
138435
  init_src();
138244
- var log32 = createLogger("model-refresh");
138436
+ var log33 = createLogger("model-refresh");
138245
138437
  var ModelRefreshService = class {
138246
138438
  constructor(queries = new SettingsQueries()) {
138247
138439
  this.queries = queries;
@@ -138294,7 +138486,7 @@ var ModelRefreshService = class {
138294
138486
  const models = await agent.listModels();
138295
138487
  return models.map(toCachedModel);
138296
138488
  } catch (err) {
138297
- log32.warn({ agentId, err }, "failed to load adapter defaults; returning empty list");
138489
+ log33.warn({ agentId, err }, "failed to load adapter defaults; returning empty list");
138298
138490
  return [];
138299
138491
  }
138300
138492
  }
@@ -138331,7 +138523,7 @@ var ModelRefreshService = class {
138331
138523
  }
138332
138524
  } catch (err) {
138333
138525
  error2 = classifyRefreshError(err);
138334
- log32.warn({ agentId, err }, "failed to refresh models; keeping prior cache");
138526
+ log33.warn({ agentId, err }, "failed to refresh models; keeping prior cache");
138335
138527
  }
138336
138528
  if (fresh) {
138337
138529
  const cachedFresh = fresh.map(toCachedModel);
@@ -138459,7 +138651,7 @@ var ModelRefreshService = class {
138459
138651
  const agents = this.queries.load().codingAgents ?? [];
138460
138652
  const idx = agents.findIndex((a6) => a6.id === agentId);
138461
138653
  if (idx === -1) {
138462
- log32.warn({ agentId }, "refresh result for unknown agent; not persisting");
138654
+ log33.warn({ agentId }, "refresh result for unknown agent; not persisting");
138463
138655
  return false;
138464
138656
  }
138465
138657
  const next = agents.map(
@@ -138537,6 +138729,25 @@ var modesRouter = t2.router({
138537
138729
  })
138538
138730
  });
138539
138731
 
138732
+ // src/server/api/panel-focus/router.ts
138733
+ init_zod();
138734
+ var focusPanelType = external_exports.enum(["chat", "terminal", "browser"]);
138735
+ var panelFocusRouter = t2.router({
138736
+ get: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string() })).query(({ input }) => {
138737
+ return panelFocusService.get(input.workspaceId);
138738
+ }),
138739
+ set: publicProcedure.input(
138740
+ external_exports.object({
138741
+ workspaceId: external_exports.string(),
138742
+ panelType: focusPanelType,
138743
+ panelId: external_exports.string()
138744
+ })
138745
+ ).mutation(({ input }) => {
138746
+ panelFocusService.set(input.workspaceId, input.panelType, input.panelId);
138747
+ return { ok: true };
138748
+ })
138749
+ });
138750
+
138540
138751
  // src/server/api/prereqs/router.ts
138541
138752
  var prereqsRouter = t2.router({
138542
138753
  check: publicProcedure.query(async () => {
@@ -138553,7 +138764,7 @@ var prereqsRouter = t2.router({
138553
138764
  init_zod();
138554
138765
 
138555
138766
  // src/server/services/project-service.ts
138556
- import { existsSync as existsSync11 } from "node:fs";
138767
+ import { existsSync as existsSync12 } from "node:fs";
138557
138768
  import { basename as basename2, join as join27, resolve as resolve7 } from "node:path";
138558
138769
  var ProjectService = class {
138559
138770
  constructor(queries = new ProjectQueries(), git = new GitClient(), settings = settingsService, statusQueries = new WorkspaceStatusQueries()) {
@@ -138590,16 +138801,22 @@ var ProjectService = class {
138590
138801
  projects2.map(async (project) => {
138591
138802
  let worktrees2 = project.worktrees;
138592
138803
  if (project.kind === "git") {
138593
- const trackedBranches = new Set(project.worktrees.map((wt) => wt.branch));
138594
- const trackedByBranch = new Map(project.worktrees.map((wt) => [wt.branch, wt]));
138804
+ const trackedByPath = new Map(project.worktrees.map((wt) => [wt.path, wt]));
138595
138805
  try {
138596
138806
  const gitWorktrees = await this.git.listWorktrees(project.path);
138597
- worktrees2 = gitWorktrees.filter((wt) => !wt.isBare && trackedBranches.has(wt.branch)).map((wt) => ({
138598
- branch: wt.branch,
138599
- path: wt.path,
138600
- head: wt.head,
138601
- pinned: trackedByBranch.get(wt.branch)?.pinned ?? false
138602
- }));
138807
+ worktrees2 = gitWorktrees.filter((wt) => !wt.isBare && trackedByPath.has(wt.path)).map((wt) => {
138808
+ const tracked2 = trackedByPath.get(wt.path);
138809
+ return {
138810
+ // Carry the stable identity from the tracked row; fall back
138811
+ // to the branch for worktrees git knows about but state
138812
+ // doesn't.
138813
+ name: tracked2?.name ?? wt.branch,
138814
+ branch: wt.branch,
138815
+ path: wt.path,
138816
+ head: wt.head,
138817
+ pinned: tracked2?.pinned ?? false
138818
+ };
138819
+ });
138603
138820
  } catch {
138604
138821
  }
138605
138822
  }
@@ -138610,7 +138827,7 @@ var ProjectService = class {
138610
138827
  label: project.label,
138611
138828
  kind: project.kind,
138612
138829
  worktrees: worktrees2.map((wt) => {
138613
- const workspaceId = toWorkspaceId(project.name, wt.branch);
138830
+ const workspaceId = toWorkspaceId(project.name, wt.name);
138614
138831
  const status = statusMap.get(workspaceId);
138615
138832
  return {
138616
138833
  ...wt,
@@ -138630,7 +138847,7 @@ var ProjectService = class {
138630
138847
  */
138631
138848
  checkPath(path3) {
138632
138849
  const resolvedPath = resolve7(path3);
138633
- const isGitRepo = existsSync11(join27(resolvedPath, ".git"));
138850
+ const isGitRepo = existsSync12(join27(resolvedPath, ".git"));
138634
138851
  return { isGitRepo };
138635
138852
  }
138636
138853
  /**
@@ -138666,7 +138883,7 @@ var ProjectService = class {
138666
138883
  }
138667
138884
  }
138668
138885
  const resolvedPath = resolve7(path3);
138669
- const kind = existsSync11(join27(resolvedPath, ".git")) ? "git" : "plain";
138886
+ const kind = existsSync12(join27(resolvedPath, ".git")) ? "git" : "plain";
138670
138887
  let defaultBranch = "main";
138671
138888
  let worktrees2 = [];
138672
138889
  if (kind === "git") {
@@ -138674,11 +138891,17 @@ var ProjectService = class {
138674
138891
  if (branch) defaultBranch = branch;
138675
138892
  try {
138676
138893
  const gitWorktrees = await this.git.listWorktrees(resolvedPath);
138677
- worktrees2 = gitWorktrees.filter((wt) => !wt.isBare).map((wt) => ({ branch: wt.branch, path: wt.path, head: wt.head, pinned: false }));
138894
+ worktrees2 = gitWorktrees.filter((wt) => !wt.isBare).map((wt) => ({
138895
+ name: wt.branch,
138896
+ branch: wt.branch,
138897
+ path: wt.path,
138898
+ head: wt.head,
138899
+ pinned: false
138900
+ }));
138678
138901
  } catch {
138679
138902
  }
138680
138903
  } else {
138681
- worktrees2 = [{ branch: "main", path: resolvedPath, pinned: false }];
138904
+ worktrees2 = [{ name: "main", branch: "main", path: resolvedPath, pinned: false }];
138682
138905
  }
138683
138906
  const project = {
138684
138907
  name: name3,
@@ -138724,7 +138947,7 @@ var ProjectService = class {
138724
138947
  message: `Project "${name3}" is already a git project`
138725
138948
  });
138726
138949
  }
138727
- if (!existsSync11(project.path)) {
138950
+ if (!existsSync12(project.path)) {
138728
138951
  throw new TRPCError({
138729
138952
  code: "NOT_FOUND",
138730
138953
  message: `Project path "${project.path}" no longer exists. Remove the project and re-add it.`
@@ -138842,7 +139065,7 @@ init_src();
138842
139065
  init_zod();
138843
139066
  import { realpathSync as realpathSync6 } from "node:fs";
138844
139067
  import { join as join28, resolve as resolve8, sep as sep5 } from "node:path";
138845
- var log33 = createLogger("trpc.queue");
139068
+ var log34 = createLogger("trpc.queue");
138846
139069
  var queuedFileSchema = external_exports.object({
138847
139070
  mediaType: external_exports.string(),
138848
139071
  url: external_exports.string(),
@@ -138874,7 +139097,7 @@ async function resolveQueuedFiles(chatId, files) {
138874
139097
  const derivedPath = file.path ?? (uploadsUrlMatch ? join28(bandHome(), "uploads", uploadsUrlMatch[1]) : void 0);
138875
139098
  if (derivedPath) {
138876
139099
  if (!isPathWithinUploadDir(derivedPath)) {
138877
- log33.warn(
139100
+ log34.warn(
138878
139101
  { chatId, path: derivedPath, filename: file.filename },
138879
139102
  "queue: dropping file with path outside uploads directory"
138880
139103
  );
@@ -138899,7 +139122,7 @@ async function resolveQueuedFiles(chatId, files) {
138899
139122
  });
138900
139123
  continue;
138901
139124
  }
138902
- log33.warn(
139125
+ log34.warn(
138903
139126
  { chatId, url: file.url, filename: file.filename },
138904
139127
  "queue: dropping file with no path and non-data URL \u2014 cannot recover disk path"
138905
139128
  );
@@ -138907,7 +139130,7 @@ async function resolveQueuedFiles(chatId, files) {
138907
139130
  if (needsSave.length > 0) {
138908
139131
  const saved = await saveUploadedFilesDetailed(needsSave);
138909
139132
  if (saved.length !== needsSave.length) {
138910
- log33.error(
139133
+ log34.error(
138911
139134
  { chatId, expected: needsSave.length, got: saved.length },
138912
139135
  "queue: saveUploadedFilesDetailed returned unexpected count \u2014 dropping data-URL files (cannot map 1:1)"
138913
139136
  );
@@ -138940,7 +139163,7 @@ var queueRouter = t2.router({
138940
139163
  try {
138941
139164
  files = await resolveQueuedFiles(chatId, input.files);
138942
139165
  } catch (err) {
138943
- log33.error(
139166
+ log34.error(
138944
139167
  { chatId, err: err instanceof Error ? err.message : err },
138945
139168
  "queue.push: failed to persist file uploads; enqueuing text only"
138946
139169
  );
@@ -138976,7 +139199,7 @@ var queueRouter = t2.router({
138976
139199
  files: await resolveQueuedFiles(chatId, m11.files)
138977
139200
  };
138978
139201
  } catch (err) {
138979
- log33.error(
139202
+ log34.error(
138980
139203
  { chatId, messageId: m11.id, err: err instanceof Error ? err.message : err },
138981
139204
  "queue: failed to resolve files for queued message; dropping its files"
138982
139205
  );
@@ -139101,7 +139324,7 @@ function aggregateTurnsByHourAndModel(snap, provider) {
139101
139324
  }
139102
139325
  return Array.from(buckets2.values());
139103
139326
  }
139104
- var log34 = createLogger("usage-scanner");
139327
+ var log35 = createLogger("usage-scanner");
139105
139328
  var SCHEDULER_KEY2 = Symbol.for("band.usage-scanner");
139106
139329
  var g14 = globalThis;
139107
139330
  if (!g14[SCHEDULER_KEY2]) {
@@ -139163,14 +139386,14 @@ var UsageScannerService = class {
139163
139386
  try {
139164
139387
  totalRows += await this.scanPair(ws, a6);
139165
139388
  } catch (err) {
139166
- log34.warn(
139389
+ log35.warn(
139167
139390
  { err, workspaceId: ws.workspaceId, agentType: a6.agentType },
139168
139391
  "usage scanner pair failed"
139169
139392
  );
139170
139393
  }
139171
139394
  }
139172
139395
  }
139173
- log34.debug(
139396
+ log35.debug(
139174
139397
  { durationMs: this.now() - started, workspaces: workspaces.length, rowsWritten: totalRows },
139175
139398
  "usage scanner tick complete"
139176
139399
  );
@@ -139215,7 +139438,7 @@ var UsageScannerService = class {
139215
139438
  try {
139216
139439
  agent = await this.createWorkspaceAgent(ws.worktreePath, a6.agentId);
139217
139440
  } catch (err) {
139218
- log34.debug({ err, agentId: a6.agentId }, "failed to instantiate agent for scan");
139441
+ log35.debug({ err, agentId: a6.agentId }, "failed to instantiate agent for scan");
139219
139442
  return 0;
139220
139443
  }
139221
139444
  if (!agent.listSessions || !agent.getSessionUsage) return 0;
@@ -139224,7 +139447,7 @@ var UsageScannerService = class {
139224
139447
  try {
139225
139448
  sessions = await agent.listSessions(ws.worktreePath);
139226
139449
  } catch (err) {
139227
- log34.debug(
139450
+ log35.debug(
139228
139451
  { err, agentId: a6.agentId, worktreePath: ws.worktreePath },
139229
139452
  "listSessions failed during usage scan"
139230
139453
  );
@@ -139240,7 +139463,7 @@ var UsageScannerService = class {
139240
139463
  try {
139241
139464
  snap = await agent.getSessionUsage(s6.sessionId, ws.worktreePath);
139242
139465
  } catch (err) {
139243
- log34.debug(
139466
+ log35.debug(
139244
139467
  { err, sessionId: s6.sessionId, agentType: a6.agentType },
139245
139468
  "getSessionUsage failed"
139246
139469
  );
@@ -139278,7 +139501,7 @@ var UsageScannerService = class {
139278
139501
  this.scanState.set(ws.workspaceId, a6.agentType, maxObserved);
139279
139502
  }
139280
139503
  if (changed.length > slice.length) {
139281
- log34.debug(
139504
+ log35.debug(
139282
139505
  {
139283
139506
  workspaceId: ws.workspaceId,
139284
139507
  agentType: a6.agentType,
@@ -139297,7 +139520,7 @@ function defaultListWorkspaces() {
139297
139520
  for (const project of projects2) {
139298
139521
  for (const worktree of project.worktrees) {
139299
139522
  out.push({
139300
- workspaceId: toWorkspaceId(project.name, worktree.branch),
139523
+ workspaceId: toWorkspaceId(project.name, worktree.name),
139301
139524
  project: project.name,
139302
139525
  worktreePath: worktree.path
139303
139526
  });
@@ -139333,11 +139556,11 @@ function startUsageScanner(options2 = {}) {
139333
139556
  const intervalMs = options2.intervalMs ?? USAGE_SCAN_INTERVAL_MS;
139334
139557
  const svc = getUsageScannerService();
139335
139558
  svc.tick().catch((err) => {
139336
- log34.warn({ err }, "initial usage scanner tick failed");
139559
+ log35.warn({ err }, "initial usage scanner tick failed");
139337
139560
  });
139338
139561
  const timer = setInterval(() => {
139339
139562
  svc.tick().catch((err) => {
139340
- log34.warn({ err }, "scheduled usage scanner tick failed");
139563
+ log35.warn({ err }, "scheduled usage scanner tick failed");
139341
139564
  });
139342
139565
  }, intervalMs);
139343
139566
  timer.unref();
@@ -139459,7 +139682,7 @@ init_zod();
139459
139682
 
139460
139683
  // src/server/services/session-service.ts
139461
139684
  init_src();
139462
- var log35 = createLogger("session-service");
139685
+ var log36 = createLogger("session-service");
139463
139686
  var SessionService = class {
139464
139687
  /**
139465
139688
  * List past sessions for a workspace's chat pane.
@@ -139479,7 +139702,7 @@ var SessionService = class {
139479
139702
  if (!agent.supportedFeatures.sessionListing || !agent.listSessions) {
139480
139703
  return { sessions: [], supported: false };
139481
139704
  }
139482
- log35.debug({ chatId, workspaceId: input.workspaceId }, "listing past sessions for chat");
139705
+ log36.debug({ chatId, workspaceId: input.workspaceId }, "listing past sessions for chat");
139483
139706
  const allSessions = await agent.listSessions(workspace.worktree.path);
139484
139707
  return { sessions: allSessions, supported: true };
139485
139708
  }
@@ -139635,7 +139858,7 @@ function getToken() {
139635
139858
  }
139636
139859
 
139637
139860
  // src/server/infra/tunnels/tunnel-client.ts
139638
- var log36 = createLogger("tunnel");
139861
+ var log37 = createLogger("tunnel");
139639
139862
  var TunnelClient = class _TunnelClient {
139640
139863
  tunnelProcess = null;
139641
139864
  tunnelUrl = null;
@@ -139659,7 +139882,7 @@ var TunnelClient = class _TunnelClient {
139659
139882
  }
139660
139883
  spawnTunnel(options2, resolvedPath) {
139661
139884
  const args = ["tunnel", "--config", "/dev/null", "--url", `http://localhost:${options2.port}`];
139662
- log36.debug("spawning cloudflared %s", args.join(" "));
139885
+ log37.debug("spawning cloudflared %s", args.join(" "));
139663
139886
  return new Promise((resolve12, reject) => {
139664
139887
  const child = spawn7("cloudflared", args, {
139665
139888
  env: { ...process.env, PATH: resolvedPath },
@@ -139673,12 +139896,12 @@ var TunnelClient = class _TunnelClient {
139673
139896
  for (const line2 of text3.split("\n")) {
139674
139897
  const trimmed = line2.trim();
139675
139898
  if (!trimmed) continue;
139676
- log36.debug("output: %s", trimmed);
139899
+ log37.debug("output: %s", trimmed);
139677
139900
  const url = _TunnelClient.extractUrl(trimmed);
139678
139901
  if (url) {
139679
139902
  const token = getToken();
139680
139903
  this.tunnelUrl = _TunnelClient.appendToken(url, token);
139681
- log36.debug("detected URL: %s", this.tunnelUrl);
139904
+ log37.debug("detected URL: %s", this.tunnelUrl);
139682
139905
  emit({ kind: "tunnel-url", url: this.tunnelUrl });
139683
139906
  if (!settled) {
139684
139907
  settled = true;
@@ -139693,7 +139916,7 @@ var TunnelClient = class _TunnelClient {
139693
139916
  handleOutput(data);
139694
139917
  });
139695
139918
  child.on("error", (err) => {
139696
- log36.debug("process error: %s", err.message);
139919
+ log37.debug("process error: %s", err.message);
139697
139920
  this.tunnelProcess = null;
139698
139921
  this.tunnelUrl = null;
139699
139922
  emit({ kind: "tunnel-error", error: err.message });
@@ -139703,7 +139926,7 @@ var TunnelClient = class _TunnelClient {
139703
139926
  }
139704
139927
  });
139705
139928
  child.on("exit", (code) => {
139706
- log36.debug("process exited with code: %d", code ?? -1);
139929
+ log37.debug("process exited with code: %d", code ?? -1);
139707
139930
  const wasRunning = this.tunnelProcess !== null && settled;
139708
139931
  this.tunnelProcess = null;
139709
139932
  this.tunnelUrl = null;
@@ -139725,7 +139948,7 @@ var TunnelClient = class _TunnelClient {
139725
139948
  });
139726
139949
  setTimeout(() => {
139727
139950
  if (!settled) {
139728
- log36.debug("30s timeout reached, resolving without URL");
139951
+ log37.debug("30s timeout reached, resolving without URL");
139729
139952
  settled = true;
139730
139953
  resolve12();
139731
139954
  }
@@ -139734,12 +139957,12 @@ var TunnelClient = class _TunnelClient {
139734
139957
  }
139735
139958
  async start(options2) {
139736
139959
  if (this.startInProgress) {
139737
- log36.debug("start: start already in progress, waiting...");
139960
+ log37.debug("start: start already in progress, waiting...");
139738
139961
  await this.startInProgress;
139739
139962
  return;
139740
139963
  }
139741
139964
  if (this.tunnelProcess) {
139742
- log36.debug("start: already running, re-emitting URL");
139965
+ log37.debug("start: already running, re-emitting URL");
139743
139966
  if (this.tunnelUrl) {
139744
139967
  emit({ kind: "tunnel-url", url: this.tunnelUrl });
139745
139968
  }
@@ -139804,7 +140027,7 @@ var TunnelService = class {
139804
140027
  var tunnelService = new TunnelService();
139805
140028
 
139806
140029
  // src/server/api/system/router.ts
139807
- var log37 = createLogger("trpc.system");
140030
+ var log38 = createLogger("trpc.system");
139808
140031
  var systemRouter = t2.router({
139809
140032
  /**
139810
140033
  * Combined liveness probe — webserver is always true if this query
@@ -139812,15 +140035,15 @@ var systemRouter = t2.router({
139812
140035
  * an interval to drive the bottom-bar status pill.
139813
140036
  */
139814
140037
  health: publicProcedure.query(() => {
139815
- log37.debug("services.health called");
140038
+ log38.debug("services.health called");
139816
140039
  const tunnel = tunnelService.getStatus();
139817
- log37.debug({ tunnel }, "services.health: tunnel status");
140040
+ log38.debug({ tunnel }, "services.health: tunnel status");
139818
140041
  const result = {
139819
140042
  webserver: true,
139820
140043
  tunnel: tunnel.running,
139821
140044
  tunnel_url: tunnel.url
139822
140045
  };
139823
- log37.debug({ result }, "services.health result");
140046
+ log38.debug({ result }, "services.health result");
139824
140047
  return result;
139825
140048
  }),
139826
140049
  // Activity level controls how often the branch-status poller fires.
@@ -139938,7 +140161,7 @@ var systemRouter = t2.router({
139938
140161
  // src/server/api/tasks/router.ts
139939
140162
  init_src();
139940
140163
  init_zod();
139941
- var log38 = createLogger("tasks-router");
140164
+ var log39 = createLogger("tasks-router");
139942
140165
  var tasksRouter = t2.router({
139943
140166
  list: publicProcedure.input(
139944
140167
  external_exports.object({
@@ -139954,7 +140177,7 @@ var tasksRouter = t2.router({
139954
140177
  const workspaceIds = /* @__PURE__ */ new Set();
139955
140178
  for (const p6 of state.projects) {
139956
140179
  for (const wt of p6.worktrees) {
139957
- workspaceIds.add(toWorkspaceId(p6.name, wt.branch));
140180
+ workspaceIds.add(toWorkspaceId(p6.name, wt.name));
139958
140181
  }
139959
140182
  }
139960
140183
  return {
@@ -140001,7 +140224,7 @@ var tasksRouter = t2.router({
140001
140224
  if (input.files && input.files.length > 0) {
140002
140225
  const savedFiles = await saveUploadedFilesDetailed(input.files);
140003
140226
  if (savedFiles.length !== input.files.length) {
140004
- log38.warn(
140227
+ log39.warn(
140005
140228
  { chatId, submitted: input.files.length, saved: savedFiles.length },
140006
140229
  "tasks.submit: some file uploads were dropped (malformed data URL?)"
140007
140230
  );
@@ -140223,25 +140446,25 @@ var terminalsRouters = {
140223
140446
  // src/server/api/tunnel/router.ts
140224
140447
  init_src();
140225
140448
  init_zod();
140226
- var log39 = createLogger("trpc.tunnel");
140449
+ var log40 = createLogger("trpc.tunnel");
140227
140450
  var tunnelRouter = t2.router({
140228
140451
  status: publicProcedure.query(() => {
140229
140452
  return tunnelService.getStatus();
140230
140453
  }),
140231
140454
  start: publicProcedure.input(external_exports.object({}).optional()).mutation(async () => {
140232
- log39.debug("tunnel.start called");
140455
+ log40.debug("tunnel.start called");
140233
140456
  try {
140234
140457
  await tunnelService.start();
140235
140458
  } catch (err) {
140236
- log39.debug({ err }, "tunnel.start: startTunnel failed");
140459
+ log40.debug({ err }, "tunnel.start: startTunnel failed");
140237
140460
  return { ok: true, url: null };
140238
140461
  }
140239
140462
  const status = tunnelService.getStatus();
140240
- log39.debug({ status }, "tunnel.start: after startTunnel");
140463
+ log40.debug({ status }, "tunnel.start: after startTunnel");
140241
140464
  if (status.url) {
140242
140465
  return { ok: true, url: status.url };
140243
140466
  }
140244
- log39.debug("tunnel.start: no URL available");
140467
+ log40.debug("tunnel.start: no URL available");
140245
140468
  return { ok: true, url: null };
140246
140469
  }),
140247
140470
  stop: publicProcedure.mutation(async () => {
@@ -140255,10 +140478,10 @@ init_zod();
140255
140478
 
140256
140479
  // src/server/services/diff-service.ts
140257
140480
  init_src();
140258
- import { existsSync as existsSync12 } from "node:fs";
140481
+ import { existsSync as existsSync13 } from "node:fs";
140259
140482
  import { readFile as readFile2, rm as rm2 } from "node:fs/promises";
140260
140483
  import { join as join29, resolve as resolve9, sep as sep6 } from "node:path";
140261
- var log40 = createLogger("diff-service");
140484
+ var log41 = createLogger("diff-service");
140262
140485
  var EMPTY_TREE_ARGS = ["hash-object", "-t", "tree", "/dev/null"];
140263
140486
  var EMPTY_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
140264
140487
  async function resolveDiffContext(cwd, defaultBranch, diffMode, compareBranchInput) {
@@ -140363,7 +140586,7 @@ var DiffService = class {
140363
140586
  );
140364
140587
  branches = output.trim().split("\n").map((b10) => b10.trim()).filter(Boolean);
140365
140588
  } catch (err) {
140366
- log40.error(
140589
+ log41.error(
140367
140590
  `listBranches: for-each-ref failed for ${cwd}: ${err instanceof Error ? err.message : err}`
140368
140591
  );
140369
140592
  }
@@ -140462,7 +140685,7 @@ var DiffService = class {
140462
140685
  async getDiffSummary(workspaceId, options2) {
140463
140686
  const workspace = this.workspaces.resolve(workspaceId);
140464
140687
  if (!workspace) throw new WorkspaceNotFoundError(workspaceId);
140465
- const hasGit = existsSync12(join29(workspace.worktree.path, ".git"));
140688
+ const hasGit = existsSync13(join29(workspace.worktree.path, ".git"));
140466
140689
  if (workspace.project.kind === "plain" || !hasGit) {
140467
140690
  const defaultBranch2 = workspace.project.defaultBranch;
140468
140691
  return {
@@ -140594,7 +140817,7 @@ var DiffService = class {
140594
140817
  var diffService = new DiffService();
140595
140818
 
140596
140819
  // src/server/services/files-service.ts
140597
- import { existsSync as existsSync13 } from "node:fs";
140820
+ import { existsSync as existsSync14 } from "node:fs";
140598
140821
  import { cp, mkdir as mkdir2, readdir as readdir2, readFile as readFile3, rename, rm as rm3, stat as stat4, writeFile as writeFile2 } from "node:fs/promises";
140599
140822
  import { dirname as dirname7, extname as extname3, join as join30, resolve as resolve10, sep as sep7 } from "node:path";
140600
140823
  var MAX_FILE_SIZE2 = 1024 * 1024;
@@ -140713,11 +140936,11 @@ var FilesService = class {
140713
140936
  async createFile(workspaceId, path3, content2 = "") {
140714
140937
  const { root, target } = this.resolveInside(workspaceId, path3, { allowRoot: false });
140715
140938
  this.assertNotGitInternals(root, target, "create");
140716
- if (existsSync13(target)) {
140939
+ if (existsSync14(target)) {
140717
140940
  throw new Error("A file or directory already exists at this path");
140718
140941
  }
140719
140942
  const parent = dirname7(target);
140720
- if (!existsSync13(parent)) {
140943
+ if (!existsSync14(parent)) {
140721
140944
  throw new Error("Parent directory does not exist");
140722
140945
  }
140723
140946
  const parentStat = await stat4(parent);
@@ -140730,11 +140953,11 @@ var FilesService = class {
140730
140953
  async createDirectory(workspaceId, path3) {
140731
140954
  const { root, target } = this.resolveInside(workspaceId, path3, { allowRoot: false });
140732
140955
  this.assertNotGitInternals(root, target, "create");
140733
- if (existsSync13(target)) {
140956
+ if (existsSync14(target)) {
140734
140957
  throw new Error("A file or directory already exists at this path");
140735
140958
  }
140736
140959
  const parent = dirname7(target);
140737
- if (!existsSync13(parent)) {
140960
+ if (!existsSync14(parent)) {
140738
140961
  throw new Error("Parent directory does not exist");
140739
140962
  }
140740
140963
  const parentStat = await stat4(parent);
@@ -140775,11 +140998,11 @@ var FilesService = class {
140775
140998
  } catch {
140776
140999
  throw new Error("Source path does not exist");
140777
141000
  }
140778
- if (existsSync13(toTarget)) {
141001
+ if (existsSync14(toTarget)) {
140779
141002
  throw new Error("A file or directory already exists at the destination");
140780
141003
  }
140781
141004
  const toParent = dirname7(toTarget);
140782
- if (!existsSync13(toParent)) {
141005
+ if (!existsSync14(toParent)) {
140783
141006
  throw new Error("Destination parent directory does not exist");
140784
141007
  }
140785
141008
  const toParentStat = await stat4(toParent);
@@ -140811,11 +141034,11 @@ var FilesService = class {
140811
141034
  if (entryStat.isDirectory() && toTarget.startsWith(fromTarget + sep7)) {
140812
141035
  throw new Error("Cannot copy a directory into itself");
140813
141036
  }
140814
- if (existsSync13(toTarget)) {
141037
+ if (existsSync14(toTarget)) {
140815
141038
  throw new Error("A file or directory already exists at the destination");
140816
141039
  }
140817
141040
  const toParent = dirname7(toTarget);
140818
- if (!existsSync13(toParent)) {
141041
+ if (!existsSync14(toParent)) {
140819
141042
  throw new Error("Destination parent directory does not exist");
140820
141043
  }
140821
141044
  const toParentStat = await stat4(toParent);
@@ -142344,6 +142567,7 @@ var appRouter = t2.router({
142344
142567
  chat: chatRouter,
142345
142568
  browsers: browsersRouter,
142346
142569
  browserLayout: browserLayoutRouter,
142570
+ panelFocus: panelFocusRouter,
142347
142571
  tasks: tasksRouter,
142348
142572
  sessions: sessionsRouter,
142349
142573
  ...terminalsRouters,
@@ -142479,7 +142703,7 @@ function getScalarHtml(specUrl) {
142479
142703
 
142480
142704
  // src/server/api/terminals/ws.ts
142481
142705
  init_src();
142482
- var log41 = createLogger("terminal-ws");
142706
+ var log42 = createLogger("terminal-ws");
142483
142707
  var MAX_CLOSE_REASON_BYTES = 123;
142484
142708
  var HEARTBEAT_INTERVAL_MS2 = 3e4;
142485
142709
  function clampCloseReason(reason) {
@@ -142551,7 +142775,7 @@ async function handleTerminalConnection(ws, req) {
142551
142775
  session = await terminalService.spawn(workspaceId, terminalId, spawnOpts);
142552
142776
  } catch (err) {
142553
142777
  const msg = err instanceof Error ? err.message : String(err);
142554
- log41.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
142778
+ log42.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
142555
142779
  safeClose(ws, 4001, msg);
142556
142780
  return;
142557
142781
  }
@@ -142565,7 +142789,7 @@ async function handleTerminalConnection(ws, req) {
142565
142789
  });
142566
142790
  }
142567
142791
  function attachSession(ws, terminalId, workspaceId, session, isNew) {
142568
- log41.debug(
142792
+ log42.debug(
142569
142793
  "Terminal %s: %s (workspace %s)",
142570
142794
  isNew ? "connected" : "reconnected",
142571
142795
  terminalId,
@@ -142594,7 +142818,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
142594
142818
  }, 3e3);
142595
142819
  const exitDisposable = session.pty.onExit(({ exitCode }) => {
142596
142820
  clearInterval(processInterval);
142597
- log41.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
142821
+ log42.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
142598
142822
  if (ws.readyState === ws.OPEN) {
142599
142823
  ws.close(1e3, "Terminal exited");
142600
142824
  }
@@ -142622,7 +142846,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
142622
142846
  clearInterval(pingInterval);
142623
142847
  dataDisposable.dispose();
142624
142848
  exitDisposable.dispose();
142625
- log41.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
142849
+ log42.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
142626
142850
  });
142627
142851
  }
142628
142852
  function handleMessage(ws, terminalId, session, message) {
@@ -142658,7 +142882,7 @@ function stripTerminalQueries(data) {
142658
142882
 
142659
142883
  // src/server/infra/browser-host/cdp-proxy.ts
142660
142884
  init_src();
142661
- var log42 = createLogger("cdp-proxy");
142885
+ var log43 = createLogger("cdp-proxy");
142662
142886
  async function handleCdpConnection(ws, req) {
142663
142887
  const url = new URL(req.url ?? "", `http://${req.headers.host}`);
142664
142888
  const bandTabId = url.searchParams.get("bandTabId");
@@ -142681,17 +142905,17 @@ async function handleCdpConnection(ws, req) {
142681
142905
  cdpTargetId = await ensureCdpTargetId(bandTabId);
142682
142906
  } catch (err) {
142683
142907
  const message = err instanceof Error ? err.message : String(err);
142684
- log42.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
142908
+ log43.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
142685
142909
  if (ws.readyState === ws.OPEN) {
142686
142910
  ws.close(4001, message.slice(0, 123));
142687
142911
  }
142688
142912
  return;
142689
142913
  }
142690
142914
  const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
142691
- log42.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
142915
+ log43.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
142692
142916
  upstream = new wrapper_default(upstreamUrl);
142693
142917
  upstream.on("open", () => {
142694
- log42.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
142918
+ log43.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
142695
142919
  for (const msg of pending2) {
142696
142920
  upstream?.send(msg);
142697
142921
  }
@@ -142703,20 +142927,20 @@ async function handleCdpConnection(ws, req) {
142703
142927
  }
142704
142928
  });
142705
142929
  upstream.on("error", (err) => {
142706
- log42.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
142930
+ log43.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
142707
142931
  markTargetDestroyed(bandTabId);
142708
142932
  if (ws.readyState === ws.OPEN) {
142709
142933
  ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
142710
142934
  }
142711
142935
  });
142712
142936
  upstream.on("close", (code) => {
142713
- log42.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
142937
+ log43.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
142714
142938
  if (ws.readyState === ws.OPEN) {
142715
142939
  ws.close(1e3, "Upstream closed");
142716
142940
  }
142717
142941
  });
142718
142942
  ws.on("close", () => {
142719
- log42.debug("CDP client closed bandTabId=%s", bandTabId);
142943
+ log43.debug("CDP client closed bandTabId=%s", bandTabId);
142720
142944
  if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
142721
142945
  try {
142722
142946
  upstream.close();
@@ -142725,7 +142949,7 @@ async function handleCdpConnection(ws, req) {
142725
142949
  }
142726
142950
  });
142727
142951
  ws.on("error", (err) => {
142728
- log42.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
142952
+ log43.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
142729
142953
  try {
142730
142954
  upstream?.close();
142731
142955
  } catch {
@@ -142735,7 +142959,7 @@ async function handleCdpConnection(ws, req) {
142735
142959
 
142736
142960
  // src/server/infra/browser-host/cdp-targets.ts
142737
142961
  init_src();
142738
- var log43 = createLogger("cdp-targets");
142962
+ var log44 = createLogger("cdp-targets");
142739
142963
  var CdpUnreachableError = class extends Error {
142740
142964
  constructor(message) {
142741
142965
  super(message);
@@ -142791,7 +143015,7 @@ async function captureSnapshot(bandTabId) {
142791
143015
  });
142792
143016
  ws.on("error", (err) => {
142793
143017
  clearTimeout(timeout);
142794
- log43.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
143018
+ log44.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
142795
143019
  markTargetDestroyed(bandTabId);
142796
143020
  settle(new CdpUnreachableError(err.message));
142797
143021
  });
@@ -142811,7 +143035,7 @@ function runMigrations() {
142811
143035
 
142812
143036
  // src/server/infra/lsp/lsp-proxy.ts
142813
143037
  init_src();
142814
- var log44 = createLogger("lsp-proxy");
143038
+ var log45 = createLogger("lsp-proxy");
142815
143039
  function frameMessage(json2) {
142816
143040
  const body = Buffer.from(json2, "utf-8");
142817
143041
  const header = `Content-Length: ${body.byteLength}\r
@@ -142829,7 +143053,7 @@ function createFrameParser(onMessage) {
142829
143053
  const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
142830
143054
  const match = headerStr.match(/Content-Length:\s*(\d+)/i);
142831
143055
  if (!match) {
142832
- log44.warn("Malformed LSP header: %s", headerStr);
143056
+ log45.warn("Malformed LSP header: %s", headerStr);
142833
143057
  buffer = buffer.subarray(separatorIdx + 4);
142834
143058
  continue;
142835
143059
  }
@@ -142862,7 +143086,7 @@ async function handleLspConnection(ws, req) {
142862
143086
  session = await getOrSpawnServer(workspaceId, lang);
142863
143087
  } catch (err) {
142864
143088
  const message = err instanceof Error ? err.message : String(err);
142865
- log44.error(
143089
+ log45.error(
142866
143090
  "Failed to spawn %s language server for workspace %s: %s",
142867
143091
  lang,
142868
143092
  workspaceId,
@@ -142876,12 +143100,12 @@ async function handleLspConnection(ws, req) {
142876
143100
  ws.close(4002, "Language server stdio not available");
142877
143101
  return;
142878
143102
  }
142879
- log44.debug("LSP client connected: %s/%s", workspaceId, lang);
143103
+ log45.debug("LSP client connected: %s/%s", workspaceId, lang);
142880
143104
  const pendingRequests = /* @__PURE__ */ new Map();
142881
143105
  const retriedIds = /* @__PURE__ */ new Set();
142882
143106
  const RETRY_DELAY_MS = 2e3;
142883
143107
  const parseFrame = createFrameParser((json2) => {
142884
- log44.debug(
143108
+ log45.debug(
142885
143109
  "LSP stdout [%s/%s]: %s",
142886
143110
  workspaceId,
142887
143111
  lang,
@@ -142893,7 +143117,7 @@ async function handleLspConnection(ws, req) {
142893
143117
  const originalRequest = pendingRequests.get(msg.id);
142894
143118
  retriedIds.add(msg.id);
142895
143119
  pendingRequests.delete(msg.id);
142896
- log44.debug(
143120
+ log45.debug(
142897
143121
  "LSP retrying request %d after 'No Project' error [%s/%s]",
142898
143122
  msg.id,
142899
143123
  workspaceId,
@@ -142915,14 +143139,14 @@ async function handleLspConnection(ws, req) {
142915
143139
  const onStdoutData = (chunk) => parseFrame(chunk);
142916
143140
  lspProcess.stdout.on("data", onStdoutData);
142917
143141
  const onExit = (code) => {
142918
- log44.debug("LSP server exited (code %s), closing WebSocket", String(code));
143142
+ log45.debug("LSP server exited (code %s), closing WebSocket", String(code));
142919
143143
  if (ws.readyState === ws.OPEN) {
142920
143144
  ws.close(1e3, "Language server exited");
142921
143145
  }
142922
143146
  };
142923
143147
  lspProcess.on("exit", onExit);
142924
143148
  function forwardToStdin(json2) {
142925
- log44.debug(
143149
+ log45.debug(
142926
143150
  "LSP stdin [%s/%s]: %s",
142927
143151
  workspaceId,
142928
143152
  lang,
@@ -142949,7 +143173,7 @@ async function handleLspConnection(ws, req) {
142949
143173
  ws.on("close", () => {
142950
143174
  lspProcess.stdout?.off("data", onStdoutData);
142951
143175
  lspProcess.off("exit", onExit);
142952
- log44.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
143176
+ log45.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
142953
143177
  });
142954
143178
  }
142955
143179
 
@@ -143097,7 +143321,7 @@ async function installSkills(opts = {}) {
143097
143321
  }
143098
143322
 
143099
143323
  // src/server/services/setup-service.ts
143100
- var log45 = createLogger("setup");
143324
+ var log46 = createLogger("setup");
143101
143325
  var AGENT_CHECKS = [
143102
143326
  { id: "claude-code", type: "claude-code", label: "Claude Code", binary: "claude" },
143103
143327
  { id: "codex", type: "codex", label: "Codex", binary: "codex" },
@@ -143114,7 +143338,7 @@ async function runFirstTimeSetup() {
143114
143338
  ]);
143115
143339
  for (const r6 of results) {
143116
143340
  if (r6.status === "rejected") {
143117
- log45.warn(
143341
+ log46.warn(
143118
143342
  "Setup step failed: %s",
143119
143343
  r6.reason instanceof Error ? r6.reason.message : String(r6.reason)
143120
143344
  );
@@ -143128,7 +143352,7 @@ async function refreshAgentModelsInBackground() {
143128
143352
  const ok2 = results.filter((r6) => !r6.error).length;
143129
143353
  const failed = results.length - ok2;
143130
143354
  if (results.length > 0) {
143131
- log45.info(
143355
+ log46.info(
143132
143356
  "Background model refresh: %d/%d agents updated (%d failed)",
143133
143357
  ok2,
143134
143358
  results.length,
@@ -143136,7 +143360,7 @@ async function refreshAgentModelsInBackground() {
143136
143360
  );
143137
143361
  }
143138
143362
  } catch (err) {
143139
- log45.warn(
143363
+ log46.warn(
143140
143364
  "Background model refresh failed: %s",
143141
143365
  err instanceof Error ? err.message : String(err)
143142
143366
  );
@@ -143150,7 +143374,7 @@ async function ensureProjectStateInSync() {
143150
143374
  try {
143151
143375
  await syncService.syncWorktrees();
143152
143376
  } catch (err) {
143153
- log45.warn(
143377
+ log46.warn(
143154
143378
  "Failed to sync project state at boot: %s",
143155
143379
  err instanceof Error ? err.message : String(err)
143156
143380
  );
@@ -143161,22 +143385,22 @@ async function ensureCliInstalled() {
143161
143385
  try {
143162
143386
  cliStatus = await checkCli();
143163
143387
  } catch (err) {
143164
- log45.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
143388
+ log46.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
143165
143389
  return;
143166
143390
  }
143167
143391
  if (cliStatus === "Installed") {
143168
143392
  return;
143169
143393
  }
143170
143394
  if (cliStatus !== "NotInstalled") {
143171
- log45.warn("CLI not auto-installed (status: %s)", cliStatus);
143395
+ log46.warn("CLI not auto-installed (status: %s)", cliStatus);
143172
143396
  return;
143173
143397
  }
143174
- log45.info("Installing band CLI...");
143398
+ log46.info("Installing band CLI...");
143175
143399
  try {
143176
143400
  await installCli();
143177
- log45.info("CLI installed to /usr/local/bin/band");
143401
+ log46.info("CLI installed to /usr/local/bin/band");
143178
143402
  } catch (err) {
143179
- log45.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
143403
+ log46.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
143180
143404
  }
143181
143405
  }
143182
143406
  async function ensureDefaultCodingAgents() {
@@ -143185,17 +143409,17 @@ async function ensureDefaultCodingAgents() {
143185
143409
  if (Array.isArray(existing) && existing.length > 0) {
143186
143410
  return;
143187
143411
  }
143188
- log45.info("Detecting installed coding agents...");
143412
+ log46.info("Detecting installed coding agents...");
143189
143413
  const detected = [];
143190
143414
  for (const check2 of AGENT_CHECKS) {
143191
143415
  const path3 = await systemService.whichBinary(check2.binary);
143192
143416
  if (path3) {
143193
- log45.info("Detected coding agent: %s (%s)", check2.id, path3);
143417
+ log46.info("Detected coding agent: %s (%s)", check2.id, path3);
143194
143418
  detected.push({ id: check2.id, type: check2.type, label: check2.label });
143195
143419
  }
143196
143420
  }
143197
143421
  if (detected.length === 0) {
143198
- log45.info("No coding agent CLIs detected on PATH");
143422
+ log46.info("No coding agent CLIs detected on PATH");
143199
143423
  return;
143200
143424
  }
143201
143425
  const current2 = loadSettings();
@@ -143204,7 +143428,7 @@ async function ensureDefaultCodingAgents() {
143204
143428
  current2.defaultCodingAgent = detected[0].id;
143205
143429
  }
143206
143430
  saveSettings(current2);
143207
- log45.info("Enabled %d coding agent(s); default = %s", detected.length, current2.defaultCodingAgent);
143431
+ log46.info("Enabled %d coding agent(s); default = %s", detected.length, current2.defaultCodingAgent);
143208
143432
  }
143209
143433
  function ensureNotificationDefaults() {
143210
143434
  const settings = loadSettings();
@@ -143216,7 +143440,7 @@ function ensureNotificationDefaults() {
143216
143440
  ...settings,
143217
143441
  notifications: { ...notifications, soundOnNeedsAttention: true }
143218
143442
  });
143219
- log45.info("Set default notifications.soundOnNeedsAttention = true");
143443
+ log46.info("Set default notifications.soundOnNeedsAttention = true");
143220
143444
  }
143221
143445
  async function ensureClaudeHooks() {
143222
143446
  try {
@@ -143225,9 +143449,9 @@ async function ensureClaudeHooks() {
143225
143449
  return;
143226
143450
  }
143227
143451
  await installHooks();
143228
- log45.info("Installed Claude Code hooks");
143452
+ log46.info("Installed Claude Code hooks");
143229
143453
  } catch (err) {
143230
- log45.warn(
143454
+ log46.warn(
143231
143455
  "Failed to install Claude Code hooks: %s",
143232
143456
  err instanceof Error ? err.message : String(err)
143233
143457
  );
@@ -143235,11 +143459,11 @@ async function ensureClaudeHooks() {
143235
143459
  }
143236
143460
  async function ensureSkillsInstalled() {
143237
143461
  try {
143238
- const result = await installSkills({ log: log45 });
143462
+ const result = await installSkills({ log: log46 });
143239
143463
  const wrote = result.written.length + result.updated.length;
143240
143464
  const linkChange = result.linked.length;
143241
143465
  if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
143242
- log45.info(
143466
+ log46.info(
143243
143467
  "Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
143244
143468
  result.written.length,
143245
143469
  result.updated.length,
@@ -143251,7 +143475,7 @@ async function ensureSkillsInstalled() {
143251
143475
  );
143252
143476
  }
143253
143477
  } catch (err) {
143254
- log45.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
143478
+ log46.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
143255
143479
  }
143256
143480
  }
143257
143481
  var SetupService = class {