@band-app/server 0.20.0 → 0.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/dist/client/assets/DockviewBrowserContainer-DqC_h-bo.js +5 -0
  2. package/dist/client/assets/{DockviewTerminalContainer-CqH5m62N.js → DockviewTerminalContainer-DyBQtb3U.js} +2 -2
  3. package/dist/client/assets/TerminalPanel-CFDxHN4Q.js +5 -0
  4. package/dist/client/assets/{_basePickBy-CosPBGEe.js → _basePickBy-Dcf1Y8Iq.js} +1 -1
  5. package/dist/client/assets/{_baseUniq-CNCpSB0P.js → _baseUniq-Cy98IGsx.js} +1 -1
  6. package/dist/client/assets/{arc-UDGCZidA.js → arc-rOBphWj1.js} +1 -1
  7. package/dist/client/assets/{architectureDiagram-VXUJARFQ-CeS1u1s5.js → architectureDiagram-VXUJARFQ-C54lj_mp.js} +1 -1
  8. package/dist/client/assets/{blockDiagram-VD42YOAC-DNtrsJ3_.js → blockDiagram-VD42YOAC-IXpkKl99.js} +1 -1
  9. package/dist/client/assets/{c4Diagram-YG6GDRKO-L-AKg5Ca.js → c4Diagram-YG6GDRKO-eHkAJFz1.js} +1 -1
  10. package/dist/client/assets/channel-DDj6wNE3.js +1 -0
  11. package/dist/client/assets/{chunk-4BX2VUAB-6WG78h6_.js → chunk-4BX2VUAB-BVtvPQLw.js} +1 -1
  12. package/dist/client/assets/{chunk-55IACEB6-CivChWg7.js → chunk-55IACEB6-DWUF7TBt.js} +1 -1
  13. package/dist/client/assets/{chunk-B4BG7PRW-BKLAk8Ng.js → chunk-B4BG7PRW-BT2NV-OP.js} +1 -1
  14. package/dist/client/assets/{chunk-DI55MBZ5-B_cDZCba.js → chunk-DI55MBZ5-Cg5CF9C8.js} +1 -1
  15. package/dist/client/assets/{chunk-FMBD7UC4-CZgE72J_.js → chunk-FMBD7UC4-B0SYeHBH.js} +1 -1
  16. package/dist/client/assets/{chunk-QN33PNHL-1qh6IGru.js → chunk-QN33PNHL-C5tEKH2s.js} +1 -1
  17. package/dist/client/assets/{chunk-QZHKN3VN-Cl_2nn9E.js → chunk-QZHKN3VN-B3eOtTKT.js} +1 -1
  18. package/dist/client/assets/{chunk-TZMSLE5B-DpxKjqWA.js → chunk-TZMSLE5B-C2LU8iG2.js} +1 -1
  19. package/dist/client/assets/classDiagram-2ON5EDUG-DEMr_v7L.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-WZHVMYZB-DEMr_v7L.js +1 -0
  21. package/dist/client/assets/clone-BsghsKY1.js +1 -0
  22. package/dist/client/assets/{cose-bilkent-S5V4N54A-DCzND3wc.js → cose-bilkent-S5V4N54A-DMEstRG3.js} +1 -1
  23. package/dist/client/assets/{dagre-6UL2VRFP-phsFBB-e.js → dagre-6UL2VRFP-Dnk33exg.js} +1 -1
  24. package/dist/client/assets/{diagram-PSM6KHXK-C3SOO9R0.js → diagram-PSM6KHXK-mrXKTY_T.js} +1 -1
  25. package/dist/client/assets/{diagram-QEK2KX5R-CAFBJ4hH.js → diagram-QEK2KX5R-BzHK-hsq.js} +1 -1
  26. package/dist/client/assets/{diagram-S2PKOQOG-Bpydud7g.js → diagram-S2PKOQOG-CQCxQKV-.js} +1 -1
  27. package/dist/client/assets/{erDiagram-Q2GNP2WA-Co4WhzwN.js → erDiagram-Q2GNP2WA-BPDJfava.js} +1 -1
  28. package/dist/client/assets/{flowDiagram-NV44I4VS-BZA58aUI.js → flowDiagram-NV44I4VS-C6Mmdoua.js} +1 -1
  29. package/dist/client/assets/{ganttDiagram-JELNMOA3--4j85sTO.js → ganttDiagram-JELNMOA3-DLbgXlJh.js} +1 -1
  30. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-6AH31Cb1.js → gitGraphDiagram-V2S2FVAM-DVLRTDa6.js} +1 -1
  31. package/dist/client/assets/{graph-7CJlwe2i.js → graph-Cwyvupsz.js} +1 -1
  32. package/dist/client/assets/{highlighted-body-B3W2YXNL-D5Kact6h.js → highlighted-body-B3W2YXNL-C0bhSLak.js} +1 -1
  33. package/dist/client/assets/{index-D_D2pxKM.js → index-8fmEfQXt.js} +1 -1
  34. package/dist/client/assets/{index-C4gIKOr_.js → index-8qew1yXR.js} +1 -1
  35. package/dist/client/assets/{index-DnzvlwNY.js → index-BEfdqN9O.js} +1 -1
  36. package/dist/client/assets/{index-Djl4xLSO.js → index-BjRdyIjf.js} +1 -1
  37. package/dist/client/assets/{index-B2DcQ-ug.js → index-BwEcNyXc.js} +1 -1
  38. package/dist/client/assets/{index-DgEnNhJH.js → index-Bx_OaRaP.js} +1 -1
  39. package/dist/client/assets/{index-B5R7cbs8.js → index-BzF5H3v-.js} +1 -1
  40. package/dist/client/assets/{index-DMMKTe60.js → index-CA4qMsBj.js} +1 -1
  41. package/dist/client/assets/{index-Cp85A8y4.js → index-CCvDsqEy.js} +1 -1
  42. package/dist/client/assets/{index-CralkALm.js → index-CXNMB7pL.js} +1 -1
  43. package/dist/client/assets/{index-pr8WXb_L.js → index-CbBtBBYr.js} +1 -1
  44. package/dist/client/assets/{index-Cv7YFrOV.js → index-CqhJvfhF.js} +1 -1
  45. package/dist/client/assets/{index-DCu6TAMf.js → index-DWLuzOpi.js} +1 -1
  46. package/dist/client/assets/{index-CoRbY65h.js → index-DsTs1gei.js} +1 -1
  47. package/dist/client/assets/{index-BwJYeeov.js → index-ERt8cxUV.js} +1 -1
  48. package/dist/client/assets/{index-Dn_GfMwq.js → index-FSq9CQql.js} +1 -1
  49. package/dist/client/assets/{index--MhpXyw4.js → index-UCQ1zVBi.js} +1 -1
  50. package/dist/client/assets/{index-B4wpLa0T.js → index-fifqJXyx.js} +1 -1
  51. package/dist/client/assets/{infoDiagram-HS3SLOUP-CeA337Zm.js → infoDiagram-HS3SLOUP-7Hhl73vO.js} +1 -1
  52. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-ujbs0LMd.js → journeyDiagram-XKPGCS4Q-CJcXgH51.js} +1 -1
  53. package/dist/client/assets/{kanban-definition-3W4ZIXB7-ffQDH_Ro.js → kanban-definition-3W4ZIXB7-CBsuk1vp.js} +1 -1
  54. package/dist/client/assets/{layout-Bp2mKXuW.js → layout-ZjLAsNj-.js} +1 -1
  55. package/dist/client/assets/{main-axhmccT5.js → main-QmYiKgqv.js} +219 -219
  56. package/dist/client/assets/{mindmap-definition-VGOIOE7T-ADZcbwuf.js → mindmap-definition-VGOIOE7T-doqFtLjy.js} +1 -1
  57. package/dist/client/assets/{pieDiagram-ADFJNKIX-BdG4-xDd.js → pieDiagram-ADFJNKIX-Bzaqqvl9.js} +1 -1
  58. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-DUtM9sRB.js → quadrantDiagram-AYHSOK5B-DxzHu9fl.js} +1 -1
  59. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-Bb0HlfNx.js → requirementDiagram-UZGBJVZJ-Cp3foAel.js} +1 -1
  60. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-DVCE_8pf.js → sankeyDiagram-TZEHDZUN-BQx6TKI3.js} +1 -1
  61. package/dist/client/assets/{sequenceDiagram-WL72ISMW-CKQaWU-Q.js → sequenceDiagram-WL72ISMW-Cd_242bL.js} +1 -1
  62. package/dist/client/assets/{square-terminal-BiJr_LVr.js → square-terminal-bliRzpRN.js} +1 -1
  63. package/dist/client/assets/{stateDiagram-FKZM4ZOC-D0QXwVbV.js → stateDiagram-FKZM4ZOC-GZM9iqTD.js} +1 -1
  64. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-yLFyTsJU.js +1 -0
  65. package/dist/client/assets/{timeline-definition-IT6M3QCI-CUDKk5ha.js → timeline-definition-IT6M3QCI-D5mcm-Qu.js} +1 -1
  66. package/dist/client/assets/{treemap-GDKQZRPO-yUFqXQpQ.js → treemap-GDKQZRPO-CkKCE0F7.js} +1 -1
  67. package/dist/client/assets/{workspace._workspaceId-Bz0CuqC_.js → workspace._workspaceId-CQVHqxcU.js} +1 -1
  68. package/dist/client/assets/{workspace._workspaceId-DorcrnsD.js → workspace._workspaceId-DFvkHRHC.js} +2 -2
  69. package/dist/client/assets/{xychartDiagram-PRI3JC2R-Dju2LIYt.js → xychartDiagram-PRI3JC2R-Djg2lfgU.js} +1 -1
  70. package/dist/openapi.json +76 -0
  71. package/dist/server/assets/{DockviewBrowserContainer-DaEHL7rU.js → DockviewBrowserContainer-Btjtd2O1.js} +29 -34
  72. package/dist/server/assets/{DockviewTerminalContainer-QeRuw498.js → DockviewTerminalContainer-bMEUzx6R.js} +3 -3
  73. package/dist/server/assets/{TerminalPanel-CIQVz_Z4.js → TerminalPanel-DDazs1HR.js} +1 -49
  74. package/dist/server/assets/{_basePickBy-Bgz-DXU9.js → _basePickBy-BR2ebl6H.js} +2 -2
  75. package/dist/server/assets/{_baseUniq-CevNURdU.js → _baseUniq-C7-_tYXk.js} +1 -1
  76. package/dist/server/assets/{_tanstack-start-manifest_v-9Dn7fTyV.js → _tanstack-start-manifest_v-TcfwNbuH.js} +1 -1
  77. package/dist/server/assets/{arc-jD7cuYE0.js → arc-CWFSWY_u.js} +1 -1
  78. package/dist/server/assets/{architecture-7HQA4BMR-CH32HJV2.js → architecture-7HQA4BMR-DDMO671Z.js} +6 -6
  79. package/dist/server/assets/{architectureDiagram-VXUJARFQ-DisnJPPo.js → architectureDiagram-VXUJARFQ-vPxmruSN.js} +6 -6
  80. package/dist/server/assets/{blockDiagram-VD42YOAC-Djjy-jiv.js → blockDiagram-VD42YOAC-DGV6m5iW.js} +6 -6
  81. package/dist/server/assets/{c4Diagram-YG6GDRKO-B12Oi-HH.js → c4Diagram-YG6GDRKO-9PjJESuA.js} +2 -2
  82. package/dist/server/assets/{channel-DFaIo-PG.js → channel-DzyKDZfe.js} +1 -1
  83. package/dist/server/assets/{chunk-4BX2VUAB-DHfsBptR.js → chunk-4BX2VUAB-MyrUiBmB.js} +1 -1
  84. package/dist/server/assets/{chunk-55IACEB6-jIjVbMix.js → chunk-55IACEB6-CJ4fKFif.js} +1 -1
  85. package/dist/server/assets/{chunk-B4BG7PRW-CZ4z-SYy.js → chunk-B4BG7PRW-CKzqfTU-.js} +4 -4
  86. package/dist/server/assets/{chunk-DI55MBZ5-BAZeiYrT.js → chunk-DI55MBZ5-DrXLxcKs.js} +3 -3
  87. package/dist/server/assets/{chunk-FMBD7UC4-CPlukapU.js → chunk-FMBD7UC4-yeB6m7NE.js} +1 -1
  88. package/dist/server/assets/{chunk-QN33PNHL-BBEzEMyZ.js → chunk-QN33PNHL-qCq8pCkn.js} +1 -1
  89. package/dist/server/assets/{chunk-QZHKN3VN-BbJAuOLh.js → chunk-QZHKN3VN-CHvK5Ic5.js} +1 -1
  90. package/dist/server/assets/{chunk-TZMSLE5B-DXQ0720e.js → chunk-TZMSLE5B-wF9ZPcJp.js} +1 -1
  91. package/dist/server/assets/{classDiagram-v2-WZHVMYZB-Dd_NiCJt.js → classDiagram-2ON5EDUG-D1OcdIXp.js} +5 -5
  92. package/dist/server/assets/{classDiagram-2ON5EDUG-Dd_NiCJt.js → classDiagram-v2-WZHVMYZB-D1OcdIXp.js} +5 -5
  93. package/dist/server/assets/{clone-D2G5HtzD.js → clone-BH4YtRmr.js} +1 -1
  94. package/dist/server/assets/{cose-bilkent-S5V4N54A-D9MbA73U.js → cose-bilkent-S5V4N54A-BiP6P-09.js} +1 -1
  95. package/dist/server/assets/{dagre-6UL2VRFP-3X8TKKNF.js → dagre-6UL2VRFP-BKfzYlJQ.js} +6 -6
  96. package/dist/server/assets/{diagram-PSM6KHXK-BifH8r_E.js → diagram-PSM6KHXK-BF6r9xQS.js} +7 -7
  97. package/dist/server/assets/{diagram-QEK2KX5R-CpM2yo3A.js → diagram-QEK2KX5R-CxL6qeVX.js} +6 -6
  98. package/dist/server/assets/{diagram-S2PKOQOG-Dem9oHxL.js → diagram-S2PKOQOG-CUKugrbt.js} +6 -6
  99. package/dist/server/assets/{erDiagram-Q2GNP2WA-Cv2t_qcc.js → erDiagram-Q2GNP2WA-CRPjeaHB.js} +4 -4
  100. package/dist/server/assets/{flowDiagram-NV44I4VS-DO9viNx6.js → flowDiagram-NV44I4VS-CXnLZPl0.js} +5 -5
  101. package/dist/server/assets/{ganttDiagram-JELNMOA3-BQLkwHvs.js → ganttDiagram-JELNMOA3-CP5EwGxj.js} +1 -1
  102. package/dist/server/assets/{gitGraph-G5XIXVHT-Rf89GAs0.js → gitGraph-G5XIXVHT-UYMoyufq.js} +6 -6
  103. package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-Cn1yq3PZ.js → gitGraphDiagram-V2S2FVAM-CZNtwgUE.js} +7 -7
  104. package/dist/server/assets/{graph-DdtTxequ.js → graph-BB1_2Q0x.js} +2 -2
  105. package/dist/server/assets/{highlighted-body-B3W2YXNL-DGIqRI0V.js → highlighted-body-B3W2YXNL-C6BqMnvu.js} +1 -1
  106. package/dist/server/assets/{index-eS7k7NKN.js → index-B5V3PU-n.js} +2 -2
  107. package/dist/server/assets/{index-B7HiLzkZ.js → index-BHQ8bMg_.js} +3 -3
  108. package/dist/server/assets/{index-iwREUWd1.js → index-BUm0x4GN.js} +2 -2
  109. package/dist/server/assets/{index-_XlsLUmp.js → index-Bay77lf3.js} +2 -2
  110. package/dist/server/assets/{index-DKFYHMSW.js → index-BbUtF3L1.js} +2 -2
  111. package/dist/server/assets/{index-rDKMQzl_.js → index-Bme4JhwA.js} +1 -1
  112. package/dist/server/assets/{index-CVQ-l3zd.js → index-CMxtCPk9.js} +2 -2
  113. package/dist/server/assets/{index-CZSZYqEH.js → index-Ct5-lZTn.js} +2 -2
  114. package/dist/server/assets/{index-DF0W4io9.js → index-D49PP401.js} +3 -3
  115. package/dist/server/assets/{index-COXowzgf.js → index-D5hMY11m.js} +4 -4
  116. package/dist/server/assets/{index-Bd47fsM9.js → index-DC1gaho7.js} +5 -5
  117. package/dist/server/assets/{index-CEu724dC.js → index-DH3a6-do.js} +2 -2
  118. package/dist/server/assets/{index-CN-GsVYc.js → index-DLEtsdeb.js} +2 -2
  119. package/dist/server/assets/{index-D0gkB7DS.js → index-DLV7EX0H.js} +1 -1
  120. package/dist/server/assets/{index-IABw8d2w.js → index-Dqk2jQZ7.js} +2 -2
  121. package/dist/server/assets/{index-CSvLh_Yz.js → index-DrWaYPW7.js} +2 -2
  122. package/dist/server/assets/{index-dA-FNez1.js → index-DsrV0B5O.js} +5 -5
  123. package/dist/server/assets/{index-C7aw98b-.js → index-lmhecPWc.js} +2 -2
  124. package/dist/server/assets/{info-VBDWY6EO-DVBWXH0S.js → info-VBDWY6EO-X8DJfp6J.js} +6 -6
  125. package/dist/server/assets/{infoDiagram-HS3SLOUP-Dn-PUlKq.js → infoDiagram-HS3SLOUP-BqzWimk3.js} +5 -5
  126. package/dist/server/assets/{journeyDiagram-XKPGCS4Q-C1eLAzL9.js → journeyDiagram-XKPGCS4Q-TTA7OGV5.js} +4 -4
  127. package/dist/server/assets/{kanban-definition-3W4ZIXB7-DFHxxNcb.js → kanban-definition-3W4ZIXB7-DxNhleha.js} +2 -2
  128. package/dist/server/assets/{layout-BEatsupl.js → layout-CdOkK52n.js} +4 -4
  129. package/dist/server/assets/{mermaid-3ZIDBTTL-8mt5O2g5.js → mermaid-3ZIDBTTL-Cof8t4J_.js} +1 -1
  130. package/dist/server/assets/{mermaid-parser.core-BLOfHo-D.js → mermaid-parser.core-Cqz_DwKC.js} +11 -11
  131. package/dist/server/assets/{mindmap-definition-VGOIOE7T-B5_qScJU.js → mindmap-definition-VGOIOE7T-DeGYTIld.js} +3 -3
  132. package/dist/server/assets/{packet-DYOGHKS2-DYeTXPnX.js → packet-DYOGHKS2-TuIP3-Qx.js} +6 -6
  133. package/dist/server/assets/{pie-VRWISCQL-BlyZBKB0.js → pie-VRWISCQL-DH44dC73.js} +6 -6
  134. package/dist/server/assets/{pieDiagram-ADFJNKIX-CwWqz5Xf.js → pieDiagram-ADFJNKIX-BPUa7SIP.js} +7 -7
  135. package/dist/server/assets/{quadrantDiagram-AYHSOK5B-BZ8A8mON.js → quadrantDiagram-AYHSOK5B-CkonmhO6.js} +1 -1
  136. package/dist/server/assets/{radar-ZZBFDIW7-B60czbOE.js → radar-ZZBFDIW7-oedT_dlV.js} +6 -6
  137. package/dist/server/assets/{requirementDiagram-UZGBJVZJ-Cctcn3D4.js → requirementDiagram-UZGBJVZJ-B39ng8tF.js} +3 -3
  138. package/dist/server/assets/{router-V4X9DgJt.js → router-Dz7oMBKX.js} +363 -196
  139. package/dist/server/assets/{sankeyDiagram-TZEHDZUN-Bvyi-a8d.js → sankeyDiagram-TZEHDZUN-61A7I6h9.js} +1 -1
  140. package/dist/server/assets/{sequenceDiagram-WL72ISMW-C83rLE-r.js → sequenceDiagram-WL72ISMW-CXIpjJu4.js} +3 -3
  141. package/dist/server/assets/{square-terminal-Dcy5Z6a4.js → square-terminal-D86hckth.js} +1 -1
  142. package/dist/server/assets/{stateDiagram-FKZM4ZOC-lfXNq0DS.js → stateDiagram-FKZM4ZOC-DSp5PEkn.js} +8 -8
  143. package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-BkZqIjkI.js → stateDiagram-v2-4FDKWEC3-B5TiwK_8.js} +4 -4
  144. package/dist/server/assets/{timeline-definition-IT6M3QCI-CejT7_79.js → timeline-definition-IT6M3QCI-DvosEzgh.js} +2 -2
  145. package/dist/server/assets/{treemap-GDKQZRPO-Dvu1YI6l.js → treemap-GDKQZRPO-BOdkONyj.js} +6 -6
  146. package/dist/server/assets/{workspace._workspaceId-BpnCyMIU.js → workspace._workspaceId-CvbciLVC.js} +3 -3
  147. package/dist/server/assets/{workspace._workspaceId-D20Q15rI.js → workspace._workspaceId-Dcw9dnbJ.js} +1 -1
  148. package/dist/server/assets/{xychartDiagram-PRI3JC2R-DmHHkA_A.js → xychartDiagram-PRI3JC2R-C22gtuGl.js} +1 -1
  149. package/dist/server/server.js +2 -2
  150. package/dist/start-server.mjs +333 -59
  151. package/package.json +4 -4
  152. package/dist/client/assets/DockviewBrowserContainer-CE6D36cE.js +0 -5
  153. package/dist/client/assets/TerminalPanel-BCLbEfyo.js +0 -5
  154. package/dist/client/assets/channel-vYE3Ojmg.js +0 -1
  155. package/dist/client/assets/classDiagram-2ON5EDUG-xnvZA_6X.js +0 -1
  156. package/dist/client/assets/classDiagram-v2-WZHVMYZB-xnvZA_6X.js +0 -1
  157. package/dist/client/assets/clone-DsvuocD4.js +0 -1
  158. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-C3iyPGuZ.js +0 -1
@@ -6070,7 +6070,7 @@ var require_transport = __commonJS({
6070
6070
  "use strict";
6071
6071
  var { createRequire: createRequire2 } = __require("module");
6072
6072
  var getCallers = require_caller();
6073
- var { join: join33, isAbsolute: isAbsolute5, sep: sep8 } = __require("node:path");
6073
+ var { join: join33, isAbsolute: isAbsolute5, sep: sep9 } = __require("node:path");
6074
6074
  var sleep2 = require_atomic_sleep();
6075
6075
  var onExit = require_on_exit_leak_free();
6076
6076
  var ThreadStream = require_thread_stream();
@@ -6178,7 +6178,7 @@ var require_transport = __commonJS({
6178
6178
  let fixTarget2;
6179
6179
  for (const filePath of callers) {
6180
6180
  try {
6181
- const context = filePath === "node:repl" ? process.cwd() + sep8 : filePath;
6181
+ const context = filePath === "node:repl" ? process.cwd() + sep9 : filePath;
6182
6182
  fixTarget2 = createRequire2(context).resolve(origin);
6183
6183
  break;
6184
6184
  } catch (err) {
@@ -29490,6 +29490,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
29490
29490
  }
29491
29491
  });
29492
29492
 
29493
+ // ../../packages/coding-agent/src/adapter-env.ts
29494
+ var AGENT_DISPATCH_ENV;
29495
+ var init_adapter_env = __esm({
29496
+ "../../packages/coding-agent/src/adapter-env.ts"() {
29497
+ AGENT_DISPATCH_ENV = {
29498
+ BAND_DISPATCH: "chat"
29499
+ };
29500
+ }
29501
+ });
29502
+
29493
29503
  // ../../packages/coding-agent/src/pricing.ts
29494
29504
  function computeCost(model, tokens) {
29495
29505
  if (!model) return 0;
@@ -29961,6 +29971,7 @@ var init_claude_code = __esm({
29961
29971
  "../../packages/coding-agent/src/adapters/claude-code.ts"() {
29962
29972
  init_sdk();
29963
29973
  init_src();
29974
+ init_adapter_env();
29964
29975
  init_pricing();
29965
29976
  init_skills();
29966
29977
  log2 = createLogger("coding-agent:claude-code");
@@ -29996,7 +30007,7 @@ var init_claude_code = __esm({
29996
30007
  }
29997
30008
  }
29998
30009
  async *runSession(prompt, sessionId, options2) {
29999
- const env = { ...process.env };
30010
+ const env = { ...process.env, ...AGENT_DISPATCH_ENV };
30000
30011
  env.CLAUDECODE = void 0;
30001
30012
  env.CLAUDE_CODE_ENTRYPOINT = void 0;
30002
30013
  env.ANTHROPIC_CUSTOM_HEADERS = void 0;
@@ -30370,6 +30381,18 @@ var init_claude_code = __esm({
30370
30381
  args: [prompt]
30371
30382
  };
30372
30383
  }
30384
+ /**
30385
+ * Resume CLI invocation for the chat tab's "Continue in terminal" action.
30386
+ * `claude --resume <session-id>` reopens the interactive REPL with that
30387
+ * exact conversation restored (session-ID lookup is scoped to the
30388
+ * project directory + its worktrees, which is where we spawn the PTY).
30389
+ */
30390
+ resumeCliInvocation(sessionId) {
30391
+ return {
30392
+ command: this.executablePath ?? CLAUDE_CODE_DEFAULT_BINARY,
30393
+ args: ["--resume", sessionId]
30394
+ };
30395
+ }
30373
30396
  /**
30374
30397
  * No static fallback. The live `supportedModels()` SDK call is the
30375
30398
  * single source of truth; `refreshModels()` populates
@@ -31112,6 +31135,18 @@ var init_cursor_cli = __esm({
31112
31135
  reason: "Cursor CLI has no interactive prompt-loading invocation; falling back to chat."
31113
31136
  };
31114
31137
  }
31138
+ /**
31139
+ * The chat tab's "Continue in terminal" action has no Cursor equivalent:
31140
+ * the agent runs over the SDK's managed JSON subprocess, with no
31141
+ * interactive by-id resume CLI. Returning the `unsupported` sentinel
31142
+ * keeps the menu item disabled.
31143
+ */
31144
+ resumeCliInvocation(_sessionId) {
31145
+ return {
31146
+ unsupported: true,
31147
+ reason: "Cursor CLI has no interactive session-resume invocation."
31148
+ };
31149
+ }
31115
31150
  };
31116
31151
  CURSOR_MODELS = [
31117
31152
  { id: "auto", name: "Auto", description: "Cursor chooses the best model" }
@@ -31951,6 +31986,7 @@ var init_codex = __esm({
31951
31986
  init_src();
31952
31987
  init_dist2();
31953
31988
  init_zod();
31989
+ init_adapter_env();
31954
31990
  init_pricing();
31955
31991
  init_skills();
31956
31992
  log4 = createLogger("coding-agent:codex");
@@ -31999,6 +32035,7 @@ var init_codex = __esm({
31999
32035
  }
32000
32036
  cleanEnv[key] = value;
32001
32037
  }
32038
+ Object.assign(cleanEnv, AGENT_DISPATCH_ENV);
32002
32039
  const codex = new Codex({
32003
32040
  ...this.executablePath ? { codexPathOverride: this.executablePath } : {},
32004
32041
  env: cleanEnv
@@ -32296,6 +32333,17 @@ var init_codex = __esm({
32296
32333
  args: [prompt]
32297
32334
  };
32298
32335
  }
32336
+ /**
32337
+ * Resume CLI invocation for the chat tab's "Continue in terminal" action.
32338
+ * `codex resume <session-id>` reopens the interactive Codex TUI with that
32339
+ * thread restored.
32340
+ */
32341
+ resumeCliInvocation(sessionId) {
32342
+ return {
32343
+ command: this.executablePath ?? CODEX_DEFAULT_BINARY,
32344
+ args: ["resume", sessionId]
32345
+ };
32346
+ }
32299
32347
  async listSessions(dir) {
32300
32348
  log4.info({ dir }, "listSessions");
32301
32349
  const sessions = await readCodexSessions();
@@ -32497,6 +32545,7 @@ var log5, GeminiCliAdapter, GEMINI_CLI_DEFAULT_BINARY, GEMINI_MODELS;
32497
32545
  var init_gemini_cli = __esm({
32498
32546
  "../../packages/coding-agent/src/adapters/gemini-cli.ts"() {
32499
32547
  init_src();
32548
+ init_adapter_env();
32500
32549
  init_skills();
32501
32550
  log5 = createLogger("coding-agent:gemini-cli");
32502
32551
  GeminiCliAdapter = class {
@@ -32541,7 +32590,9 @@ var init_gemini_cli = __esm({
32541
32590
  const child = spawn3(this.executablePath, args, {
32542
32591
  cwd: this.workspaceDir,
32543
32592
  stdio: ["ignore", "pipe", "pipe"],
32544
- env: { ...process.env }
32593
+ // BAND_DISPATCH=chat so a nested `band` CLI call from this agent
32594
+ // dispatches back into a chat pane (see adapter-env.ts).
32595
+ env: { ...process.env, ...AGENT_DISPATCH_ENV }
32545
32596
  });
32546
32597
  this.activeChild = child;
32547
32598
  let spawnError = null;
@@ -32671,6 +32722,17 @@ var init_gemini_cli = __esm({
32671
32722
  args: ["--", prompt]
32672
32723
  };
32673
32724
  }
32725
+ /**
32726
+ * The chat tab's "Continue in terminal" action has no Gemini equivalent:
32727
+ * the Gemini CLI has no session model, so there's no session ID to resume
32728
+ * by. Returning the `unsupported` sentinel keeps the menu item disabled.
32729
+ */
32730
+ resumeCliInvocation(_sessionId) {
32731
+ return {
32732
+ unsupported: true,
32733
+ reason: "Gemini CLI has no session-resume invocation."
32734
+ };
32735
+ }
32674
32736
  };
32675
32737
  GEMINI_CLI_DEFAULT_BINARY = "gemini";
32676
32738
  GEMINI_MODELS = [
@@ -32888,6 +32950,7 @@ var log6, OpenCodeAdapter, OPENCODE_DEFAULT_BINARY;
32888
32950
  var init_opencode = __esm({
32889
32951
  "../../packages/coding-agent/src/adapters/opencode.ts"() {
32890
32952
  init_src();
32953
+ init_adapter_env();
32891
32954
  init_skills();
32892
32955
  log6 = createLogger("coding-agent:opencode");
32893
32956
  OpenCodeAdapter = class {
@@ -32952,7 +33015,9 @@ var init_opencode = __esm({
32952
33015
  const child = spawn4(this.executablePath, args, {
32953
33016
  cwd: this.workspaceDir,
32954
33017
  stdio: ["ignore", "pipe", "pipe"],
32955
- env: { ...process.env }
33018
+ // BAND_DISPATCH=chat so a nested `band` CLI call from this agent
33019
+ // dispatches back into a chat pane (see adapter-env.ts).
33020
+ env: { ...process.env, ...AGENT_DISPATCH_ENV }
32956
33021
  });
32957
33022
  this.activeChild = child;
32958
33023
  child.on("error", (err) => {
@@ -33152,6 +33217,18 @@ var init_opencode = __esm({
33152
33217
  args: ["--prompt", prompt]
33153
33218
  };
33154
33219
  }
33220
+ /**
33221
+ * Resume CLI invocation for the chat tab's "Continue in terminal" action.
33222
+ * `opencode --session <id>` launches the interactive TUI on that exact
33223
+ * session (the same `--session` flag `runSession` uses for headless
33224
+ * `opencode run`).
33225
+ */
33226
+ resumeCliInvocation(sessionId) {
33227
+ return {
33228
+ command: this.executablePath,
33229
+ args: ["--session", sessionId]
33230
+ };
33231
+ }
33155
33232
  async listSessions(dir) {
33156
33233
  const sessions = await fetchOpenCodeSessions(this.executablePath, dir);
33157
33234
  log6.info({ dir, count: sessions.length }, "listSessions");
@@ -89610,7 +89687,7 @@ var require_dist5 = __commonJS({
89610
89687
  // start-server.ts
89611
89688
  import { appendFileSync as appendFileSync2, createReadStream as createReadStream3, mkdirSync as mkdirSync9, readFileSync as readFileSync10, statSync as statSync9 } from "node:fs";
89612
89689
  import { createServer } from "node:http";
89613
- import { basename as basename3, join as join32, resolve as resolve11, sep as sep7 } from "node:path";
89690
+ import { basename as basename3, join as join32, resolve as resolve11, sep as sep8 } from "node:path";
89614
89691
 
89615
89692
  // ../../node_modules/.pnpm/@trpc+server@11.12.0_typescript@5.9.3/node_modules/@trpc/server/dist/codes-DagpWZLc.mjs
89616
89693
  function mergeWithoutOverrides(obj1, ...objs) {
@@ -114371,6 +114448,13 @@ var import_jsx_runtime52 = __toESM(require_jsx_runtime(), 1);
114371
114448
 
114372
114449
  // src/dashboard/components/NewWorkspaceForm.tsx
114373
114450
  var import_react20 = __toESM(require_react(), 1);
114451
+
114452
+ // src/lib/branch-name.ts
114453
+ function slugifyBranchName(input) {
114454
+ return input.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9\-/]/g, "").replace(/-{2,}/g, "-").replace(/\/+/g, "/").replace(/^[-/]+|[-/]+$/g, "");
114455
+ }
114456
+
114457
+ // src/dashboard/components/NewWorkspaceForm.tsx
114374
114458
  var import_jsx_runtime53 = __toESM(require_jsx_runtime(), 1);
114375
114459
 
114376
114460
  // src/dashboard/components/PromoteToGitDialog.tsx
@@ -120218,8 +120302,8 @@ function mimeTypeFromFilename(filename) {
120218
120302
  init_src();
120219
120303
  init_zod();
120220
120304
  import { execFile as execFile6 } from "node:child_process";
120221
- import { randomUUID as randomUUID2 } from "node:crypto";
120222
- import { existsSync as existsSync8, mkdirSync as mkdirSync5, unlinkSync as unlinkSync2 } from "node:fs";
120305
+ import { randomUUID as randomUUID3 } from "node:crypto";
120306
+ import { existsSync as existsSync8, mkdirSync as mkdirSync5, unlinkSync as unlinkSync3 } from "node:fs";
120223
120307
  import { rm } from "node:fs/promises";
120224
120308
  import { join as join20 } from "node:path";
120225
120309
  import { promisify as promisify2 } from "node:util";
@@ -120802,6 +120886,21 @@ function hasGlobMeta(pattern) {
120802
120886
  return /[*?[\]{}]/.test(pattern);
120803
120887
  }
120804
120888
 
120889
+ // src/server/services/_utils/format-shell-command.ts
120890
+ var PTY_CONTROL_CHAR_RANGE = new RegExp(
120891
+ `[${String.fromCharCode(0)}-${String.fromCharCode(31)}${String.fromCharCode(
120892
+ 127
120893
+ )}-${String.fromCharCode(159)}]`,
120894
+ "g"
120895
+ );
120896
+ function formatShellCommand(command, args) {
120897
+ const stripControls = (s6) => s6.replace(PTY_CONTROL_CHAR_RANGE, "");
120898
+ const quoted = [command, ...args].map(
120899
+ (token) => `'${stripControls(token).replace(/'/g, "'\\''")}'`
120900
+ );
120901
+ return quoted.join(" ");
120902
+ }
120903
+
120805
120904
  // src/server/services/browser-service.ts
120806
120905
  init_src();
120807
120906
 
@@ -122357,8 +122456,10 @@ init_zod();
122357
122456
 
122358
122457
  // src/server/infra/terminals/terminal-pool.ts
122359
122458
  init_src();
122360
- import { existsSync as existsSync7 } from "node:fs";
122361
- import { join as join19 } from "node:path";
122459
+ import { randomUUID as randomUUID2 } from "node:crypto";
122460
+ import { existsSync as existsSync7, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "node:fs";
122461
+ import { tmpdir } from "node:os";
122462
+ import { join as join19, sep as sep3 } from "node:path";
122362
122463
  var log21 = createLogger("terminal-pool");
122363
122464
  var MAX_SCROLLBACK_SIZE = 1e5;
122364
122465
  var TerminalPool = class {
@@ -122392,10 +122493,11 @@ var TerminalPool = class {
122392
122493
  if (options2?.env) {
122393
122494
  Object.assign(env, options2.env);
122394
122495
  }
122496
+ env.BAND_DISPATCH = "terminal";
122395
122497
  let cwd = workspaceRoot;
122396
122498
  if (options2?.cwd) {
122397
122499
  const resolved = join19(workspaceRoot, options2.cwd);
122398
- if (!resolved.startsWith(workspaceRoot)) {
122500
+ if (resolved !== workspaceRoot && !resolved.startsWith(workspaceRoot + sep3)) {
122399
122501
  log21.warn(
122400
122502
  "Ignoring cwd %s \u2014 resolves outside workspace root %s",
122401
122503
  options2.cwd,
@@ -122438,8 +122540,7 @@ var TerminalPool = class {
122438
122540
  const session = { pty: ptyProcess, scrollback: "", workspaceId };
122439
122541
  this.terminals.set(terminalId, session);
122440
122542
  if (options2?.command) {
122441
- ptyProcess.write(`${options2.command}
122442
- `);
122543
+ this.autoRunCommand(session, options2.command);
122443
122544
  }
122444
122545
  let ids = this.workspaceTerminals.get(workspaceId);
122445
122546
  if (!ids) {
@@ -122473,9 +122574,94 @@ var TerminalPool = class {
122473
122574
  this.workspaceTerminals.delete(workspaceId);
122474
122575
  }
122475
122576
  }
122577
+ if (session.autoRunFile) {
122578
+ try {
122579
+ unlinkSync2(session.autoRunFile);
122580
+ } catch {
122581
+ }
122582
+ }
122476
122583
  });
122477
122584
  return session;
122478
122585
  }
122586
+ /**
122587
+ * Auto-run the workspace's initial command inside a freshly spawned PTY,
122588
+ * robustly.
122589
+ *
122590
+ * Writing a long command line straight into a cold PTY is racy on three
122591
+ * fronts, all of which surfaced in production with `via=terminal`
122592
+ * prompt-as-argv launches (`'<agent-binary>' '<entire-prompt>'`):
122593
+ *
122594
+ * 1. **Dropped newline.** The shell may not have finished sourcing its
122595
+ * rc files, and the tty can still be in its startup canonical-mode
122596
+ * window. A trailing `\n` written then is swallowed — the command
122597
+ * is typed at the prompt but never executed.
122598
+ * 2. **Truncation.** A single input line longer than the tty's
122599
+ * canonical buffer (`MAX_CANON`, ~4 KB) is clipped. Long prompts
122600
+ * blow past that easily.
122601
+ * 3. **UTF-8 corruption.** A multi-byte sequence split across a tty
122602
+ * buffer boundary is mangled (the classic em-dash → mojibake).
122603
+ *
122604
+ * Fix both layers: (1) stage the command's bytes in a temp file so they
122605
+ * never traverse the tty's canonical input buffer — sidestepping the
122606
+ * truncation and UTF-8-split failures entirely — and (2) wait for the
122607
+ * shell to emit its first output (its prompt) before writing the
122608
+ * *short* `source <file>` line. The short line is well under the
122609
+ * canonical limit and lands after the cold-start window, so its newline
122610
+ * survives. `source` runs the command in the current interactive shell,
122611
+ * so the user keeps their session afterwards.
122612
+ */
122613
+ autoRunCommand(session, command) {
122614
+ const pty = session.pty;
122615
+ let cmdFile;
122616
+ try {
122617
+ cmdFile = join19(tmpdir(), `band-autorun-${randomUUID2()}.sh`);
122618
+ writeFileSync2(cmdFile, `${command}
122619
+ `, { encoding: "utf-8", mode: 384, flag: "wx" });
122620
+ session.autoRunFile = cmdFile;
122621
+ } catch (err) {
122622
+ log21.warn(
122623
+ "autoRunCommand: temp-file staging failed (%s); writing command directly",
122624
+ err instanceof Error ? err.message : String(err)
122625
+ );
122626
+ pty.write(`${command}
122627
+ `);
122628
+ return;
122629
+ }
122630
+ const quotedPath = cmdFile.replace(/'/g, `'\\''`);
122631
+ const sourceLine = `. '${quotedPath}'
122632
+ `;
122633
+ let done = false;
122634
+ const inject = () => {
122635
+ if (done) return;
122636
+ done = true;
122637
+ try {
122638
+ pty.write(sourceLine);
122639
+ } catch (err) {
122640
+ log21.warn("autoRunCommand: failed to inject command line (%s)", err);
122641
+ }
122642
+ };
122643
+ let dataDisposed = false;
122644
+ const disposeData = () => {
122645
+ if (dataDisposed) return;
122646
+ dataDisposed = true;
122647
+ dataDisposable.dispose();
122648
+ };
122649
+ const dataDisposable = pty.onData(() => {
122650
+ disposeData();
122651
+ inject();
122652
+ });
122653
+ const timer = setTimeout(inject, 750);
122654
+ timer.unref();
122655
+ let exitDisposed = false;
122656
+ const exitDisposable = pty.onExit(() => {
122657
+ done = true;
122658
+ clearTimeout(timer);
122659
+ disposeData();
122660
+ if (exitDisposed) return;
122661
+ exitDisposed = true;
122662
+ exitDisposable.dispose();
122663
+ });
122664
+ }
122479
122665
  /**
122480
122666
  * Returns an existing PTY session by terminalId, or undefined.
122481
122667
  */
@@ -122851,19 +123037,6 @@ var PlainProjectError = class extends Error {
122851
123037
  function isRebaseCollision(err) {
122852
123038
  return String(err).includes("Cannot rebase onto multiple branches");
122853
123039
  }
122854
- var PTY_CONTROL_CHAR_RANGE = new RegExp(
122855
- `[${String.fromCharCode(0)}-${String.fromCharCode(31)}${String.fromCharCode(
122856
- 127
122857
- )}-${String.fromCharCode(159)}]`,
122858
- "g"
122859
- );
122860
- function formatShellCommand(command, args) {
122861
- const stripControls = (s6) => s6.replace(PTY_CONTROL_CHAR_RANGE, "");
122862
- const quoted = [command, ...args].map(
122863
- (token) => `'${stripControls(token).replace(/'/g, "'\\''")}'`
122864
- );
122865
- return quoted.join(" ");
122866
- }
122867
123040
  var WorkspaceService = class {
122868
123041
  constructor(queries = new WorkspaceQueries(), usageEventQueries = new UsageEventQueries(), usageScanStateQueries = new UsageScanStateQueries()) {
122869
123042
  this.queries = queries;
@@ -122956,6 +123129,13 @@ var WorkspaceService = class {
122956
123129
  * no dispatch."
122957
123130
  */
122958
123131
  async create(input) {
123132
+ const sanitizedBranch = slugifyBranchName(input.branch);
123133
+ if (!sanitizedBranch) {
123134
+ throw new Error(
123135
+ `Branch name "${input.branch}" is invalid \u2014 it contains no valid characters after sanitization.`
123136
+ );
123137
+ }
123138
+ input = { ...input, branch: sanitizedBranch };
122959
123139
  const state = loadState();
122960
123140
  const project = state.projects.find((p6) => p6.name === input.project);
122961
123141
  if (!project) {
@@ -123014,7 +123194,7 @@ var WorkspaceService = class {
123014
123194
  via = "chat";
123015
123195
  } else {
123016
123196
  terminalCommand = formatShellCommand(invocation.command, invocation.args);
123017
- terminalId = randomUUID2();
123197
+ terminalId = randomUUID3();
123018
123198
  }
123019
123199
  } catch (err) {
123020
123200
  log23.warn(
@@ -123061,6 +123241,57 @@ var WorkspaceService = class {
123061
123241
  }
123062
123242
  return { ok: true, path: worktreePath, via, terminalId };
123063
123243
  }
123244
+ /**
123245
+ * Continue a chat's coding-agent session in a terminal pane.
123246
+ *
123247
+ * Resolves the chat's underlying session id + the adapter for whichever
123248
+ * agent it ran, asks the adapter for the vendor CLI's *resume* invocation
123249
+ * (`claude --resume <id>`, `codex resume <id>`, `opencode --session <id>`),
123250
+ * composes it into a shell-safe command, and spawns a fresh terminal pane
123251
+ * running it — so the user keeps working in the very session the web chat
123252
+ * was running. Shares the spawn + `terminal-created` emit shape with the
123253
+ * `via=terminal` branch of {@link create} (issue #551).
123254
+ *
123255
+ * Returns a discriminated result rather than throwing so the tRPC router
123256
+ * stays a thin mapping layer — it validates input, delegates here, maps a
123257
+ * `{ ok: false, code }` straight onto a `TRPCError`, and echoes
123258
+ * `{ ok: true, … }` back to the client.
123259
+ */
123260
+ async continueChatInTerminal(chatId) {
123261
+ const chat = chatService.get(chatId);
123262
+ if (!chat) {
123263
+ return { ok: false, code: "NOT_FOUND", message: "Chat not found" };
123264
+ }
123265
+ if (!chat.activeSessionId) {
123266
+ return {
123267
+ ok: false,
123268
+ code: "PRECONDITION_FAILED",
123269
+ message: "Chat has no active session to continue"
123270
+ };
123271
+ }
123272
+ const workspace = this.resolve(chat.workspaceId);
123273
+ if (!workspace) {
123274
+ return { ok: false, code: "NOT_FOUND", message: "Workspace not found" };
123275
+ }
123276
+ const agent = await agentService.getOrCreateAgent(chatId, workspace.worktree.path, chat.agent);
123277
+ const invocation = agent.resumeCliInvocation?.(chat.activeSessionId);
123278
+ if (!invocation || invocation.unsupported) {
123279
+ return {
123280
+ ok: false,
123281
+ code: "BAD_REQUEST",
123282
+ message: invocation?.reason ?? "Agent does not support resuming in a terminal"
123283
+ };
123284
+ }
123285
+ const command = formatShellCommand(invocation.command, invocation.args);
123286
+ const terminalId = randomUUID3();
123287
+ await terminalService.spawn(chat.workspaceId, terminalId, { command });
123288
+ emit({ kind: "terminal-created", workspaceId: chat.workspaceId, terminalId });
123289
+ log23.info(
123290
+ { chatId, workspaceId: chat.workspaceId, terminalId },
123291
+ "continue chat session in terminal"
123292
+ );
123293
+ return { ok: true, terminalId, workspaceId: chat.workspaceId, sessionId: chat.activeSessionId };
123294
+ }
123064
123295
  /**
123065
123296
  * Remove a workspace (git worktree) and its workspace-scoped state.
123066
123297
  *
@@ -123112,7 +123343,7 @@ var WorkspaceService = class {
123112
123343
  saveState(state);
123113
123344
  const workspaceId = toWorkspaceId(input.project, input.branch);
123114
123345
  try {
123115
- unlinkSync2(join20(bandHome(), "workspace-prompts", `${workspaceId}.json`));
123346
+ unlinkSync3(join20(bandHome(), "workspace-prompts", `${workspaceId}.json`));
123116
123347
  } catch {
123117
123348
  }
123118
123349
  deleteWorkspaceStatus(workspaceId);
@@ -124049,6 +124280,14 @@ async function runTask(chatId, task) {
124049
124280
  task.sessionId = event.resolvedSessionId;
124050
124281
  persistTask(task);
124051
124282
  }
124283
+ const resolvedChat = chatService.get(chatId);
124284
+ if (resolvedChat?.activeSessionId === event.previousSessionId) {
124285
+ chatService.updateActiveSession(chatId, {
124286
+ activeSessionId: event.resolvedSessionId,
124287
+ summary: resolvedChat.activeSessionSummary,
124288
+ lastModified: resolvedChat.activeSessionLastModified ?? Date.now()
124289
+ });
124290
+ }
124052
124291
  broadcast(chatId, {
124053
124292
  type: "data-session",
124054
124293
  data: { sessionId: event.resolvedSessionId }
@@ -136618,7 +136857,10 @@ var chatsRouter = t2.router({
136618
136857
  external_exports.object({
136619
136858
  workspaceId: external_exports.string(),
136620
136859
  chatId: external_exports.string(),
136621
- sessionId: external_exports.string().optional()
136860
+ // Cap the length: this id is persisted as `activeSessionId` and later
136861
+ // flows into the resume command line (`continueInTerminal` →
136862
+ // `formatShellCommand` → PTY). Real provider ids are well under this.
136863
+ sessionId: external_exports.string().max(512).optional()
136622
136864
  })
136623
136865
  ).mutation(async ({ input }) => {
136624
136866
  let chat = chatService.get(input.chatId);
@@ -136661,7 +136903,7 @@ var chatsRouter = t2.router({
136661
136903
  workspaceId: external_exports.string(),
136662
136904
  chatId: external_exports.string(),
136663
136905
  message: external_exports.string(),
136664
- sessionId: external_exports.string().optional()
136906
+ sessionId: external_exports.string().max(512).optional()
136665
136907
  })
136666
136908
  ).mutation(({ input }) => {
136667
136909
  let chat = chatService.get(input.chatId);
@@ -136694,6 +136936,33 @@ var chatsRouter = t2.router({
136694
136936
  resume: publicProcedure.input(external_exports.object({ chatId: external_exports.string() })).mutation(({ input }) => {
136695
136937
  chatService.updateStatus(input.chatId, "idle");
136696
136938
  return { ok: true };
136939
+ }),
136940
+ /**
136941
+ * Continue this chat's coding-agent session in a terminal pane.
136942
+ *
136943
+ * Resolves the chat's underlying agent session ID (`activeSessionId`) and
136944
+ * the adapter for whichever coding agent it ran, asks the adapter for the
136945
+ * vendor CLI's *resume* invocation (`claude --resume <id>`,
136946
+ * `codex resume <id>`, `opencode --session <id>`), composes it into a
136947
+ * shell-safe command, and spawns a fresh terminal pane running it — so the
136948
+ * user keeps working in the very session the web chat was running.
136949
+ *
136950
+ * Mirrors the spawn+emit pair in `WorkspaceService.create`'s
136951
+ * `via=terminal` branch (issue #551), and resolves the agent inline the
136952
+ * same way `setActiveSession` above does. Errors surface to the client so
136953
+ * the UI can keep the menu item disabled for agents that can't resume
136954
+ * (Gemini CLI / Cursor CLI) or chats with no session yet.
136955
+ */
136956
+ continueInTerminal: publicProcedure.input(external_exports.object({ chatId: external_exports.string().max(512) })).mutation(async ({ input }) => {
136957
+ const result = await workspaceService.continueChatInTerminal(input.chatId);
136958
+ if (!result.ok) {
136959
+ throw new TRPCError({ code: result.code, message: result.message });
136960
+ }
136961
+ return {
136962
+ terminalId: result.terminalId,
136963
+ workspaceId: result.workspaceId,
136964
+ sessionId: result.sessionId
136965
+ };
136697
136966
  })
136698
136967
  });
136699
136968
 
@@ -136701,7 +136970,7 @@ var chatsRouter = t2.router({
136701
136970
  init_zod();
136702
136971
 
136703
136972
  // src/server/services/cli-service.ts
136704
- import { accessSync, constants, lstatSync as lstatSync2, realpathSync as realpathSync3, symlinkSync as symlinkSync2, unlinkSync as unlinkSync3 } from "node:fs";
136973
+ import { accessSync, constants, lstatSync as lstatSync2, realpathSync as realpathSync3, symlinkSync as symlinkSync2, unlinkSync as unlinkSync4 } from "node:fs";
136705
136974
  import { platform as platform2 } from "node:os";
136706
136975
  import { dirname as dirname4, join as join23, resolve as resolve5 } from "node:path";
136707
136976
  var SYMLINK_PATH = "/usr/local/bin/band";
@@ -136816,7 +137085,7 @@ async function installCli(_opts = {}) {
136816
137085
  if (isDirWritable(dir)) {
136817
137086
  try {
136818
137087
  lstatSync2(SYMLINK_PATH);
136819
- unlinkSync3(SYMLINK_PATH);
137088
+ unlinkSync4(SYMLINK_PATH);
136820
137089
  } catch (err) {
136821
137090
  const code = err.code;
136822
137091
  if (code !== "ENOENT") throw err;
@@ -136922,7 +137191,7 @@ init_zod();
136922
137191
 
136923
137192
  // src/server/services/editor-service.ts
136924
137193
  import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync7 } from "node:fs";
136925
- import { isAbsolute as isAbsolute4, join as join25, resolve as resolve6, sep as sep3 } from "node:path";
137194
+ import { isAbsolute as isAbsolute4, join as join25, resolve as resolve6, sep as sep4 } from "node:path";
136926
137195
 
136927
137196
  // src/server/services/file-watcher.ts
136928
137197
  import { watch as fsWatch } from "node:fs";
@@ -137193,11 +137462,11 @@ var EditorService = class {
137193
137462
  throw new EditorOpenError("BAD_REQUEST", `Not a file: ${input.filePath}`);
137194
137463
  }
137195
137464
  const normalizedRoot = canonicalRoot.replace(/\/+$/, "");
137196
- const isInside = canonicalTarget === normalizedRoot || canonicalTarget.startsWith(`${normalizedRoot}${sep3}`);
137465
+ const isInside = canonicalTarget === normalizedRoot || canonicalTarget.startsWith(`${normalizedRoot}${sep4}`);
137197
137466
  let payloadPath;
137198
137467
  if (isInside) {
137199
137468
  const relativePath = canonicalTarget === normalizedRoot ? "" : canonicalTarget.slice(normalizedRoot.length + 1);
137200
- payloadPath = relativePath.split(sep3).join("/");
137469
+ payloadPath = relativePath.split(sep4).join("/");
137201
137470
  } else {
137202
137471
  payloadPath = canonicalTarget;
137203
137472
  }
@@ -137236,9 +137505,9 @@ function canonicalizeMaybeMissing(p6) {
137236
137505
  return p6;
137237
137506
  }
137238
137507
  }
137239
- const parts = p6.split(sep3);
137508
+ const parts = p6.split(sep4);
137240
137509
  for (let i2 = parts.length - 1; i2 > 0; i2--) {
137241
- const prefix = parts.slice(0, i2).join(sep3) || sep3;
137510
+ const prefix = parts.slice(0, i2).join(sep4) || sep4;
137242
137511
  if (existsSync10(prefix)) {
137243
137512
  try {
137244
137513
  const canonicalPrefix = realpathSync5(prefix);
@@ -137539,7 +137808,7 @@ var historyRouter = t2.router({
137539
137808
  });
137540
137809
 
137541
137810
  // src/server/services/hooks-service.ts
137542
- import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "node:fs";
137811
+ import { mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync3 } from "node:fs";
137543
137812
  import { homedir as homedir8 } from "node:os";
137544
137813
  import { dirname as dirname6, join as join26 } from "node:path";
137545
137814
 
@@ -137748,7 +138017,7 @@ async function installHooks() {
137748
138017
  hooks[event] = filtered;
137749
138018
  }
137750
138019
  settings.hooks = hooks;
137751
- writeFileSync2(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
138020
+ writeFileSync3(settingsPath, JSON.stringify(settings, null, 2), "utf-8");
137752
138021
  }
137753
138022
 
137754
138023
  // src/server/api/hooks/router.ts
@@ -138371,7 +138640,7 @@ var projectsRouter = t2.router({
138371
138640
  init_src();
138372
138641
  init_zod();
138373
138642
  import { realpathSync as realpathSync6 } from "node:fs";
138374
- import { join as join28, resolve as resolve8, sep as sep4 } from "node:path";
138643
+ import { join as join28, resolve as resolve8, sep as sep5 } from "node:path";
138375
138644
  var log32 = createLogger("trpc.queue");
138376
138645
  var queuedFileSchema = external_exports.object({
138377
138646
  mediaType: external_exports.string(),
@@ -138382,13 +138651,13 @@ var queuedFileSchema = external_exports.object({
138382
138651
  function isPathWithinUploadDir(p6) {
138383
138652
  const uploadDir = join28(bandHome(), "uploads");
138384
138653
  const normalized2 = resolve8(p6);
138385
- if (normalized2 !== uploadDir && !normalized2.startsWith(uploadDir + sep4)) {
138654
+ if (normalized2 !== uploadDir && !normalized2.startsWith(uploadDir + sep5)) {
138386
138655
  return false;
138387
138656
  }
138388
138657
  try {
138389
138658
  const canonicalUploadDir = realpathSync6(uploadDir);
138390
138659
  const canonicalPath = realpathSync6(p6);
138391
- return canonicalPath === canonicalUploadDir || canonicalPath.startsWith(canonicalUploadDir + sep4);
138660
+ return canonicalPath === canonicalUploadDir || canonicalPath.startsWith(canonicalUploadDir + sep5);
138392
138661
  } catch {
138393
138662
  return true;
138394
138663
  }
@@ -139176,8 +139445,8 @@ var TunnelClient = class _TunnelClient {
139176
139445
  return match ? match[0] : null;
139177
139446
  }
139178
139447
  static appendToken(baseUrl, token) {
139179
- const sep8 = baseUrl.includes("?") ? "&" : "?";
139180
- return `${baseUrl}${sep8}token=${token}`;
139448
+ const sep9 = baseUrl.includes("?") ? "&" : "?";
139449
+ return `${baseUrl}${sep9}token=${token}`;
139181
139450
  }
139182
139451
  spawnTunnel(options2, resolvedPath) {
139183
139452
  const args = ["tunnel", "--config", "/dev/null", "--url", `http://localhost:${options2.port}`];
@@ -139632,7 +139901,7 @@ function throwAsTrpcError2(err) {
139632
139901
  }
139633
139902
 
139634
139903
  // src/server/api/terminals/router.ts
139635
- import { randomUUID as randomUUID3 } from "node:crypto";
139904
+ import { randomUUID as randomUUID4 } from "node:crypto";
139636
139905
  init_zod();
139637
139906
  var terminalRouter = t2.router({
139638
139907
  list: publicProcedure.input(external_exports.object({ workspaceId: external_exports.string() })).query(({ input }) => {
@@ -139641,13 +139910,17 @@ var terminalRouter = t2.router({
139641
139910
  create: publicProcedure.input(
139642
139911
  external_exports.object({
139643
139912
  workspaceId: external_exports.string(),
139644
- id: external_exports.string().optional(),
139913
+ // Constrain to a UUID: every caller (the dashboard's
139914
+ // `newTerminalId()` and the server's `randomUUID()` fallback)
139915
+ // already sends one, and it stops a hostile id from being used
139916
+ // anywhere the pool derives a filesystem path from it.
139917
+ id: external_exports.string().uuid().optional(),
139645
139918
  command: external_exports.string().optional(),
139646
139919
  cwd: external_exports.string().optional(),
139647
139920
  env: external_exports.record(external_exports.string()).optional()
139648
139921
  })
139649
139922
  ).mutation(async ({ input }) => {
139650
- const terminalId = input.id ?? randomUUID3();
139923
+ const terminalId = input.id ?? randomUUID4();
139651
139924
  const session = await terminalService.spawn(input.workspaceId, terminalId, {
139652
139925
  command: input.command,
139653
139926
  cwd: input.cwd,
@@ -139775,7 +140048,7 @@ init_zod();
139775
140048
  init_src();
139776
140049
  import { existsSync as existsSync12 } from "node:fs";
139777
140050
  import { readFile as readFile2, rm as rm2 } from "node:fs/promises";
139778
- import { join as join29, resolve as resolve9, sep as sep5 } from "node:path";
140051
+ import { join as join29, resolve as resolve9, sep as sep6 } from "node:path";
139779
140052
  var log39 = createLogger("diff-service");
139780
140053
  var EMPTY_TREE_ARGS = ["hash-object", "-t", "tree", "/dev/null"];
139781
140054
  var EMPTY_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
@@ -139830,14 +140103,14 @@ function parseFileStatuses(nameStatusOutput) {
139830
140103
  }
139831
140104
  function assertWorktreeRelative(cwd, filePath) {
139832
140105
  const target = resolve9(join29(cwd, filePath));
139833
- if (target !== cwd && !target.startsWith(cwd + sep5)) {
140106
+ if (target !== cwd && !target.startsWith(cwd + sep6)) {
139834
140107
  throw new Error("Invalid path");
139835
140108
  }
139836
140109
  if (target === cwd) {
139837
140110
  throw new Error("Invalid path");
139838
140111
  }
139839
140112
  const relative2 = target.slice(cwd.length + 1);
139840
- if (relative2 === ".git" || relative2.startsWith(`.git${sep5}`) || relative2.startsWith(".git/")) {
140113
+ if (relative2 === ".git" || relative2.startsWith(`.git${sep6}`) || relative2.startsWith(".git/")) {
139841
140114
  throw new Error("Refusing to touch .git internals");
139842
140115
  }
139843
140116
  return target;
@@ -140114,7 +140387,7 @@ var diffService = new DiffService();
140114
140387
  // src/server/services/files-service.ts
140115
140388
  import { existsSync as existsSync13 } from "node:fs";
140116
140389
  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";
140117
- import { dirname as dirname7, extname as extname3, join as join30, resolve as resolve10, sep as sep6 } from "node:path";
140390
+ import { dirname as dirname7, extname as extname3, join as join30, resolve as resolve10, sep as sep7 } from "node:path";
140118
140391
  var MAX_FILE_SIZE2 = 1024 * 1024;
140119
140392
  var LANG_MAP2 = {
140120
140393
  ".js": "javascript",
@@ -140163,7 +140436,7 @@ var FilesService = class {
140163
140436
  }
140164
140437
  const root = workspace.worktree.path;
140165
140438
  const target = resolve10(join30(root, relative2));
140166
- const insideRoot = target === root || target.startsWith(root + sep6);
140439
+ const insideRoot = target === root || target.startsWith(root + sep7);
140167
140440
  if (!insideRoot) {
140168
140441
  throw new Error("Invalid path");
140169
140442
  }
@@ -140181,7 +140454,7 @@ var FilesService = class {
140181
140454
  throw new Error(`Refusing to ${label} worktree root`);
140182
140455
  }
140183
140456
  const relative2 = target.slice(root.length + 1);
140184
- if (relative2 === ".git" || relative2.startsWith(`.git${sep6}`) || relative2.startsWith(".git/")) {
140457
+ if (relative2 === ".git" || relative2.startsWith(`.git${sep7}`) || relative2.startsWith(".git/")) {
140185
140458
  throw new Error(`Refusing to ${label} .git internals`);
140186
140459
  }
140187
140460
  }
@@ -140326,7 +140599,7 @@ var FilesService = class {
140326
140599
  } catch {
140327
140600
  throw new Error("Source path does not exist");
140328
140601
  }
140329
- if (entryStat.isDirectory() && toTarget.startsWith(fromTarget + sep6)) {
140602
+ if (entryStat.isDirectory() && toTarget.startsWith(fromTarget + sep7)) {
140330
140603
  throw new Error("Cannot copy a directory into itself");
140331
140604
  }
140332
140605
  if (existsSync13(toTarget)) {
@@ -142520,9 +142793,9 @@ import {
142520
142793
  rmSync as rmSync2,
142521
142794
  statSync as statSync8,
142522
142795
  symlinkSync as symlinkSync3,
142523
- writeFileSync as writeFileSync3
142796
+ writeFileSync as writeFileSync4
142524
142797
  } from "node:fs";
142525
- import { homedir as homedir9, tmpdir } from "node:os";
142798
+ import { homedir as homedir9, tmpdir as tmpdir2 } from "node:os";
142526
142799
  import { dirname as dirname8, join as join31 } from "node:path";
142527
142800
  var BAND_SKILL_NAMES = [
142528
142801
  "band",
@@ -142603,7 +142876,7 @@ async function installSkills(opts = {}) {
142603
142876
  }
142604
142877
  return result;
142605
142878
  }
142606
- const stagingDir = mkdtempSync(join31(tmpdir(), "band-skills-"));
142879
+ const stagingDir = mkdtempSync(join31(tmpdir2(), "band-skills-"));
142607
142880
  try {
142608
142881
  await generateSkills(bandPath, stagingDir);
142609
142882
  for (const name3 of BAND_SKILL_NAMES) {
@@ -142633,7 +142906,7 @@ async function installSkills(opts = {}) {
142633
142906
  continue;
142634
142907
  }
142635
142908
  mkdirSync8(dirname8(destPath), { recursive: true });
142636
- writeFileSync3(destPath, sourceContent);
142909
+ writeFileSync4(destPath, sourceContent);
142637
142910
  if (existingContent) {
142638
142911
  result.updated.push(destPath);
142639
142912
  opts.log?.info(
@@ -143055,7 +143328,7 @@ function serveWorkspaceFile(res, workspaceId, rawPath) {
143055
143328
  }
143056
143329
  const root = workspace.worktree.path;
143057
143330
  const target = resolve11(join32(root, rawPath));
143058
- if (!target.startsWith(root + sep7) && target !== root) {
143331
+ if (!target.startsWith(root + sep8) && target !== root) {
143059
143332
  res.writeHead(400);
143060
143333
  res.end("Bad request");
143061
143334
  return;
@@ -143466,6 +143739,7 @@ Failed to bind any port in ${initialPort}..${initialPort + 19}:
143466
143739
  throw err;
143467
143740
  }
143468
143741
  process.env.BAND_PORT = String(boundPort);
143742
+ process.env.BAND_SERVER_URL = `http://127.0.0.1:${boundPort}`;
143469
143743
  console.log(`Web server listening on http://0.0.0.0:${boundPort}`);
143470
143744
  if (boundPort !== initialPort) {
143471
143745
  console.log(