@band-app/server 0.3.0 → 0.3.2

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 (167) hide show
  1. package/dist/client/assets/DockviewTerminalContainer-7Pkqfotg.js +2 -0
  2. package/dist/client/assets/{TerminalPanel-B_7JSCCc.js → TerminalPanel-DAjuH-1U.js} +1 -1
  3. package/dist/client/assets/{_basePickBy-OQ1l2y4N.js → _basePickBy-B02OZLcK.js} +1 -1
  4. package/dist/client/assets/{_baseUniq-DP68ni3r.js → _baseUniq-DxmC1mRo.js} +1 -1
  5. package/dist/client/assets/{arc-BsOTNMJP.js → arc-BxtlwYEK.js} +1 -1
  6. package/dist/client/assets/{architectureDiagram-VXUJARFQ-5ctkZyKm.js → architectureDiagram-VXUJARFQ-BnYx6bly.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-VD42YOAC-JKAkJdAV.js → blockDiagram-VD42YOAC-HBOCmfSX.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-YG6GDRKO-RuKjDs_5.js → c4Diagram-YG6GDRKO-SWifZ63q.js} +1 -1
  9. package/dist/client/assets/channel-AmzbAQB9.js +1 -0
  10. package/dist/client/assets/{chunk-4BX2VUAB-BhHxyh-d.js → chunk-4BX2VUAB-CHmUyEof.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-CYm2wbN6.js → chunk-55IACEB6-CPjk6PkV.js} +1 -1
  12. package/dist/client/assets/{chunk-B4BG7PRW-C9lN0wb3.js → chunk-B4BG7PRW-wibRuvxs.js} +1 -1
  13. package/dist/client/assets/{chunk-DI55MBZ5-Bt2XM7pP.js → chunk-DI55MBZ5-3Os9hWPG.js} +1 -1
  14. package/dist/client/assets/{chunk-FMBD7UC4-CD7Uflt_.js → chunk-FMBD7UC4-CyyZMRYx.js} +1 -1
  15. package/dist/client/assets/{chunk-QN33PNHL-BU5wcW-Y.js → chunk-QN33PNHL-OjyZvCLX.js} +1 -1
  16. package/dist/client/assets/{chunk-QZHKN3VN-BfxuPp_p.js → chunk-QZHKN3VN-DvKGTNd6.js} +1 -1
  17. package/dist/client/assets/{chunk-TZMSLE5B-BRxuGNcy.js → chunk-TZMSLE5B-CiDjoyCu.js} +1 -1
  18. package/dist/client/assets/classDiagram-2ON5EDUG-B7NSG0Se.js +1 -0
  19. package/dist/client/assets/classDiagram-v2-WZHVMYZB-B7NSG0Se.js +1 -0
  20. package/dist/client/assets/clone-DGVvqALc.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-S5V4N54A-BRSOoelM.js → cose-bilkent-S5V4N54A-Xt9mkXow.js} +1 -1
  22. package/dist/client/assets/{dagre-6UL2VRFP-CqEPGLG_.js → dagre-6UL2VRFP-iKb8-8az.js} +1 -1
  23. package/dist/client/assets/{diagram-PSM6KHXK-CW6lQAph.js → diagram-PSM6KHXK-5EN_OWwE.js} +1 -1
  24. package/dist/client/assets/{diagram-QEK2KX5R-DXpQB09y.js → diagram-QEK2KX5R-Bspa_oIP.js} +1 -1
  25. package/dist/client/assets/{diagram-S2PKOQOG-BuKSc7hj.js → diagram-S2PKOQOG-rMh8HVTX.js} +1 -1
  26. package/dist/client/assets/{erDiagram-Q2GNP2WA-DCOsaIMe.js → erDiagram-Q2GNP2WA-DDIi6KEO.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-NV44I4VS-DcrleJ78.js → flowDiagram-NV44I4VS-keexbyTE.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-JELNMOA3-DvQNO27q.js → ganttDiagram-JELNMOA3-BJDtoWV3.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-DvTlrniW.js → gitGraphDiagram-V2S2FVAM-C3U_yDok.js} +1 -1
  30. package/dist/client/assets/{graph-BVOV61MY.js → graph-CXIustk1.js} +1 -1
  31. package/dist/client/assets/{highlighted-body-B3W2YXNL-s73Py2xy.js → highlighted-body-B3W2YXNL-Wrr4mAYt.js} +1 -1
  32. package/dist/client/assets/{index-DGRRlzO8.js → index--YcOjZeH.js} +1 -1
  33. package/dist/client/assets/{index-xFYSTaUY.js → index-6JEkkDo8.js} +1 -1
  34. package/dist/client/assets/{index-ouQJCO_a.js → index-Aitm1TDm.js} +1 -1
  35. package/dist/client/assets/{index-D3UFDKZm.js → index-BQnMh5Ey.js} +1 -1
  36. package/dist/client/assets/{index-CF9PCIXP.js → index-BW_n511W.js} +1 -1
  37. package/dist/client/assets/{index-V0GcGOe-.js → index-Bc5chL-g.js} +1 -1
  38. package/dist/client/assets/{index-D7QbmAu4.js → index-Br9YzqZk.js} +1 -1
  39. package/dist/client/assets/{index-CK-BTC9O.js → index-C49Jfk-p.js} +1 -1
  40. package/dist/client/assets/{index-DcHmgA8z.js → index-CImHE-vf.js} +1 -1
  41. package/dist/client/assets/{index-DpO1oBiD.js → index-CP6eh1me.js} +1 -1
  42. package/dist/client/assets/{index-0hkPM41a.js → index-DQZeHe3T.js} +1 -1
  43. package/dist/client/assets/{index-D8qAYkE6.js → index-DVb3uzxJ.js} +1 -1
  44. package/dist/client/assets/{index-DzkW40bH.js → index-DbV1dJqS.js} +1 -1
  45. package/dist/client/assets/{index-CNvrx9RT.js → index-Dp56OOnl.js} +1 -1
  46. package/dist/client/assets/{index-DLckpD-5.js → index-DyG7IfDO.js} +1 -1
  47. package/dist/client/assets/{index-DeXx_AuY.js → index-MvOIOMkW.js} +1 -1
  48. package/dist/client/assets/{index-BSkZi14t.js → index-XciBSftr.js} +1 -1
  49. package/dist/client/assets/{index-LSBeIErX.js → index-oZQsTqMq.js} +1 -1
  50. package/dist/client/assets/{infoDiagram-HS3SLOUP-BkIrT0lS.js → infoDiagram-HS3SLOUP-Coba2Ecg.js} +1 -1
  51. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-CuAJwUYZ.js → journeyDiagram-XKPGCS4Q-DcRdN5Jw.js} +1 -1
  52. package/dist/client/assets/{kanban-definition-3W4ZIXB7-C5oojjKn.js → kanban-definition-3W4ZIXB7-B4rTq8FU.js} +1 -1
  53. package/dist/client/assets/{layout-VixgcoEh.js → layout-CS8um6L3.js} +1 -1
  54. package/dist/client/assets/{linear-B8GEtbtI.js → linear-BN5Y0XM-.js} +1 -1
  55. package/dist/client/assets/{main-CaSLsHIV.js → main-BIlcXlzs.js} +235 -235
  56. package/dist/client/assets/main-BnrSCdeV.css +1 -0
  57. package/dist/client/assets/{mindmap-definition-VGOIOE7T-ChF2Jy20.js → mindmap-definition-VGOIOE7T-Ds51PqE9.js} +1 -1
  58. package/dist/client/assets/{pieDiagram-ADFJNKIX-Cs7BVmqM.js → pieDiagram-ADFJNKIX-gYVi9omj.js} +1 -1
  59. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-V83WZ4fh.js → quadrantDiagram-AYHSOK5B-C5iqQQKZ.js} +1 -1
  60. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-D2GE0VK5.js → requirementDiagram-UZGBJVZJ-BqKUhE2H.js} +1 -1
  61. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-C-ahmW9t.js → sankeyDiagram-TZEHDZUN-BkDgrkkQ.js} +1 -1
  62. package/dist/client/assets/{sequenceDiagram-WL72ISMW-CeikJo7j.js → sequenceDiagram-WL72ISMW-DOxbfZhn.js} +1 -1
  63. package/dist/client/assets/{stateDiagram-FKZM4ZOC-BxMm9YXu.js → stateDiagram-FKZM4ZOC-B3TrsBb9.js} +1 -1
  64. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-CQVcKuBa.js +1 -0
  65. package/dist/client/assets/{timeline-definition-IT6M3QCI-gFAlmUmY.js → timeline-definition-IT6M3QCI-DG2Hs4KW.js} +1 -1
  66. package/dist/client/assets/{treemap-GDKQZRPO-DKt9bIHO.js → treemap-GDKQZRPO-BgXNPM_M.js} +1 -1
  67. package/dist/client/assets/{useSessionListContext-DeLrvh5j.js → useSessionListContext-C4FLYEE-.js} +1 -1
  68. package/dist/client/assets/{workspace._workspaceId-Dm5LPp7D.js → workspace._workspaceId-B2-qsdVH.js} +1 -1
  69. package/dist/client/assets/{workspace._workspaceId.changes-DixHvPIg.js → workspace._workspaceId.changes-ah5-NQ9M.js} +1 -1
  70. package/dist/client/assets/workspace._workspaceId.code-BUlNqyPU.js +1 -0
  71. package/dist/client/assets/{workspace._workspaceId.code._-DWgmdTsF.js → workspace._workspaceId.code._-DebwiKyc.js} +1 -1
  72. package/dist/client/assets/{workspace._workspaceId.code.index-k3jnNrmM.js → workspace._workspaceId.code.index-BoCEbFIx.js} +1 -1
  73. package/dist/client/assets/{workspace._workspaceId.index-L6dOjOuf.js → workspace._workspaceId.index-sal33uc0.js} +1 -1
  74. package/dist/client/assets/{workspace._workspaceId.terminal-j5zlufNR.js → workspace._workspaceId.terminal-BquerOxc.js} +2 -2
  75. package/dist/client/assets/{xychartDiagram-PRI3JC2R-DCzhNdgu.js → xychartDiagram-PRI3JC2R-C25x1FNe.js} +1 -1
  76. package/dist/server/assets/{DockviewTerminalContainer-0lBzSHAB.js → DockviewTerminalContainer-BJRCcV8V.js} +10 -2
  77. package/dist/server/assets/{TerminalPanel-DlyqXpg4.js → TerminalPanel-C-Tqzsb9.js} +1 -1
  78. package/dist/server/assets/{_basePickBy-Uvw-ZCjq.js → _basePickBy-DnnQYRPA.js} +2 -2
  79. package/dist/server/assets/{_baseUniq-DJi3N8KD.js → _baseUniq-DK15vf9R.js} +1 -1
  80. package/dist/server/assets/{_tanstack-start-manifest_v-CLW7JNBK.js → _tanstack-start-manifest_v-51-y0m60.js} +1 -1
  81. package/dist/server/assets/{arc-B2OUCIV1.js → arc-NNeAZNFP.js} +1 -1
  82. package/dist/server/assets/{architecture-7HQA4BMR-BhS6ObWP.js → architecture-7HQA4BMR-CFBQ6v0L.js} +6 -6
  83. package/dist/server/assets/{architectureDiagram-VXUJARFQ-Zlx9bJA4.js → architectureDiagram-VXUJARFQ-C5DZiZyi.js} +6 -6
  84. package/dist/server/assets/{blockDiagram-VD42YOAC-D4Kk0Ngg.js → blockDiagram-VD42YOAC-L5ieGxFF.js} +6 -6
  85. package/dist/server/assets/{c4Diagram-YG6GDRKO-DyIulYvs.js → c4Diagram-YG6GDRKO-Bv39r0cE.js} +2 -2
  86. package/dist/server/assets/{channel-D5u33HGQ.js → channel-BJm48Wp9.js} +1 -1
  87. package/dist/server/assets/{chunk-4BX2VUAB-xAm1S4cV.js → chunk-4BX2VUAB-DJ-pm5Zg.js} +1 -1
  88. package/dist/server/assets/{chunk-55IACEB6-BKYzWPC-.js → chunk-55IACEB6-B6e_cQv2.js} +1 -1
  89. package/dist/server/assets/{chunk-B4BG7PRW-0GA7TpHM.js → chunk-B4BG7PRW-BuDzYmK0.js} +4 -4
  90. package/dist/server/assets/{chunk-DI55MBZ5-BZgnoUtH.js → chunk-DI55MBZ5-DjAWM8Pq.js} +3 -3
  91. package/dist/server/assets/{chunk-FMBD7UC4-D4-haik2.js → chunk-FMBD7UC4-DYB3IL_G.js} +1 -1
  92. package/dist/server/assets/{chunk-QN33PNHL-cz0i18Kh.js → chunk-QN33PNHL-CehfCXvD.js} +1 -1
  93. package/dist/server/assets/{chunk-QZHKN3VN-B6EetbPS.js → chunk-QZHKN3VN-BmLwAQLo.js} +1 -1
  94. package/dist/server/assets/{chunk-TZMSLE5B-Bs97HrcS.js → chunk-TZMSLE5B-7ME36Awr.js} +1 -1
  95. package/dist/server/assets/{classDiagram-v2-WZHVMYZB-DX-De1xE.js → classDiagram-2ON5EDUG-Bm6tgj68.js} +5 -5
  96. package/dist/server/assets/{classDiagram-2ON5EDUG-DX-De1xE.js → classDiagram-v2-WZHVMYZB-Bm6tgj68.js} +5 -5
  97. package/dist/server/assets/{clone-B8d9SkTy.js → clone-BcVyfejn.js} +1 -1
  98. package/dist/server/assets/{cose-bilkent-S5V4N54A-9mJAWvad.js → cose-bilkent-S5V4N54A-DmleNa4v.js} +1 -1
  99. package/dist/server/assets/{dagre-6UL2VRFP-C1atBmRs.js → dagre-6UL2VRFP-L-yKb3Zq.js} +6 -6
  100. package/dist/server/assets/{diagram-PSM6KHXK-CyGQvN3g.js → diagram-PSM6KHXK-CLQUsOvK.js} +7 -7
  101. package/dist/server/assets/{diagram-QEK2KX5R-DzfTH21h.js → diagram-QEK2KX5R-CPIjUINK.js} +6 -6
  102. package/dist/server/assets/{diagram-S2PKOQOG-Bn4ENm4_.js → diagram-S2PKOQOG-CT98niKC.js} +6 -6
  103. package/dist/server/assets/{erDiagram-Q2GNP2WA-DqzNX--h.js → erDiagram-Q2GNP2WA-B8SLNOhT.js} +4 -4
  104. package/dist/server/assets/{flowDiagram-NV44I4VS-qQuNi_ek.js → flowDiagram-NV44I4VS-CKOlpEYf.js} +5 -5
  105. package/dist/server/assets/{ganttDiagram-JELNMOA3-CvxepebM.js → ganttDiagram-JELNMOA3-Cz_3Y_fm.js} +2 -2
  106. package/dist/server/assets/{gitGraph-G5XIXVHT-BmYVGvm7.js → gitGraph-G5XIXVHT-Bd-Xnyvl.js} +6 -6
  107. package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-BIMAii04.js → gitGraphDiagram-V2S2FVAM-LTcGOQh8.js} +7 -7
  108. package/dist/server/assets/{graph-DXLb-QKT.js → graph-NUwJV50a.js} +2 -2
  109. package/dist/server/assets/{highlighted-body-B3W2YXNL-imCkdLOn.js → highlighted-body-B3W2YXNL-uXJZSUGv.js} +1 -1
  110. package/dist/server/assets/{index-RhBuqPPl.js → index-BL6ldRfC.js} +2 -2
  111. package/dist/server/assets/{index-D5lNe_xt.js → index-BR3UKwL5.js} +2 -2
  112. package/dist/server/assets/{index-vnItYDqO.js → index-BfIGXl0c.js} +2 -2
  113. package/dist/server/assets/{index-BR76j4Vk.js → index-BsiXULyc.js} +2 -2
  114. package/dist/server/assets/{index-BA0UwY9Z.js → index-Cc7MEkFb.js} +1 -1
  115. package/dist/server/assets/{index-xMc3ZlRc.js → index-CiwZb3K7.js} +2 -2
  116. package/dist/server/assets/{index-BG9HkusL.js → index-CjogWqmh.js} +5 -5
  117. package/dist/server/assets/{index-cStp1vpB.js → index-D3nc-6Y6.js} +3 -3
  118. package/dist/server/assets/{index-Du735q5O.js → index-DLBp1ZlP.js} +2 -2
  119. package/dist/server/assets/{index-CA8DyWtN.js → index-DTO2Bghw.js} +2 -2
  120. package/dist/server/assets/{index-CnuRAKgr.js → index-DcSGnX9Y.js} +3 -3
  121. package/dist/server/assets/{index-E4GEYitW.js → index-Dpdg8d2x.js} +4 -4
  122. package/dist/server/assets/{index-BZuMEWyk.js → index-GifGhqSy.js} +1 -1
  123. package/dist/server/assets/{index-CS3QeU4e.js → index-TSafpX9w.js} +5 -5
  124. package/dist/server/assets/{index-Cj7do86C.js → index-ehJX-x7u.js} +2 -2
  125. package/dist/server/assets/{index-CQTgGi5V.js → index-kawf-mXU.js} +2 -2
  126. package/dist/server/assets/{index-BOtyo6Nx.js → index-lgqrOY_d.js} +2 -2
  127. package/dist/server/assets/{index-A_IwCrQa.js → index-v2ZoIblX.js} +2 -2
  128. package/dist/server/assets/{info-VBDWY6EO-Dw4W0VYI.js → info-VBDWY6EO-CK3UQKwB.js} +6 -6
  129. package/dist/server/assets/{infoDiagram-HS3SLOUP-C2Qm4J_0.js → infoDiagram-HS3SLOUP-CHCI1AvB.js} +5 -5
  130. package/dist/server/assets/{journeyDiagram-XKPGCS4Q-C0cd_WBg.js → journeyDiagram-XKPGCS4Q-DnaN-6ze.js} +4 -4
  131. package/dist/server/assets/{kanban-definition-3W4ZIXB7-kcejmLgx.js → kanban-definition-3W4ZIXB7-JU-5yrQV.js} +2 -2
  132. package/dist/server/assets/{layout-EA-crFYK.js → layout-CdOTdZJ1.js} +4 -4
  133. package/dist/server/assets/{linear-DWOAXyT_.js → linear-BxoHwVMJ.js} +1 -1
  134. package/dist/server/assets/{mermaid-3ZIDBTTL-B3JY0bnx.js → mermaid-3ZIDBTTL-CKq41YLn.js} +1 -1
  135. package/dist/server/assets/{mermaid-parser.core-CxYB8AxK.js → mermaid-parser.core-DZVkd7yV.js} +11 -11
  136. package/dist/server/assets/{mindmap-definition-VGOIOE7T-C2uLj2ri.js → mindmap-definition-VGOIOE7T-D4mbSp8m.js} +3 -3
  137. package/dist/server/assets/{packet-DYOGHKS2-bCkPivks.js → packet-DYOGHKS2-nhhZIGJC.js} +6 -6
  138. package/dist/server/assets/{pie-VRWISCQL-cbn_jdq6.js → pie-VRWISCQL-kCISsi8U.js} +6 -6
  139. package/dist/server/assets/{pieDiagram-ADFJNKIX-BYnq3CiI.js → pieDiagram-ADFJNKIX-CHCBgglI.js} +7 -7
  140. package/dist/server/assets/{quadrantDiagram-AYHSOK5B-Bg0bur0-.js → quadrantDiagram-AYHSOK5B-D1Es_GIX.js} +2 -2
  141. package/dist/server/assets/{radar-ZZBFDIW7-CjGOJm-y.js → radar-ZZBFDIW7-_TLemglD.js} +6 -6
  142. package/dist/server/assets/{requirementDiagram-UZGBJVZJ-BiHrf5LP.js → requirementDiagram-UZGBJVZJ-CgQ8ccM0.js} +3 -3
  143. package/dist/server/assets/{router-BejKXIrT.js → router-ui6wVh7X.js} +444 -98
  144. package/dist/server/assets/{sankeyDiagram-TZEHDZUN-BLGAaS-t.js → sankeyDiagram-TZEHDZUN-dV-3kXAD.js} +1 -1
  145. package/dist/server/assets/{sequenceDiagram-WL72ISMW-CSRhSSG0.js → sequenceDiagram-WL72ISMW-DSjsmvhJ.js} +3 -3
  146. package/dist/server/assets/{stateDiagram-FKZM4ZOC-B_CCwVLH.js → stateDiagram-FKZM4ZOC-D1P44e7A.js} +8 -8
  147. package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-Br6BE9Dl.js → stateDiagram-v2-4FDKWEC3-BUB-g8R5.js} +4 -4
  148. package/dist/server/assets/{timeline-definition-IT6M3QCI-CpqSODIH.js → timeline-definition-IT6M3QCI-o0TWDfVE.js} +2 -2
  149. package/dist/server/assets/{treemap-GDKQZRPO-BqVJj6g2.js → treemap-GDKQZRPO-BnU8dMVn.js} +6 -6
  150. package/dist/server/assets/{workspace._workspaceId-BbEoQ0xz.js → workspace._workspaceId-BKa2ZK9u.js} +1 -1
  151. package/dist/server/assets/{workspace._workspaceId.changes-DRDZGvmq.js → workspace._workspaceId.changes-B8i8BeUK.js} +1 -1
  152. package/dist/server/assets/{workspace._workspaceId.code._-B5vvVD15.js → workspace._workspaceId.code._-4IwwK8EO.js} +1 -1
  153. package/dist/server/assets/{workspace._workspaceId.code.index-BDyHn77d.js → workspace._workspaceId.code.index-BTqIEfGL.js} +1 -1
  154. package/dist/server/assets/{workspace._workspaceId.index-ZhjhoB2w.js → workspace._workspaceId.index-ac3z18YW.js} +1 -1
  155. package/dist/server/assets/{workspace._workspaceId.terminal-Bi68U-9c.js → workspace._workspaceId.terminal-CvQaDekl.js} +2 -2
  156. package/dist/server/assets/{xychartDiagram-PRI3JC2R-AnGllwBT.js → xychartDiagram-PRI3JC2R-_U_JrS6w.js} +2 -2
  157. package/dist/server/server.js +2 -2
  158. package/dist/start-server.mjs +1111 -713
  159. package/package.json +5 -5
  160. package/dist/client/assets/DockviewTerminalContainer-C0Z9VUwT.js +0 -2
  161. package/dist/client/assets/channel-BJ7kvLrw.js +0 -1
  162. package/dist/client/assets/classDiagram-2ON5EDUG-DtIBgqOd.js +0 -1
  163. package/dist/client/assets/classDiagram-v2-WZHVMYZB-DtIBgqOd.js +0 -1
  164. package/dist/client/assets/clone-BC8-cd9B.js +0 -1
  165. package/dist/client/assets/main-DunGnoXJ.css +0 -1
  166. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-CMecyWp7.js +0 -1
  167. package/dist/client/assets/workspace._workspaceId.code-ClgjzVFK.js +0 -1
@@ -29602,6 +29602,15 @@ ${lines.join("\n")}`;
29602
29602
  function encodeProjectDir(absDir) {
29603
29603
  return absDir.replace(/[^a-zA-Z0-9]/g, "-");
29604
29604
  }
29605
+ function lruSet(map2, key, value, cap) {
29606
+ if (map2.has(key)) map2.delete(key);
29607
+ map2.set(key, value);
29608
+ while (map2.size > cap) {
29609
+ const oldest = map2.keys().next().value;
29610
+ if (oldest === void 0) break;
29611
+ map2.delete(oldest);
29612
+ }
29613
+ }
29605
29614
  async function readSessionLastPrompt(workspaceDir, sessionId) {
29606
29615
  const configDir = process.env.CLAUDE_CONFIG_DIR || join4(homedir(), ".claude");
29607
29616
  const file2 = join4(configDir, "projects", encodeProjectDir(workspaceDir), `${sessionId}.jsonl`);
@@ -29643,11 +29652,19 @@ async function readSessionLastPrompt(workspaceDir, sessionId) {
29643
29652
  }
29644
29653
  }
29645
29654
  }
29655
+ function claudeContextForId(id) {
29656
+ if (id.includes("[1m]")) return 1e6;
29657
+ if (id.startsWith("claude-haiku")) return 2e5;
29658
+ if (id.startsWith("claude-opus")) return 2e5;
29659
+ if (id.startsWith("claude-sonnet")) return 1e6;
29660
+ return void 0;
29661
+ }
29646
29662
  function mapModelInfo(info) {
29647
29663
  return {
29648
29664
  id: info.value,
29649
29665
  name: info.displayName,
29650
- description: info.description
29666
+ description: info.description,
29667
+ contextWindow: claudeContextForId(info.value)
29651
29668
  };
29652
29669
  }
29653
29670
  function mapSessionInfo(info, lastPrompt) {
@@ -29835,7 +29852,7 @@ function discoverClaudeSkills(workspaceDir) {
29835
29852
  }
29836
29853
  return Array.from(skillMap.values()).sort((a6, b10) => a6.name.localeCompare(b10.name));
29837
29854
  }
29838
- var log2, SESSION_TAIL_BYTES, ClaudeCodeAdapter;
29855
+ var log2, SESSION_TAIL_BYTES, cumulativeUsageBySession, MAX_CUMULATIVE_SESSIONS, ClaudeCodeAdapter;
29839
29856
  var init_claude_code = __esm({
29840
29857
  "../../packages/coding-agent/src/adapters/claude-code.ts"() {
29841
29858
  init_sdk();
@@ -29843,6 +29860,8 @@ var init_claude_code = __esm({
29843
29860
  init_skills();
29844
29861
  log2 = createLogger("coding-agent:claude-code");
29845
29862
  SESSION_TAIL_BYTES = 64 * 1024;
29863
+ cumulativeUsageBySession = /* @__PURE__ */ new Map();
29864
+ MAX_CUMULATIVE_SESSIONS = 500;
29846
29865
  ClaudeCodeAdapter = class {
29847
29866
  name = "Claude Code";
29848
29867
  supportedFeatures = {
@@ -29943,6 +29962,37 @@ var init_claude_code = __esm({
29943
29962
  toolNames: /* @__PURE__ */ new Map(),
29944
29963
  hasEmittedTextSinceLastUser: false
29945
29964
  };
29965
+ let currentSessionId = sessionId ?? "";
29966
+ const initialCumulative = currentSessionId ? cumulativeUsageBySession.get(currentSessionId) : void 0;
29967
+ let cumulativeInput = initialCumulative?.input ?? 0;
29968
+ let cumulativeOutput = initialCumulative?.output ?? 0;
29969
+ let cumulativeCacheRead = initialCumulative?.cacheRead ?? 0;
29970
+ let cumulativeCacheCreation = initialCumulative?.cacheCreation ?? 0;
29971
+ const persistCumulative = () => {
29972
+ if (!currentSessionId) return;
29973
+ lruSet(
29974
+ cumulativeUsageBySession,
29975
+ currentSessionId,
29976
+ {
29977
+ input: cumulativeInput,
29978
+ output: cumulativeOutput,
29979
+ cacheRead: cumulativeCacheRead,
29980
+ cacheCreation: cumulativeCacheCreation
29981
+ },
29982
+ MAX_CUMULATIVE_SESSIONS
29983
+ );
29984
+ };
29985
+ const adoptSessionId = (newSid) => {
29986
+ if (!newSid || newSid === currentSessionId) return;
29987
+ const prevStored = currentSessionId ? cumulativeUsageBySession.get(currentSessionId) : void 0;
29988
+ if (prevStored) {
29989
+ lruSet(cumulativeUsageBySession, newSid, prevStored, MAX_CUMULATIVE_SESSIONS);
29990
+ cumulativeUsageBySession.delete(currentSessionId);
29991
+ }
29992
+ currentSessionId = newSid;
29993
+ persistCumulative();
29994
+ };
29995
+ let lastKnownContext;
29946
29996
  try {
29947
29997
  for await (const message of conversation) {
29948
29998
  log2.debug(
@@ -29952,7 +30002,69 @@ var init_claude_code = __esm({
29952
30002
  },
29953
30003
  "sdk message"
29954
30004
  );
30005
+ const rawSid = message.session_id;
30006
+ if (rawSid != null) {
30007
+ adoptSessionId(String(rawSid));
30008
+ }
30009
+ if (message.type === "result") {
30010
+ const resultUsage = message.usage;
30011
+ if (resultUsage) {
30012
+ const inputTokens = resultUsage.input_tokens ?? 0;
30013
+ const outputTokens = resultUsage.output_tokens ?? 0;
30014
+ const cacheReadTokens = resultUsage.cache_read_input_tokens ?? 0;
30015
+ const cacheCreationTokens = resultUsage.cache_creation_input_tokens ?? 0;
30016
+ cumulativeInput += inputTokens;
30017
+ cumulativeOutput += outputTokens;
30018
+ cumulativeCacheRead += cacheReadTokens;
30019
+ cumulativeCacheCreation += cacheCreationTokens;
30020
+ persistCumulative();
30021
+ if (!lastKnownContext) {
30022
+ try {
30023
+ const ctx = await conversation.getContextUsage();
30024
+ lastKnownContext = {
30025
+ contextTokens: ctx.totalTokens,
30026
+ maxContextTokens: ctx.maxTokens
30027
+ };
30028
+ } catch (err) {
30029
+ log2.warn({ err }, "getContextUsage failed on result; emitting without snapshot");
30030
+ }
30031
+ }
30032
+ yield {
30033
+ type: "usage",
30034
+ provider: "claude",
30035
+ inputTokens,
30036
+ outputTokens,
30037
+ cacheReadTokens,
30038
+ cacheCreationTokens,
30039
+ contextTokens: lastKnownContext?.contextTokens,
30040
+ maxContextTokens: lastKnownContext?.maxContextTokens,
30041
+ totalProcessedTokens: cumulativeInput + cumulativeOutput + cumulativeCacheRead + cumulativeCacheCreation
30042
+ };
30043
+ }
30044
+ }
29955
30045
  yield* mapClaudeCodeEvent(message, state2);
30046
+ if (message.type === "assistant" && message.parent_tool_use_id == null) {
30047
+ try {
30048
+ const ctx = await conversation.getContextUsage();
30049
+ lastKnownContext = {
30050
+ contextTokens: ctx.totalTokens,
30051
+ maxContextTokens: ctx.maxTokens
30052
+ };
30053
+ yield {
30054
+ type: "usage",
30055
+ provider: "claude",
30056
+ inputTokens: cumulativeInput,
30057
+ outputTokens: cumulativeOutput,
30058
+ cacheReadTokens: cumulativeCacheRead,
30059
+ cacheCreationTokens: cumulativeCacheCreation,
30060
+ contextTokens: ctx.totalTokens,
30061
+ maxContextTokens: ctx.maxTokens,
30062
+ totalProcessedTokens: cumulativeInput + cumulativeOutput + cumulativeCacheRead + cumulativeCacheCreation
30063
+ };
30064
+ } catch (err) {
30065
+ log2.warn({ err }, "getContextUsage failed; skipping usage emission");
30066
+ }
30067
+ }
29956
30068
  }
29957
30069
  log2.info("conversation generator done");
29958
30070
  } catch (err) {
@@ -30057,28 +30169,33 @@ var init_claude_code = __esm({
30057
30169
  return [
30058
30170
  {
30059
30171
  id: "claude-sonnet-4-6",
30060
- name: "Default (recommended)",
30061
- description: "Use the default model (currently Sonnet 4.6) \xB7 $3/$15 per Mtok"
30172
+ name: "Sonnet 4.6",
30173
+ description: "Balanced default for everyday work",
30174
+ contextWindow: claudeContextForId("claude-sonnet-4-6")
30062
30175
  },
30063
30176
  {
30064
30177
  id: "claude-sonnet-4-6[1m]",
30065
- name: "Sonnet (1M context)",
30066
- description: "Sonnet 4.6 for long sessions \xB7 $6/$22.50 per Mtok"
30178
+ name: "Sonnet 4.6 (1M)",
30179
+ description: "Long-context tier for large sessions",
30180
+ contextWindow: 1e6
30067
30181
  },
30068
30182
  {
30069
30183
  id: "claude-opus-4-7",
30070
- name: "Opus",
30071
- description: "Opus 4.7 \xB7 Most capable for complex work \xB7 $5/$25 per Mtok"
30184
+ name: "Opus 4.7",
30185
+ description: "Most capable for complex work",
30186
+ contextWindow: claudeContextForId("claude-opus-4-7")
30072
30187
  },
30073
30188
  {
30074
30189
  id: "claude-opus-4-7[1m]",
30075
- name: "Opus (1M context)",
30076
- description: "Opus 4.7 for long sessions \xB7 $10/$37.50 per Mtok"
30190
+ name: "Opus 4.7 (1M)",
30191
+ description: "Most capable, long-context tier",
30192
+ contextWindow: 1e6
30077
30193
  },
30078
30194
  {
30079
30195
  id: "claude-haiku-4-5-20251001",
30080
- name: "Haiku",
30081
- description: "Haiku 4.5 \xB7 Fastest for quick answers \xB7 $1/$5 per Mtok"
30196
+ name: "Haiku 4.5",
30197
+ description: "Fastest for quick answers",
30198
+ contextWindow: claudeContextForId("claude-haiku-4-5-20251001")
30082
30199
  }
30083
30200
  ];
30084
30201
  }
@@ -30905,8 +31022,13 @@ var init_openai_codex = __esm({
30905
31022
  }
30906
31023
  listModels() {
30907
31024
  return [
30908
- { id: "codex-mini", name: "Codex Mini", description: "Fast and efficient" },
30909
- { id: "o4-mini", name: "o4-mini" }
31025
+ {
31026
+ id: "codex-mini",
31027
+ name: "Codex Mini",
31028
+ description: "Fast and efficient",
31029
+ contextWindow: 2e5
31030
+ },
31031
+ { id: "o4-mini", name: "o4-mini", contextWindow: 2e5 }
30910
31032
  ];
30911
31033
  }
30912
31034
  };
@@ -31387,6 +31509,15 @@ import { readdir, stat as stat2 } from "node:fs/promises";
31387
31509
  import { homedir as homedir3 } from "node:os";
31388
31510
  import { join as join6 } from "node:path";
31389
31511
  import { createInterface } from "node:readline";
31512
+ function lruSet2(map2, key, value, cap) {
31513
+ if (map2.has(key)) map2.delete(key);
31514
+ map2.set(key, value);
31515
+ while (map2.size > cap) {
31516
+ const oldest = map2.keys().next().value;
31517
+ if (oldest === void 0) break;
31518
+ map2.delete(oldest);
31519
+ }
31520
+ }
31390
31521
  function resolveCodexBinary() {
31391
31522
  try {
31392
31523
  const cmd = process.platform === "win32" ? "where" : "which";
@@ -31733,13 +31864,15 @@ async function readCodexSessionMessages(sessionId, options2) {
31733
31864
  const slice = hasMore ? collected.slice(0, requested) : collected;
31734
31865
  return { messages: slice, hasMore, firstOffset: offset4 };
31735
31866
  }
31736
- var log5, CodexAdapter, CODEX_MODELS, CODEX_HOME2, SESSIONS_DIR;
31867
+ var log5, cumulativeUsageBySession2, MAX_CUMULATIVE_SESSIONS2, CodexAdapter, CODEX_CTX, CODEX_MODELS, CODEX_HOME2, SESSIONS_DIR;
31737
31868
  var init_codex = __esm({
31738
31869
  "../../packages/coding-agent/src/adapters/codex.ts"() {
31739
31870
  init_src();
31740
31871
  init_dist2();
31741
31872
  init_skills();
31742
31873
  log5 = createLogger("coding-agent:codex");
31874
+ cumulativeUsageBySession2 = /* @__PURE__ */ new Map();
31875
+ MAX_CUMULATIVE_SESSIONS2 = 500;
31743
31876
  CodexAdapter = class {
31744
31877
  name = "Codex";
31745
31878
  supportedFeatures = {
@@ -31807,9 +31940,34 @@ var init_codex = __esm({
31807
31940
  });
31808
31941
  const startMs = Date.now();
31809
31942
  let turnCount = 0;
31810
- let totalInputTokens = 0;
31811
- let totalOutputTokens = 0;
31812
31943
  let actualSessionId = sessionId ?? "";
31944
+ const initialCumulative = actualSessionId ? cumulativeUsageBySession2.get(actualSessionId) : void 0;
31945
+ let totalInputTokens = initialCumulative?.input ?? 0;
31946
+ let totalOutputTokens = initialCumulative?.output ?? 0;
31947
+ let totalReasoningOutputTokens = initialCumulative?.reasoningOutput ?? 0;
31948
+ const persistCumulative = () => {
31949
+ if (!actualSessionId) return;
31950
+ lruSet2(
31951
+ cumulativeUsageBySession2,
31952
+ actualSessionId,
31953
+ {
31954
+ input: totalInputTokens,
31955
+ output: totalOutputTokens,
31956
+ reasoningOutput: totalReasoningOutputTokens
31957
+ },
31958
+ MAX_CUMULATIVE_SESSIONS2
31959
+ );
31960
+ };
31961
+ const adoptSessionId = (newSid) => {
31962
+ if (!newSid || newSid === actualSessionId) return;
31963
+ const prevStored = actualSessionId ? cumulativeUsageBySession2.get(actualSessionId) : void 0;
31964
+ if (prevStored) {
31965
+ lruSet2(cumulativeUsageBySession2, newSid, prevStored, MAX_CUMULATIVE_SESSIONS2);
31966
+ cumulativeUsageBySession2.delete(actualSessionId);
31967
+ }
31968
+ actualSessionId = newSid;
31969
+ persistCumulative();
31970
+ };
31813
31971
  const runStreamedStartMs = Date.now();
31814
31972
  log5.info("calling thread.runStreamed");
31815
31973
  let result;
@@ -31838,13 +31996,16 @@ var init_codex = __esm({
31838
31996
  this.activeIterator = iterator;
31839
31997
  const toolNames = /* @__PURE__ */ new Map();
31840
31998
  const emittedTextLengths = /* @__PURE__ */ new Map();
31999
+ let lastTurnOutcome = null;
32000
+ let lastTurnError = null;
31841
32001
  try {
31842
32002
  for await (const event of { [Symbol.asyncIterator]: () => iterator }) {
31843
32003
  log5.debug({ eventType: event.type }, "codex event");
31844
32004
  switch (event.type) {
31845
32005
  // ── Session lifecycle ──────────────────────────────────────────
31846
32006
  case "thread.started": {
31847
- actualSessionId = event.thread_id ?? sessionId ?? "";
32007
+ const resolvedSid = event.thread_id ?? sessionId ?? "";
32008
+ adoptSessionId(resolvedSid);
31848
32009
  log5.info(
31849
32010
  { threadId: event.thread_id, sessionIdParam: sessionId, actualSessionId },
31850
32011
  "codex thread.started"
@@ -31874,29 +32035,49 @@ var init_codex = __esm({
31874
32035
  break;
31875
32036
  }
31876
32037
  case "turn.completed": {
31877
- totalInputTokens += event.usage.input_tokens;
31878
- totalOutputTokens += event.usage.output_tokens;
32038
+ const usage = event.usage ?? {
32039
+ input_tokens: 0,
32040
+ output_tokens: 0,
32041
+ cached_input_tokens: 0,
32042
+ reasoning_output_tokens: 0
32043
+ };
32044
+ const inputTokens = usage.input_tokens ?? 0;
32045
+ const outputTokens = usage.output_tokens ?? 0;
32046
+ const cachedInputTokens = usage.cached_input_tokens ?? 0;
32047
+ const reasoningOutputTokens = usage.reasoning_output_tokens ?? 0;
32048
+ const contextTokens = inputTokens + outputTokens + reasoningOutputTokens;
32049
+ totalInputTokens += inputTokens;
32050
+ totalOutputTokens += outputTokens;
32051
+ totalReasoningOutputTokens += reasoningOutputTokens;
32052
+ persistCumulative();
32053
+ log5.debug(
32054
+ {
32055
+ inputTokens,
32056
+ outputTokens,
32057
+ cachedInputTokens,
32058
+ reasoningOutputTokens,
32059
+ contextTokens,
32060
+ totalProcessed: totalInputTokens + totalOutputTokens + totalReasoningOutputTokens
32061
+ },
32062
+ "codex usage emitted"
32063
+ );
31879
32064
  yield {
31880
- type: "session-result",
31881
- success: true,
31882
- sessionId: actualSessionId,
31883
- durationMs: Date.now() - startMs,
31884
- numTurns: turnCount,
31885
- costUsd: 0,
31886
- errors: []
32065
+ type: "usage",
32066
+ provider: "codex",
32067
+ inputTokens,
32068
+ outputTokens,
32069
+ cacheReadTokens: cachedInputTokens,
32070
+ reasoningOutputTokens,
32071
+ contextTokens,
32072
+ totalProcessedTokens: totalInputTokens + totalOutputTokens + totalReasoningOutputTokens
31887
32073
  };
32074
+ lastTurnOutcome = "completed";
32075
+ lastTurnError = null;
31888
32076
  break;
31889
32077
  }
31890
32078
  case "turn.failed": {
31891
- yield {
31892
- type: "session-result",
31893
- success: false,
31894
- sessionId: actualSessionId,
31895
- durationMs: Date.now() - startMs,
31896
- numTurns: turnCount,
31897
- costUsd: 0,
31898
- errors: [event.error.message]
31899
- };
32079
+ lastTurnOutcome = "failed";
32080
+ lastTurnError = event.error.message;
31900
32081
  break;
31901
32082
  }
31902
32083
  // ── Errors ────────────────────────────────────────────────────
@@ -31914,11 +32095,23 @@ var init_codex = __esm({
31914
32095
  turnCount,
31915
32096
  totalInputTokens,
31916
32097
  totalOutputTokens,
32098
+ totalReasoningOutputTokens,
31917
32099
  actualSessionId,
31918
32100
  elapsedMs: Date.now() - startMs
31919
32101
  },
31920
32102
  "codex stream done \u2014 all events consumed"
31921
32103
  );
32104
+ if (lastTurnOutcome !== null) {
32105
+ yield {
32106
+ type: "session-result",
32107
+ success: lastTurnOutcome === "completed",
32108
+ sessionId: actualSessionId,
32109
+ durationMs: Date.now() - startMs,
32110
+ numTurns: turnCount,
32111
+ costUsd: 0,
32112
+ errors: lastTurnError ? [lastTurnError] : []
32113
+ };
32114
+ }
31922
32115
  } catch (err) {
31923
32116
  const msg = err instanceof Error ? err.message : String(err);
31924
32117
  log5.error({ err, cwd: this.workspaceDir }, "codex stream error");
@@ -31958,12 +32151,38 @@ var init_codex = __esm({
31958
32151
  return readCodexSessionMessages(sessionId, options2);
31959
32152
  }
31960
32153
  };
32154
+ CODEX_CTX = 4e5;
31961
32155
  CODEX_MODELS = [
31962
- { id: "gpt-5.5", name: "GPT-5.5", description: "Flagship frontier model" },
31963
- { id: "gpt-5.4", name: "GPT-5.4", description: "Previous flagship model" },
31964
- { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", description: "Fast, efficient mini model" },
31965
- { id: "gpt-5.3-codex", name: "GPT-5.3 Codex", description: "Coding-optimized model" },
31966
- { id: "gpt-5.2-codex", name: "GPT-5.2 Codex", description: "Previous coding-optimized model" }
32156
+ {
32157
+ id: "gpt-5.5",
32158
+ name: "GPT-5.5",
32159
+ description: "Flagship frontier model",
32160
+ contextWindow: CODEX_CTX
32161
+ },
32162
+ {
32163
+ id: "gpt-5.4",
32164
+ name: "GPT-5.4",
32165
+ description: "Previous flagship model",
32166
+ contextWindow: CODEX_CTX
32167
+ },
32168
+ {
32169
+ id: "gpt-5.4-mini",
32170
+ name: "GPT-5.4 Mini",
32171
+ description: "Fast, efficient mini model",
32172
+ contextWindow: CODEX_CTX
32173
+ },
32174
+ {
32175
+ id: "gpt-5.3-codex",
32176
+ name: "GPT-5.3 Codex",
32177
+ description: "Coding-optimized model",
32178
+ contextWindow: CODEX_CTX
32179
+ },
32180
+ {
32181
+ id: "gpt-5.2-codex",
32182
+ name: "GPT-5.2 Codex",
32183
+ description: "Previous coding-optimized model",
32184
+ contextWindow: CODEX_CTX
32185
+ }
31967
32186
  ];
31968
32187
  CODEX_HOME2 = process.env.CODEX_HOME || join6(homedir3(), ".codex");
31969
32188
  SESSIONS_DIR = join6(CODEX_HOME2, "sessions");
@@ -32151,8 +32370,18 @@ var init_gemini_cli = __esm({
32151
32370
  }
32152
32371
  listModels() {
32153
32372
  return [
32154
- { id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", description: "Most capable" },
32155
- { id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", description: "Fast and efficient" }
32373
+ {
32374
+ id: "gemini-2.5-pro",
32375
+ name: "Gemini 2.5 Pro",
32376
+ description: "Most capable",
32377
+ contextWindow: 1e6
32378
+ },
32379
+ {
32380
+ id: "gemini-2.5-flash",
32381
+ name: "Gemini 2.5 Flash",
32382
+ description: "Fast and efficient",
32383
+ contextWindow: 1e6
32384
+ }
32156
32385
  ];
32157
32386
  }
32158
32387
  };
@@ -32423,6 +32652,9 @@ var init_opencode = __esm({
32423
32652
  child.stderr.on("data", (chunk) => {
32424
32653
  stderrChunks.push(chunk.toString());
32425
32654
  });
32655
+ const exitCodePromise = new Promise((resolve8) => {
32656
+ child.on("close", (code) => resolve8(code ?? 0));
32657
+ });
32426
32658
  const rl = createInterface3({ input: child.stdout });
32427
32659
  try {
32428
32660
  for await (const line2 of rl) {
@@ -32481,9 +32713,7 @@ var init_opencode = __esm({
32481
32713
  }
32482
32714
  }
32483
32715
  }
32484
- lastExitCode = await new Promise((resolve8) => {
32485
- child.on("close", (code) => resolve8(code ?? 0));
32486
- });
32716
+ lastExitCode = await exitCodePromise;
32487
32717
  lastStderr = stderrChunks.join("");
32488
32718
  if (!gotOutput && effectiveSessionId && attempt < maxAttempts) {
32489
32719
  log7.warn(
@@ -119484,7 +119714,7 @@ var import_react10 = __toESM(require_react(), 1);
119484
119714
  var import_jsx_runtime49 = __toESM(require_jsx_runtime(), 1);
119485
119715
 
119486
119716
  // ../../packages/dashboard-core/src/components/DashboardShell.tsx
119487
- var import_react18 = __toESM(require_react(), 1);
119717
+ var import_react19 = __toESM(require_react(), 1);
119488
119718
 
119489
119719
  // ../../packages/dashboard-core/src/hooks/use-cli-setup.ts
119490
119720
  var import_react11 = __toESM(require_react(), 1);
@@ -119702,6 +119932,9 @@ var WorkspaceCard = (0, import_react15.memo)(function WorkspaceCard2({
119702
119932
  var import_jsx_runtime55 = __toESM(require_jsx_runtime(), 1);
119703
119933
 
119704
119934
  // ../../packages/dashboard-core/src/components/SettingsPage.tsx
119935
+ var import_react18 = __toESM(require_react(), 1);
119936
+
119937
+ // ../../packages/dashboard-core/src/lib/experimental-flags.ts
119705
119938
  var import_react17 = __toESM(require_react(), 1);
119706
119939
 
119707
119940
  // ../../packages/dashboard-core/src/components/settings/SettingsRow.tsx
@@ -119719,13 +119952,13 @@ var isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
119719
119952
 
119720
119953
  // ../../packages/dashboard-core/src/components/DiffView.tsx
119721
119954
  init_dist4();
119722
- var import_react22 = __toESM(require_react(), 1);
119955
+ var import_react23 = __toESM(require_react(), 1);
119723
119956
 
119724
119957
  // ../../packages/dashboard-core/src/hooks/use-search.ts
119725
- var import_react19 = __toESM(require_react(), 1);
119958
+ var import_react20 = __toESM(require_react(), 1);
119726
119959
 
119727
119960
  // ../../packages/dashboard-core/src/components/ChangesFileTree.tsx
119728
- var import_react20 = __toESM(require_react(), 1);
119961
+ var import_react21 = __toESM(require_react(), 1);
119729
119962
 
119730
119963
  // ../../packages/dashboard-core/src/components/FileStatusBadge.tsx
119731
119964
  var import_jsx_runtime60 = __toESM(require_jsx_runtime(), 1);
@@ -119738,7 +119971,7 @@ var import_jsx_runtime62 = __toESM(require_jsx_runtime(), 1);
119738
119971
 
119739
119972
  // ../../packages/dashboard-core/src/components/SearchBar.tsx
119740
119973
  var import_lucide_react5 = __toESM(require_lucide_react(), 1);
119741
- var import_react21 = __toESM(require_react(), 1);
119974
+ var import_react22 = __toESM(require_react(), 1);
119742
119975
  var import_jsx_runtime63 = __toESM(require_jsx_runtime(), 1);
119743
119976
  function ToggleButton({
119744
119977
  active,
@@ -119757,7 +119990,7 @@ function ToggleButton({
119757
119990
  }
119758
119991
  );
119759
119992
  }
119760
- var SearchBar = (0, import_react21.forwardRef)(function SearchBar2({
119993
+ var SearchBar = (0, import_react22.forwardRef)(function SearchBar2({
119761
119994
  query,
119762
119995
  onQueryChange,
119763
119996
  options: options2,
@@ -119769,18 +120002,18 @@ var SearchBar = (0, import_react21.forwardRef)(function SearchBar2({
119769
120002
  onClose,
119770
120003
  className
119771
120004
  }, ref) {
119772
- const inputRef = (0, import_react21.useRef)(null);
119773
- (0, import_react21.useImperativeHandle)(ref, () => ({
120005
+ const inputRef = (0, import_react22.useRef)(null);
120006
+ (0, import_react22.useImperativeHandle)(ref, () => ({
119774
120007
  focus: () => inputRef.current?.focus(),
119775
120008
  select: () => inputRef.current?.select()
119776
120009
  }));
119777
- const toggleCase = (0, import_react21.useCallback)(() => {
120010
+ const toggleCase = (0, import_react22.useCallback)(() => {
119778
120011
  onOptionsChange({ ...options2, caseSensitive: !options2.caseSensitive });
119779
120012
  }, [options2, onOptionsChange]);
119780
- const toggleWholeWord = (0, import_react21.useCallback)(() => {
120013
+ const toggleWholeWord = (0, import_react22.useCallback)(() => {
119781
120014
  onOptionsChange({ ...options2, wholeWord: !options2.wholeWord });
119782
120015
  }, [options2, onOptionsChange]);
119783
- const toggleRegex = (0, import_react21.useCallback)(() => {
120016
+ const toggleRegex = (0, import_react22.useCallback)(() => {
119784
120017
  onOptionsChange({ ...options2, regex: !options2.regex });
119785
120018
  }, [options2, onOptionsChange]);
119786
120019
  return /* @__PURE__ */ (0, import_jsx_runtime63.jsxs)(
@@ -119902,14 +120135,14 @@ var diffTheme = EditorView.theme({
119902
120135
  });
119903
120136
 
119904
120137
  // ../../packages/dashboard-core/src/components/FileBrowser.tsx
119905
- var import_react23 = __toESM(require_react(), 1);
120138
+ var import_react24 = __toESM(require_react(), 1);
119906
120139
  var import_jsx_runtime65 = __toESM(require_jsx_runtime(), 1);
119907
120140
 
119908
120141
  // ../../packages/dashboard-core/src/components/FileViewer.tsx
119909
- var import_react25 = __toESM(require_react(), 1);
120142
+ var import_react26 = __toESM(require_react(), 1);
119910
120143
 
119911
120144
  // ../../packages/dashboard-core/src/components/ImagePreview.tsx
119912
- var import_react24 = __toESM(require_react(), 1);
120145
+ var import_react25 = __toESM(require_react(), 1);
119913
120146
  var import_jsx_runtime66 = __toESM(require_jsx_runtime(), 1);
119914
120147
 
119915
120148
  // ../../packages/dashboard-core/src/components/PdfPreview.tsx
@@ -119919,22 +120152,22 @@ var import_jsx_runtime67 = __toESM(require_jsx_runtime(), 1);
119919
120152
  var import_jsx_runtime68 = __toESM(require_jsx_runtime(), 1);
119920
120153
 
119921
120154
  // ../../packages/dashboard-core/src/components/QuickOpenDialog.tsx
119922
- var import_react26 = __toESM(require_react(), 1);
120155
+ var import_react27 = __toESM(require_react(), 1);
119923
120156
  var import_jsx_runtime69 = __toESM(require_jsx_runtime(), 1);
119924
120157
 
119925
120158
  // ../../packages/dashboard-core/src/components/SearchFilesDialog.tsx
119926
- var import_react27 = __toESM(require_react(), 1);
120159
+ var import_react28 = __toESM(require_react(), 1);
119927
120160
  var import_jsx_runtime70 = __toESM(require_jsx_runtime(), 1);
119928
120161
 
119929
120162
  // ../../packages/dashboard-core/src/components/WorkspacePickerDialog.tsx
119930
- var import_react28 = __toESM(require_react(), 1);
120163
+ var import_react29 = __toESM(require_react(), 1);
119931
120164
  var import_jsx_runtime71 = __toESM(require_jsx_runtime(), 1);
119932
120165
 
119933
120166
  // ../../packages/dashboard-core/src/components/WorkspaceTabNav.tsx
119934
120167
  var import_jsx_runtime72 = __toESM(require_jsx_runtime(), 1);
119935
120168
 
119936
120169
  // ../../packages/dashboard-core/src/hooks/use-editor-history.ts
119937
- var import_react29 = __toESM(require_react(), 1);
120170
+ var import_react30 = __toESM(require_react(), 1);
119938
120171
 
119939
120172
  // ../../node_modules/.pnpm/marked@15.0.12/node_modules/marked/lib/marked.esm.js
119940
120173
  function _getDefaults() {
@@ -130105,489 +130338,268 @@ function listPanelStatesForWorkspace(workspaceId, panelType) {
130105
130338
  return db2.select().from(panelStates).where(and(eq2(panelStates.workspaceId, workspaceId), eq2(panelStates.panelType, panelType))).all();
130106
130339
  }
130107
130340
 
130108
- // src/lib/chat-manager.ts
130109
- var log9 = createLogger("chat-manager");
130110
- var PANEL_TYPE = "chat";
130111
- var chatSessions = /* @__PURE__ */ new Map();
130112
- var workspaceChats = /* @__PURE__ */ new Map();
130113
- var _initialized = false;
130114
- function ensureInitialized() {
130115
- if (_initialized) return;
130116
- _initialized = true;
130117
- loadChatsFromDb();
130341
+ // src/lib/dockview-layout-manager.ts
130342
+ function isLeaf(node) {
130343
+ return node.type === "leaf" && typeof node.data === "object" && !Array.isArray(node.data);
130118
130344
  }
130119
- function addToIndex(session) {
130120
- chatSessions.set(session.id, session);
130121
- let ids = workspaceChats.get(session.workspaceId);
130122
- if (!ids) {
130123
- ids = /* @__PURE__ */ new Set();
130124
- workspaceChats.set(session.workspaceId, ids);
130125
- }
130126
- ids.add(session.id);
130345
+ function isBranch(node) {
130346
+ return node.type === "branch" && Array.isArray(node.data);
130127
130347
  }
130128
- function removeFromIndex(chatId) {
130129
- const session = chatSessions.get(chatId);
130130
- if (!session) return;
130131
- chatSessions.delete(chatId);
130132
- const ids = workspaceChats.get(session.workspaceId);
130133
- if (ids) {
130134
- ids.delete(chatId);
130135
- if (ids.size === 0) {
130136
- workspaceChats.delete(session.workspaceId);
130348
+ function findFirstLeaf(node) {
130349
+ if (isLeaf(node)) return node.data;
130350
+ if (isBranch(node)) {
130351
+ for (const child of node.data) {
130352
+ const found = findFirstLeaf(child);
130353
+ if (found) return found;
130137
130354
  }
130138
130355
  }
130356
+ return null;
130139
130357
  }
130140
- function generateChatId() {
130141
- return `chat_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
130142
- }
130143
- function serializeState(session) {
130144
- const blob2 = {
130145
- name: session.name,
130146
- agent: session.agent,
130147
- model: session.model ?? null,
130148
- mode: session.mode ?? null,
130149
- activeSessionId: session.activeSessionId ?? null,
130150
- activeSessionSummary: session.activeSessionSummary ?? null,
130151
- activeSessionLastModified: session.activeSessionLastModified ?? null,
130152
- status: session.status
130153
- };
130154
- return JSON.stringify(blob2);
130155
- }
130156
- function createChat(workspaceId, options2) {
130157
- const settings = loadSettings();
130158
- const defaultAgent = getAgentDefinition(settings);
130159
- const now = Date.now();
130160
- const session = {
130161
- id: options2?.id ?? generateChatId(),
130162
- workspaceId,
130163
- name: options2?.name ?? "Chat",
130164
- agent: options2?.agent ?? defaultAgent.id,
130165
- model: options2?.model,
130166
- mode: options2?.mode,
130167
- status: "idle"
130168
- };
130169
- insertPanelState({
130170
- id: session.id,
130171
- workspaceId: session.workspaceId,
130172
- panelType: PANEL_TYPE,
130173
- state: serializeState(session),
130174
- createdAt: now,
130175
- updatedAt: now
130176
- });
130177
- addToIndex(session);
130178
- log9.info({ chatId: session.id, workspaceId, agent: session.agent }, "chat pane created");
130179
- return session;
130180
- }
130181
- function getChat(chatId) {
130182
- ensureInitialized();
130183
- return chatSessions.get(chatId);
130184
- }
130185
- function listChats(workspaceId) {
130186
- ensureInitialized();
130187
- const ids = workspaceChats.get(workspaceId);
130188
- if (!ids) return [];
130189
- const sessions = [];
130190
- for (const id of ids) {
130191
- const session = chatSessions.get(id);
130192
- if (session) sessions.push(session);
130358
+ function findLeafById(node, groupId) {
130359
+ if (isLeaf(node)) return node.data.id === groupId ? node.data : null;
130360
+ if (isBranch(node)) {
130361
+ for (const child of node.data) {
130362
+ const found = findLeafById(child, groupId);
130363
+ if (found) return found;
130364
+ }
130193
130365
  }
130194
- return sessions;
130195
- }
130196
- function updateChat(chatId, updates) {
130197
- const session = chatSessions.get(chatId);
130198
- if (!session) return void 0;
130199
- if (updates.name !== void 0) session.name = updates.name;
130200
- if (updates.agent !== void 0) session.agent = updates.agent;
130201
- if (updates.model !== void 0) session.model = updates.model ?? void 0;
130202
- if (updates.mode !== void 0) session.mode = updates.mode ?? void 0;
130203
- updatePanelState(chatId, {
130204
- state: serializeState(session),
130205
- updatedAt: Date.now()
130206
- });
130207
- log9.info({ chatId, updates }, "chat pane updated");
130208
- return session;
130209
- }
130210
- function updateChatStatus(chatId, status) {
130211
- const session = chatSessions.get(chatId);
130212
- if (!session) return;
130213
- session.status = status;
130214
- updatePanelState(chatId, {
130215
- state: serializeState(session),
130216
- updatedAt: Date.now()
130217
- });
130366
+ return null;
130218
130367
  }
130219
- function updateChatActiveSession(chatId, update) {
130220
- const session = chatSessions.get(chatId);
130221
- if (!session) return;
130222
- if (typeof update === "string" || update === void 0) {
130223
- session.activeSessionId = update;
130224
- session.activeSessionSummary = void 0;
130225
- session.activeSessionLastModified = void 0;
130226
- } else {
130227
- session.activeSessionId = update.activeSessionId;
130228
- session.activeSessionSummary = update.summary;
130229
- session.activeSessionLastModified = update.lastModified;
130368
+ function leafContainsView(node, panelId) {
130369
+ if (isLeaf(node)) return node.data.views.includes(panelId);
130370
+ if (isBranch(node)) {
130371
+ return node.data.some((child) => leafContainsView(child, panelId));
130230
130372
  }
130231
- updatePanelState(chatId, {
130232
- state: serializeState(session),
130233
- updatedAt: Date.now()
130234
- });
130373
+ return false;
130235
130374
  }
130236
- function updateChatSessionSummary(chatId, sessionId, summary, lastModified) {
130237
- const session = chatSessions.get(chatId);
130238
- if (!session) return false;
130239
- if (session.activeSessionId !== sessionId) return false;
130240
- if (session.activeSessionSummary === summary && session.activeSessionLastModified === lastModified) {
130241
- return false;
130375
+ function defaultPanelIdFromLayout(layout) {
130376
+ if (!layout || !isDockviewLayout(layout)) return null;
130377
+ if (layout.activeGroup) {
130378
+ const leaf = findLeafById(layout.grid.root, layout.activeGroup);
130379
+ if (leaf) {
130380
+ if (leaf.activeView && leaf.views.includes(leaf.activeView)) {
130381
+ return leaf.activeView;
130382
+ }
130383
+ if (leaf.views.length > 0) return leaf.views[0];
130384
+ }
130242
130385
  }
130243
- session.activeSessionSummary = summary;
130244
- session.activeSessionLastModified = lastModified;
130245
- updatePanelState(chatId, {
130246
- state: serializeState(session),
130247
- updatedAt: Date.now()
130248
- });
130249
- return true;
130250
- }
130251
- function removeChat(chatId) {
130252
- const session = chatSessions.get(chatId);
130253
- if (!session) return false;
130254
- removeAgent(chatId);
130255
- deletePanelState(chatId);
130256
- removeFromIndex(chatId);
130257
- log9.info({ chatId, workspaceId: session.workspaceId }, "chat pane removed");
130258
- return true;
130259
- }
130260
- function removeWorkspaceChats(workspaceId) {
130261
- const ids = workspaceChats.get(workspaceId);
130262
- if (!ids) return;
130263
- for (const chatId of [...ids]) {
130264
- removeAgent(chatId);
130265
- chatSessions.delete(chatId);
130386
+ const firstLeaf = findFirstLeaf(layout.grid.root);
130387
+ if (!firstLeaf) return null;
130388
+ if (firstLeaf.activeView && firstLeaf.views.includes(firstLeaf.activeView)) {
130389
+ return firstLeaf.activeView;
130266
130390
  }
130267
- deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE);
130268
- workspaceChats.delete(workspaceId);
130269
- log9.info({ workspaceId }, "all chat panes removed for workspace");
130391
+ return firstLeaf.views[0] ?? null;
130270
130392
  }
130271
- function loadChatsFromDb() {
130272
- _initialized = true;
130273
- const rows = listPanelStates(PANEL_TYPE);
130274
- const now = Date.now();
130275
- for (const row of rows) {
130276
- const parsed = JSON.parse(row.state);
130277
- parsed.status = "idle";
130278
- updatePanelState(row.id, {
130279
- state: JSON.stringify(parsed),
130280
- updatedAt: now
130281
- });
130282
- const session = {
130283
- id: row.id,
130284
- workspaceId: row.workspaceId,
130285
- name: parsed.name,
130286
- agent: parsed.agent,
130287
- model: parsed.model ?? void 0,
130288
- mode: parsed.mode ?? void 0,
130289
- activeSessionId: parsed.activeSessionId ?? void 0,
130290
- activeSessionSummary: parsed.activeSessionSummary ?? void 0,
130291
- activeSessionLastModified: parsed.activeSessionLastModified ?? void 0,
130292
- status: "idle"
130293
- };
130294
- addToIndex(session);
130295
- }
130296
- if (rows.length > 0) {
130297
- log9.info({ count: rows.length }, "loaded chat panes from database");
130393
+ function removeFromGrid(node, panelId) {
130394
+ if (isLeaf(node)) {
130395
+ const idx = node.data.views.indexOf(panelId);
130396
+ if (idx !== -1) {
130397
+ node.data.views.splice(idx, 1);
130398
+ if (node.data.activeView === panelId) {
130399
+ node.data.activeView = node.data.views[0];
130400
+ }
130401
+ }
130402
+ } else if (isBranch(node)) {
130403
+ for (const child of node.data) {
130404
+ removeFromGrid(child, panelId);
130405
+ }
130298
130406
  }
130299
- return rows.length;
130300
130407
  }
130301
- function getOrCreateDefaultChat(workspaceId) {
130302
- const chats = listChats(workspaceId);
130303
- if (chats.length > 0) return chats[0];
130304
- return createChat(workspaceId, { name: "Chat" });
130408
+ function isDockviewLayout(obj) {
130409
+ if (typeof obj !== "object" || obj === null) return false;
130410
+ const o2 = obj;
130411
+ return typeof o2.grid === "object" && typeof o2.panels === "object";
130305
130412
  }
130306
-
130307
- // src/lib/queued-message-store.ts
130308
- var QUEUED_KEY = Symbol.for("band.queued-messages");
130309
- var LISTENERS_KEY = Symbol.for("band.queued-messages.listeners");
130310
- var g10 = globalThis;
130311
- if (!g10[QUEUED_KEY]) g10[QUEUED_KEY] = /* @__PURE__ */ new Map();
130312
- if (!g10[LISTENERS_KEY]) g10[LISTENERS_KEY] = /* @__PURE__ */ new Set();
130313
- var store = g10[QUEUED_KEY];
130314
- var queueListeners = g10[LISTENERS_KEY];
130315
- function notify(chatId) {
130316
- const messages = [...store.get(chatId) ?? []];
130317
- for (const listener of queueListeners) {
130413
+ var DockviewLayoutManager = class {
130414
+ constructor(panelType) {
130415
+ this.panelType = panelType;
130416
+ }
130417
+ layoutId(workspaceId) {
130418
+ return `${this.panelType}_${workspaceId}`;
130419
+ }
130420
+ /**
130421
+ * Get the layout tree for a workspace.
130422
+ * Returns the parsed JSON tree or null if no layout is stored.
130423
+ */
130424
+ get(workspaceId) {
130425
+ const rows = listPanelStatesForWorkspace(workspaceId, this.panelType);
130426
+ if (rows.length === 0) return null;
130318
130427
  try {
130319
- listener(chatId, messages);
130428
+ return JSON.parse(rows[0].state);
130320
130429
  } catch {
130430
+ return null;
130431
+ }
130432
+ }
130433
+ /**
130434
+ * Save (upsert) the layout tree for a workspace.
130435
+ */
130436
+ save(workspaceId, tree) {
130437
+ const id = this.layoutId(workspaceId);
130438
+ const state2 = JSON.stringify(tree);
130439
+ const now = Date.now();
130440
+ const rows = listPanelStatesForWorkspace(workspaceId, this.panelType);
130441
+ if (rows.length > 0) {
130442
+ updatePanelState(id, { state: state2, updatedAt: now });
130443
+ } else {
130444
+ insertPanelState({
130445
+ id,
130446
+ workspaceId,
130447
+ panelType: this.panelType,
130448
+ state: state2,
130449
+ createdAt: now,
130450
+ updatedAt: now
130451
+ });
130452
+ }
130453
+ }
130454
+ /**
130455
+ * Delete the layout for a workspace.
130456
+ */
130457
+ delete(workspaceId) {
130458
+ deletePanelStatesForWorkspace(workspaceId, this.panelType);
130459
+ }
130460
+ /**
130461
+ * Add a panel to the saved dockview layout.
130462
+ *
130463
+ * Appends the panel to the first group's `views` array and adds the panel
130464
+ * entry to the `panels` map. If no layout exists, creates a fresh one-tab layout.
130465
+ */
130466
+ addPanel(workspaceId, panel) {
130467
+ const raw = this.get(workspaceId);
130468
+ if (raw && isDockviewLayout(raw)) {
130469
+ const alreadyInGrid = leafContainsView(raw.grid.root, panel.id);
130470
+ if (raw.panels[panel.id] && alreadyInGrid) {
130471
+ raw.panels[panel.id] = panel;
130472
+ this.save(workspaceId, raw);
130473
+ return;
130474
+ }
130475
+ raw.panels[panel.id] = panel;
130476
+ const leaf = findFirstLeaf(raw.grid.root);
130477
+ if (leaf && !leaf.views.includes(panel.id)) {
130478
+ leaf.views.push(panel.id);
130479
+ leaf.activeView = panel.id;
130480
+ }
130481
+ this.save(workspaceId, raw);
130482
+ } else {
130483
+ const groupId = `group_${panel.id}`;
130484
+ const width = 500;
130485
+ const height = 500;
130486
+ const layout = {
130487
+ grid: {
130488
+ root: {
130489
+ type: "branch",
130490
+ data: [
130491
+ {
130492
+ type: "leaf",
130493
+ data: { id: groupId, views: [panel.id], activeView: panel.id },
130494
+ size: width
130495
+ }
130496
+ ],
130497
+ size: height
130498
+ },
130499
+ height,
130500
+ width,
130501
+ orientation: "HORIZONTAL"
130502
+ },
130503
+ panels: { [panel.id]: panel },
130504
+ activeGroup: groupId
130505
+ };
130506
+ this.save(workspaceId, layout);
130321
130507
  }
130322
130508
  }
130509
+ /**
130510
+ * Remove a panel from the saved dockview layout.
130511
+ *
130512
+ * Removes the panel from the `panels` map and from any group's `views` array.
130513
+ */
130514
+ removePanel(workspaceId, panelId) {
130515
+ const raw = this.get(workspaceId);
130516
+ if (!raw || !isDockviewLayout(raw)) return;
130517
+ delete raw.panels[panelId];
130518
+ removeFromGrid(raw.grid.root, panelId);
130519
+ this.save(workspaceId, raw);
130520
+ }
130521
+ /**
130522
+ * List all panel IDs in the saved layout.
130523
+ * Useful for reconciling layout with live records.
130524
+ */
130525
+ listPanelIds(workspaceId) {
130526
+ const raw = this.get(workspaceId);
130527
+ if (!raw || !isDockviewLayout(raw)) return [];
130528
+ return Object.keys(raw.panels);
130529
+ }
130530
+ };
130531
+
130532
+ // src/lib/chat-layout-manager.ts
130533
+ var manager = new DockviewLayoutManager("chat_layout");
130534
+ var getChatLayout = (workspaceId) => manager.get(workspaceId);
130535
+ var saveChatLayout = (workspaceId, tree) => manager.save(workspaceId, tree);
130536
+ var deleteChatLayout = (workspaceId) => manager.delete(workspaceId);
130537
+ function addChatToLayout(workspaceId, chatId, opts) {
130538
+ manager.addPanel(workspaceId, {
130539
+ id: chatId,
130540
+ contentComponent: "chatTab",
130541
+ tabComponent: "chatTab",
130542
+ title: opts?.title ?? "Chat",
130543
+ params: {
130544
+ workspaceId,
130545
+ chatId
130546
+ }
130547
+ });
130323
130548
  }
130324
- function subscribeQueue(listener) {
130325
- queueListeners.add(listener);
130326
- return () => {
130327
- queueListeners.delete(listener);
130328
- };
130549
+ function removeChatFromLayout(workspaceId, chatId) {
130550
+ manager.removePanel(workspaceId, chatId);
130329
130551
  }
130330
- function pushQueuedMessage(chatId, text4) {
130331
- const msgs = store.get(chatId);
130332
- if (msgs) {
130333
- msgs.push(text4);
130334
- } else {
130335
- store.set(chatId, [text4]);
130552
+
130553
+ // src/lib/git.ts
130554
+ import { execFile as execFile2 } from "node:child_process";
130555
+ import { readFile, stat as stat3 } from "node:fs/promises";
130556
+ import { join as join13 } from "node:path";
130557
+ function parseGitRemoteUrl(url2) {
130558
+ const sshMatch = url2.match(/^[\w.-]+@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
130559
+ if (sshMatch) {
130560
+ return { host: sshMatch[1], owner: sshMatch[2], repo: sshMatch[3] };
130336
130561
  }
130337
- notify(chatId);
130562
+ const httpsMatch = url2.match(/^https?:\/\/([^/]+)\/([^/]+)\/(.+?)(?:\.git)?$/);
130563
+ if (httpsMatch) {
130564
+ return { host: httpsMatch[1], owner: httpsMatch[2], repo: httpsMatch[3] };
130565
+ }
130566
+ return null;
130338
130567
  }
130339
- function setQueuedMessages(chatId, texts) {
130340
- if (texts.length === 0) {
130341
- store.delete(chatId);
130342
- } else {
130343
- store.set(chatId, [...texts]);
130568
+ async function getRepoInfo(worktreePath) {
130569
+ try {
130570
+ const remoteUrl = (await execGit(["remote", "get-url", "origin"], worktreePath)).trim();
130571
+ const parsed = parseGitRemoteUrl(remoteUrl);
130572
+ if (!parsed) {
130573
+ console.error(`getRepoInfo: failed to parse remote URL "${remoteUrl}" for ${worktreePath}`);
130574
+ }
130575
+ return parsed;
130576
+ } catch (err) {
130577
+ console.error(
130578
+ `getRepoInfo: failed for ${worktreePath}:`,
130579
+ err instanceof Error ? err.message : err
130580
+ );
130581
+ return null;
130344
130582
  }
130345
- notify(chatId);
130346
130583
  }
130347
- function getQueuedMessages(chatId) {
130348
- return store.get(chatId) ?? [];
130584
+ function gitCmd() {
130585
+ const env = { ...process.env };
130586
+ if (env.PATH) {
130587
+ env.PATH = `/opt/homebrew/bin:/usr/local/bin:${env.PATH}`;
130588
+ }
130589
+ return { command: "git", env };
130349
130590
  }
130350
- function shiftQueuedMessage(chatId) {
130351
- const msgs = store.get(chatId);
130352
- if (!msgs || msgs.length === 0) return null;
130353
- const first = msgs.shift();
130354
- if (msgs.length === 0) store.delete(chatId);
130355
- notify(chatId);
130356
- return first;
130357
- }
130358
- function removeQueuedMessage(chatId, text4) {
130359
- const msgs = store.get(chatId);
130360
- if (!msgs) return false;
130361
- const idx = msgs.indexOf(text4);
130362
- if (idx === -1) return false;
130363
- msgs.splice(idx, 1);
130364
- if (msgs.length === 0) store.delete(chatId);
130365
- notify(chatId);
130366
- return true;
130367
- }
130368
- function clearQueuedMessages(chatId) {
130369
- store.delete(chatId);
130370
- notify(chatId);
130371
- }
130372
-
130373
- // src/lib/task-runner.ts
130374
- init_src();
130375
- import { mkdirSync as mkdirSync4, readdirSync as readdirSync6 } from "node:fs";
130376
- import { join as join15 } from "node:path";
130377
-
130378
- // src/lib/mime-types.ts
130379
- import { extname } from "node:path";
130380
- var MIME_TYPES = {
130381
- ".png": "image/png",
130382
- ".jpg": "image/jpeg",
130383
- ".jpeg": "image/jpeg",
130384
- ".gif": "image/gif",
130385
- ".webp": "image/webp",
130386
- ".svg": "image/svg+xml",
130387
- ".ico": "image/x-icon",
130388
- ".bmp": "image/bmp",
130389
- ".avif": "image/avif",
130390
- ".pdf": "application/pdf",
130391
- ".json": "application/json",
130392
- ".txt": "text/plain",
130393
- ".md": "text/markdown",
130394
- ".csv": "text/csv",
130395
- ".html": "text/html",
130396
- ".css": "text/css",
130397
- ".js": "application/javascript",
130398
- ".ts": "application/typescript",
130399
- ".xml": "application/xml",
130400
- ".yaml": "application/x-yaml",
130401
- ".yml": "application/x-yaml",
130402
- ".zip": "application/zip"
130403
- };
130404
- function mimeTypeFromFilename(filename) {
130405
- const ext = extname(filename).toLowerCase();
130406
- return MIME_TYPES[ext] || "application/octet-stream";
130407
- }
130408
-
130409
- // src/lib/pending-inputs.ts
130410
- var PENDING_KEY2 = Symbol.for("band.pending-inputs");
130411
- var g11 = globalThis;
130412
- if (!g11[PENDING_KEY2]) g11[PENDING_KEY2] = /* @__PURE__ */ new Map();
130413
- var pendingInputs = g11[PENDING_KEY2];
130414
- function createPendingInput(approvalId) {
130415
- return new Promise((resolve8, reject) => {
130416
- pendingInputs.set(approvalId, { resolve: resolve8, reject });
130417
- });
130418
- }
130419
- function resolvePendingInput(approvalId, answers) {
130420
- const pending2 = pendingInputs.get(approvalId);
130421
- if (!pending2) return false;
130422
- pendingInputs.delete(approvalId);
130423
- pending2.resolve(answers);
130424
- return true;
130425
- }
130426
- function rejectAllPendingInputs(error40) {
130427
- for (const [approvalId, pending2] of pendingInputs) {
130428
- pendingInputs.delete(approvalId);
130429
- pending2.reject(error40);
130430
- }
130431
- }
130432
-
130433
- // src/lib/task-store.ts
130434
- init_src();
130435
- var log10 = createLogger("task-store");
130436
- function generateTaskId() {
130437
- return `tsk_${Date.now()}`;
130438
- }
130439
- function saveTask(task) {
130440
- const db2 = getDb();
130441
- db2.insert(tasks).values({
130442
- id: task.id,
130443
- workspaceId: task.workspaceId,
130444
- project: task.project,
130445
- branch: task.branch,
130446
- prompt: task.prompt,
130447
- status: task.status,
130448
- sessionId: task.sessionId ?? null,
130449
- startedAt: task.startedAt,
130450
- completedAt: task.completedAt ?? null,
130451
- maxTurns: task.maxTurns ?? null,
130452
- mode: task.mode ?? null,
130453
- model: task.model ?? null,
130454
- codingAgentId: task.codingAgentId ?? null,
130455
- chatId: task.chatId ?? null
130456
- }).onConflictDoUpdate({
130457
- target: tasks.id,
130458
- set: {
130459
- workspaceId: task.workspaceId,
130460
- project: task.project,
130461
- branch: task.branch,
130462
- prompt: task.prompt,
130463
- status: task.status,
130464
- sessionId: task.sessionId ?? null,
130465
- startedAt: task.startedAt,
130466
- completedAt: task.completedAt ?? null,
130467
- maxTurns: task.maxTurns ?? null,
130468
- mode: task.mode ?? null,
130469
- model: task.model ?? null,
130470
- codingAgentId: task.codingAgentId ?? null,
130471
- chatId: task.chatId ?? null
130472
- }
130473
- }).run();
130474
- }
130475
- function loadTask(id) {
130476
- const db2 = getDb();
130477
- const row = db2.select().from(tasks).where(eq2(tasks.id, id)).get();
130478
- if (!row) return null;
130479
- return rowToRecord(row);
130480
- }
130481
- function listTasks(filters) {
130482
- const db2 = getDb();
130483
- const conditions = [];
130484
- if (filters?.project) {
130485
- conditions.push(eq2(tasks.project, filters.project));
130486
- }
130487
- if (filters?.workspaceId) {
130488
- conditions.push(eq2(tasks.workspaceId, filters.workspaceId));
130489
- }
130490
- if (filters?.status) {
130491
- conditions.push(eq2(tasks.status, filters.status));
130492
- }
130493
- if (filters?.sessionId) {
130494
- conditions.push(eq2(tasks.sessionId, filters.sessionId));
130495
- }
130496
- if (filters?.chatId) {
130497
- conditions.push(eq2(tasks.chatId, filters.chatId));
130498
- }
130499
- const query = conditions.length > 0 ? db2.select().from(tasks).where(and(...conditions)).orderBy(desc(tasks.startedAt)) : db2.select().from(tasks).orderBy(desc(tasks.startedAt));
130500
- return query.all().map(rowToRecord);
130501
- }
130502
- function cleanupStaleTasks() {
130503
- const db2 = getDb();
130504
- const now = Date.now();
130505
- const result = db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.status, "running")).run();
130506
- const count3 = result.changes;
130507
- if (count3 > 0) {
130508
- log10.info({ count: count3 }, "cleaned up stale tasks on startup");
130509
- }
130510
- return count3;
130511
- }
130512
- function markTaskFailed(id) {
130513
- const task = loadTask(id);
130514
- if (!task || task.status !== "running") return null;
130515
- const now = Date.now();
130516
- const db2 = getDb();
130517
- db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.id, id)).run();
130518
- task.status = "failed";
130519
- task.completedAt = now;
130520
- return task;
130521
- }
130522
- function rowToRecord(row) {
130523
- return {
130524
- id: row.id,
130525
- workspaceId: row.workspaceId,
130526
- project: row.project,
130527
- branch: row.branch,
130528
- prompt: row.prompt,
130529
- status: row.status,
130530
- sessionId: row.sessionId ?? void 0,
130531
- startedAt: row.startedAt,
130532
- completedAt: row.completedAt ?? void 0,
130533
- maxTurns: row.maxTurns ?? void 0,
130534
- mode: row.mode ?? void 0,
130535
- model: row.model ?? void 0,
130536
- codingAgentId: row.codingAgentId ?? void 0,
130537
- chatId: row.chatId ?? void 0
130538
- };
130539
- }
130540
-
130541
- // src/lib/git.ts
130542
- import { execFile as execFile2 } from "node:child_process";
130543
- import { readFile, stat as stat3 } from "node:fs/promises";
130544
- import { join as join13 } from "node:path";
130545
- function parseGitRemoteUrl(url2) {
130546
- const sshMatch = url2.match(/^[\w.-]+@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
130547
- if (sshMatch) {
130548
- return { host: sshMatch[1], owner: sshMatch[2], repo: sshMatch[3] };
130549
- }
130550
- const httpsMatch = url2.match(/^https?:\/\/([^/]+)\/([^/]+)\/(.+?)(?:\.git)?$/);
130551
- if (httpsMatch) {
130552
- return { host: httpsMatch[1], owner: httpsMatch[2], repo: httpsMatch[3] };
130553
- }
130554
- return null;
130555
- }
130556
- async function getRepoInfo(worktreePath) {
130557
- try {
130558
- const remoteUrl = (await execGit(["remote", "get-url", "origin"], worktreePath)).trim();
130559
- const parsed = parseGitRemoteUrl(remoteUrl);
130560
- if (!parsed) {
130561
- console.error(`getRepoInfo: failed to parse remote URL "${remoteUrl}" for ${worktreePath}`);
130562
- }
130563
- return parsed;
130564
- } catch (err) {
130565
- console.error(
130566
- `getRepoInfo: failed for ${worktreePath}:`,
130567
- err instanceof Error ? err.message : err
130568
- );
130569
- return null;
130570
- }
130571
- }
130572
- function gitCmd() {
130573
- const env = { ...process.env };
130574
- if (env.PATH) {
130575
- env.PATH = `/opt/homebrew/bin:/usr/local/bin:${env.PATH}`;
130576
- }
130577
- return { command: "git", env };
130578
- }
130579
- var MAX_BUFFER = 50 * 1024 * 1024;
130580
- function execGit(args, cwd) {
130581
- const { command, env } = gitCmd();
130582
- return new Promise((resolve8, reject) => {
130583
- execFile2(command, args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
130584
- if (err) {
130585
- reject(new Error(stderr || err.message));
130586
- return;
130587
- }
130588
- resolve8(stdout);
130589
- });
130590
- });
130591
+ var MAX_BUFFER = 50 * 1024 * 1024;
130592
+ function execGit(args, cwd) {
130593
+ const { command, env } = gitCmd();
130594
+ return new Promise((resolve8, reject) => {
130595
+ execFile2(command, args, { cwd, env, maxBuffer: MAX_BUFFER }, (err, stdout, stderr) => {
130596
+ if (err) {
130597
+ reject(new Error(stderr || err.message));
130598
+ return;
130599
+ }
130600
+ resolve8(stdout);
130601
+ });
130602
+ });
130591
130603
  }
130592
130604
  function execGh(args, cwd) {
130593
130605
  const env = { ...process.env };
@@ -131207,6 +131219,451 @@ function subscribe(listener) {
131207
131219
  };
131208
131220
  }
131209
131221
 
131222
+ // src/lib/chat-manager.ts
131223
+ var log9 = createLogger("chat-manager");
131224
+ var PANEL_TYPE = "chat";
131225
+ var chatSessions = /* @__PURE__ */ new Map();
131226
+ var workspaceChats = /* @__PURE__ */ new Map();
131227
+ var _initialized = false;
131228
+ function ensureInitialized() {
131229
+ if (_initialized) return;
131230
+ _initialized = true;
131231
+ loadChatsFromDb();
131232
+ }
131233
+ function addToIndex(session) {
131234
+ chatSessions.set(session.id, session);
131235
+ let ids = workspaceChats.get(session.workspaceId);
131236
+ if (!ids) {
131237
+ ids = /* @__PURE__ */ new Set();
131238
+ workspaceChats.set(session.workspaceId, ids);
131239
+ }
131240
+ ids.add(session.id);
131241
+ }
131242
+ function removeFromIndex(chatId) {
131243
+ const session = chatSessions.get(chatId);
131244
+ if (!session) return;
131245
+ chatSessions.delete(chatId);
131246
+ const ids = workspaceChats.get(session.workspaceId);
131247
+ if (ids) {
131248
+ ids.delete(chatId);
131249
+ if (ids.size === 0) {
131250
+ workspaceChats.delete(session.workspaceId);
131251
+ }
131252
+ }
131253
+ }
131254
+ function generateChatId() {
131255
+ return `chat_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
131256
+ }
131257
+ function serializeState(session) {
131258
+ const blob2 = {
131259
+ name: session.name,
131260
+ agent: session.agent,
131261
+ model: session.model ?? null,
131262
+ mode: session.mode ?? null,
131263
+ activeSessionId: session.activeSessionId ?? null,
131264
+ activeSessionSummary: session.activeSessionSummary ?? null,
131265
+ activeSessionLastModified: session.activeSessionLastModified ?? null,
131266
+ status: session.status
131267
+ };
131268
+ return JSON.stringify(blob2);
131269
+ }
131270
+ function createChat(workspaceId, options2) {
131271
+ const settings = loadSettings();
131272
+ const defaultAgent = getAgentDefinition(settings);
131273
+ const now = Date.now();
131274
+ const session = {
131275
+ id: options2?.id ?? generateChatId(),
131276
+ workspaceId,
131277
+ name: options2?.name ?? "Chat",
131278
+ agent: options2?.agent ?? defaultAgent.id,
131279
+ model: options2?.model,
131280
+ mode: options2?.mode,
131281
+ status: "idle"
131282
+ };
131283
+ insertPanelState({
131284
+ id: session.id,
131285
+ workspaceId: session.workspaceId,
131286
+ panelType: PANEL_TYPE,
131287
+ state: serializeState(session),
131288
+ createdAt: now,
131289
+ updatedAt: now
131290
+ });
131291
+ addToIndex(session);
131292
+ addChatToLayout(workspaceId, session.id, { title: session.name });
131293
+ emit({ kind: "chat-created", workspaceId, chatId: session.id });
131294
+ log9.info({ chatId: session.id, workspaceId, agent: session.agent }, "chat pane created");
131295
+ return session;
131296
+ }
131297
+ function getChat(chatId) {
131298
+ ensureInitialized();
131299
+ return chatSessions.get(chatId);
131300
+ }
131301
+ function listChats(workspaceId) {
131302
+ ensureInitialized();
131303
+ const ids = workspaceChats.get(workspaceId);
131304
+ if (!ids) return [];
131305
+ const sessions = [];
131306
+ for (const id of ids) {
131307
+ const session = chatSessions.get(id);
131308
+ if (session) sessions.push(session);
131309
+ }
131310
+ return sessions;
131311
+ }
131312
+ function updateChat(chatId, updates) {
131313
+ const session = chatSessions.get(chatId);
131314
+ if (!session) return void 0;
131315
+ if (updates.name !== void 0) session.name = updates.name;
131316
+ if (updates.agent !== void 0) session.agent = updates.agent;
131317
+ if (updates.model !== void 0) session.model = updates.model ?? void 0;
131318
+ if (updates.mode !== void 0) session.mode = updates.mode ?? void 0;
131319
+ updatePanelState(chatId, {
131320
+ state: serializeState(session),
131321
+ updatedAt: Date.now()
131322
+ });
131323
+ log9.info({ chatId, updates }, "chat pane updated");
131324
+ return session;
131325
+ }
131326
+ function updateChatStatus(chatId, status) {
131327
+ const session = chatSessions.get(chatId);
131328
+ if (!session) return;
131329
+ session.status = status;
131330
+ updatePanelState(chatId, {
131331
+ state: serializeState(session),
131332
+ updatedAt: Date.now()
131333
+ });
131334
+ }
131335
+ function updateChatActiveSession(chatId, update) {
131336
+ const session = chatSessions.get(chatId);
131337
+ if (!session) return;
131338
+ if (typeof update === "string" || update === void 0) {
131339
+ session.activeSessionId = update;
131340
+ session.activeSessionSummary = void 0;
131341
+ session.activeSessionLastModified = void 0;
131342
+ } else {
131343
+ session.activeSessionId = update.activeSessionId;
131344
+ session.activeSessionSummary = update.summary;
131345
+ session.activeSessionLastModified = update.lastModified;
131346
+ }
131347
+ updatePanelState(chatId, {
131348
+ state: serializeState(session),
131349
+ updatedAt: Date.now()
131350
+ });
131351
+ }
131352
+ function updateChatSessionSummary(chatId, sessionId, summary, lastModified) {
131353
+ const session = chatSessions.get(chatId);
131354
+ if (!session) return false;
131355
+ if (session.activeSessionId !== sessionId) return false;
131356
+ if (session.activeSessionSummary === summary && session.activeSessionLastModified === lastModified) {
131357
+ return false;
131358
+ }
131359
+ session.activeSessionSummary = summary;
131360
+ session.activeSessionLastModified = lastModified;
131361
+ updatePanelState(chatId, {
131362
+ state: serializeState(session),
131363
+ updatedAt: Date.now()
131364
+ });
131365
+ return true;
131366
+ }
131367
+ function removeChat(chatId) {
131368
+ const session = chatSessions.get(chatId);
131369
+ if (!session) return false;
131370
+ removeAgent(chatId);
131371
+ deletePanelState(chatId);
131372
+ removeChatFromLayout(session.workspaceId, chatId);
131373
+ removeFromIndex(chatId);
131374
+ emit({ kind: "chat-removed", workspaceId: session.workspaceId, chatId });
131375
+ log9.info({ chatId, workspaceId: session.workspaceId }, "chat pane removed");
131376
+ return true;
131377
+ }
131378
+ function removeWorkspaceChats(workspaceId) {
131379
+ const ids = workspaceChats.get(workspaceId);
131380
+ if (!ids) return;
131381
+ for (const chatId of [...ids]) {
131382
+ removeAgent(chatId);
131383
+ chatSessions.delete(chatId);
131384
+ }
131385
+ deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE);
131386
+ workspaceChats.delete(workspaceId);
131387
+ log9.info({ workspaceId }, "all chat panes removed for workspace");
131388
+ }
131389
+ function loadChatsFromDb() {
131390
+ _initialized = true;
131391
+ const rows = listPanelStates(PANEL_TYPE);
131392
+ const now = Date.now();
131393
+ for (const row of rows) {
131394
+ const parsed = JSON.parse(row.state);
131395
+ parsed.status = "idle";
131396
+ updatePanelState(row.id, {
131397
+ state: JSON.stringify(parsed),
131398
+ updatedAt: now
131399
+ });
131400
+ const session = {
131401
+ id: row.id,
131402
+ workspaceId: row.workspaceId,
131403
+ name: parsed.name,
131404
+ agent: parsed.agent,
131405
+ model: parsed.model ?? void 0,
131406
+ mode: parsed.mode ?? void 0,
131407
+ activeSessionId: parsed.activeSessionId ?? void 0,
131408
+ activeSessionSummary: parsed.activeSessionSummary ?? void 0,
131409
+ activeSessionLastModified: parsed.activeSessionLastModified ?? void 0,
131410
+ status: "idle"
131411
+ };
131412
+ addToIndex(session);
131413
+ }
131414
+ if (rows.length > 0) {
131415
+ log9.info({ count: rows.length }, "loaded chat panes from database");
131416
+ }
131417
+ return rows.length;
131418
+ }
131419
+ function getOrCreateDefaultChat(workspaceId) {
131420
+ const chats = listChats(workspaceId);
131421
+ if (chats.length > 0) {
131422
+ const layout = getChatLayout(workspaceId);
131423
+ const layoutDefault = defaultPanelIdFromLayout(layout);
131424
+ if (layoutDefault) {
131425
+ const match = chats.find((c2) => c2.id === layoutDefault);
131426
+ if (match) return match;
131427
+ }
131428
+ return chats[0];
131429
+ }
131430
+ return createChat(workspaceId, { name: "Chat" });
131431
+ }
131432
+
131433
+ // src/lib/queued-message-store.ts
131434
+ var QUEUED_KEY = Symbol.for("band.queued-messages");
131435
+ var LISTENERS_KEY = Symbol.for("band.queued-messages.listeners");
131436
+ var g10 = globalThis;
131437
+ if (!g10[QUEUED_KEY]) g10[QUEUED_KEY] = /* @__PURE__ */ new Map();
131438
+ if (!g10[LISTENERS_KEY]) g10[LISTENERS_KEY] = /* @__PURE__ */ new Set();
131439
+ var store = g10[QUEUED_KEY];
131440
+ var queueListeners = g10[LISTENERS_KEY];
131441
+ function notify(chatId) {
131442
+ const messages = [...store.get(chatId) ?? []];
131443
+ for (const listener of queueListeners) {
131444
+ try {
131445
+ listener(chatId, messages);
131446
+ } catch {
131447
+ }
131448
+ }
131449
+ }
131450
+ function subscribeQueue(listener) {
131451
+ queueListeners.add(listener);
131452
+ return () => {
131453
+ queueListeners.delete(listener);
131454
+ };
131455
+ }
131456
+ function pushQueuedMessage(chatId, text4) {
131457
+ const msgs = store.get(chatId);
131458
+ if (msgs) {
131459
+ msgs.push(text4);
131460
+ } else {
131461
+ store.set(chatId, [text4]);
131462
+ }
131463
+ notify(chatId);
131464
+ }
131465
+ function setQueuedMessages(chatId, texts) {
131466
+ if (texts.length === 0) {
131467
+ store.delete(chatId);
131468
+ } else {
131469
+ store.set(chatId, [...texts]);
131470
+ }
131471
+ notify(chatId);
131472
+ }
131473
+ function getQueuedMessages(chatId) {
131474
+ return store.get(chatId) ?? [];
131475
+ }
131476
+ function shiftQueuedMessage(chatId) {
131477
+ const msgs = store.get(chatId);
131478
+ if (!msgs || msgs.length === 0) return null;
131479
+ const first = msgs.shift();
131480
+ if (msgs.length === 0) store.delete(chatId);
131481
+ notify(chatId);
131482
+ return first;
131483
+ }
131484
+ function removeQueuedMessage(chatId, text4) {
131485
+ const msgs = store.get(chatId);
131486
+ if (!msgs) return false;
131487
+ const idx = msgs.indexOf(text4);
131488
+ if (idx === -1) return false;
131489
+ msgs.splice(idx, 1);
131490
+ if (msgs.length === 0) store.delete(chatId);
131491
+ notify(chatId);
131492
+ return true;
131493
+ }
131494
+ function clearQueuedMessages(chatId) {
131495
+ store.delete(chatId);
131496
+ notify(chatId);
131497
+ }
131498
+
131499
+ // src/lib/task-runner.ts
131500
+ init_src();
131501
+ import { mkdirSync as mkdirSync4, readdirSync as readdirSync6 } from "node:fs";
131502
+ import { join as join15 } from "node:path";
131503
+
131504
+ // src/lib/mime-types.ts
131505
+ import { extname } from "node:path";
131506
+ var MIME_TYPES = {
131507
+ ".png": "image/png",
131508
+ ".jpg": "image/jpeg",
131509
+ ".jpeg": "image/jpeg",
131510
+ ".gif": "image/gif",
131511
+ ".webp": "image/webp",
131512
+ ".svg": "image/svg+xml",
131513
+ ".ico": "image/x-icon",
131514
+ ".bmp": "image/bmp",
131515
+ ".avif": "image/avif",
131516
+ ".pdf": "application/pdf",
131517
+ ".json": "application/json",
131518
+ ".txt": "text/plain",
131519
+ ".md": "text/markdown",
131520
+ ".csv": "text/csv",
131521
+ ".html": "text/html",
131522
+ ".css": "text/css",
131523
+ ".js": "application/javascript",
131524
+ ".ts": "application/typescript",
131525
+ ".xml": "application/xml",
131526
+ ".yaml": "application/x-yaml",
131527
+ ".yml": "application/x-yaml",
131528
+ ".zip": "application/zip"
131529
+ };
131530
+ function mimeTypeFromFilename(filename) {
131531
+ const ext = extname(filename).toLowerCase();
131532
+ return MIME_TYPES[ext] || "application/octet-stream";
131533
+ }
131534
+
131535
+ // src/lib/pending-inputs.ts
131536
+ var PENDING_KEY2 = Symbol.for("band.pending-inputs");
131537
+ var g11 = globalThis;
131538
+ if (!g11[PENDING_KEY2]) g11[PENDING_KEY2] = /* @__PURE__ */ new Map();
131539
+ var pendingInputs = g11[PENDING_KEY2];
131540
+ function createPendingInput(approvalId) {
131541
+ return new Promise((resolve8, reject) => {
131542
+ pendingInputs.set(approvalId, { resolve: resolve8, reject });
131543
+ });
131544
+ }
131545
+ function resolvePendingInput(approvalId, answers) {
131546
+ const pending2 = pendingInputs.get(approvalId);
131547
+ if (!pending2) return false;
131548
+ pendingInputs.delete(approvalId);
131549
+ pending2.resolve(answers);
131550
+ return true;
131551
+ }
131552
+ function rejectAllPendingInputs(error40) {
131553
+ for (const [approvalId, pending2] of pendingInputs) {
131554
+ pendingInputs.delete(approvalId);
131555
+ pending2.reject(error40);
131556
+ }
131557
+ }
131558
+
131559
+ // src/lib/task-store.ts
131560
+ init_src();
131561
+ var log10 = createLogger("task-store");
131562
+ function generateTaskId() {
131563
+ return `tsk_${Date.now()}`;
131564
+ }
131565
+ function saveTask(task) {
131566
+ const db2 = getDb();
131567
+ db2.insert(tasks).values({
131568
+ id: task.id,
131569
+ workspaceId: task.workspaceId,
131570
+ project: task.project,
131571
+ branch: task.branch,
131572
+ prompt: task.prompt,
131573
+ status: task.status,
131574
+ sessionId: task.sessionId ?? null,
131575
+ startedAt: task.startedAt,
131576
+ completedAt: task.completedAt ?? null,
131577
+ maxTurns: task.maxTurns ?? null,
131578
+ mode: task.mode ?? null,
131579
+ model: task.model ?? null,
131580
+ codingAgentId: task.codingAgentId ?? null,
131581
+ chatId: task.chatId ?? null
131582
+ }).onConflictDoUpdate({
131583
+ target: tasks.id,
131584
+ set: {
131585
+ workspaceId: task.workspaceId,
131586
+ project: task.project,
131587
+ branch: task.branch,
131588
+ prompt: task.prompt,
131589
+ status: task.status,
131590
+ sessionId: task.sessionId ?? null,
131591
+ startedAt: task.startedAt,
131592
+ completedAt: task.completedAt ?? null,
131593
+ maxTurns: task.maxTurns ?? null,
131594
+ mode: task.mode ?? null,
131595
+ model: task.model ?? null,
131596
+ codingAgentId: task.codingAgentId ?? null,
131597
+ chatId: task.chatId ?? null
131598
+ }
131599
+ }).run();
131600
+ }
131601
+ function loadTask(id) {
131602
+ const db2 = getDb();
131603
+ const row = db2.select().from(tasks).where(eq2(tasks.id, id)).get();
131604
+ if (!row) return null;
131605
+ return rowToRecord(row);
131606
+ }
131607
+ function listTasks(filters) {
131608
+ const db2 = getDb();
131609
+ const conditions = [];
131610
+ if (filters?.project) {
131611
+ conditions.push(eq2(tasks.project, filters.project));
131612
+ }
131613
+ if (filters?.workspaceId) {
131614
+ conditions.push(eq2(tasks.workspaceId, filters.workspaceId));
131615
+ }
131616
+ if (filters?.status) {
131617
+ conditions.push(eq2(tasks.status, filters.status));
131618
+ }
131619
+ if (filters?.sessionId) {
131620
+ conditions.push(eq2(tasks.sessionId, filters.sessionId));
131621
+ }
131622
+ if (filters?.chatId) {
131623
+ conditions.push(eq2(tasks.chatId, filters.chatId));
131624
+ }
131625
+ const query = conditions.length > 0 ? db2.select().from(tasks).where(and(...conditions)).orderBy(desc(tasks.startedAt)) : db2.select().from(tasks).orderBy(desc(tasks.startedAt));
131626
+ return query.all().map(rowToRecord);
131627
+ }
131628
+ function cleanupStaleTasks() {
131629
+ const db2 = getDb();
131630
+ const now = Date.now();
131631
+ const result = db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.status, "running")).run();
131632
+ const count3 = result.changes;
131633
+ if (count3 > 0) {
131634
+ log10.info({ count: count3 }, "cleaned up stale tasks on startup");
131635
+ }
131636
+ return count3;
131637
+ }
131638
+ function markTaskFailed(id) {
131639
+ const task = loadTask(id);
131640
+ if (!task || task.status !== "running") return null;
131641
+ const now = Date.now();
131642
+ const db2 = getDb();
131643
+ db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.id, id)).run();
131644
+ task.status = "failed";
131645
+ task.completedAt = now;
131646
+ return task;
131647
+ }
131648
+ function rowToRecord(row) {
131649
+ return {
131650
+ id: row.id,
131651
+ workspaceId: row.workspaceId,
131652
+ project: row.project,
131653
+ branch: row.branch,
131654
+ prompt: row.prompt,
131655
+ status: row.status,
131656
+ sessionId: row.sessionId ?? void 0,
131657
+ startedAt: row.startedAt,
131658
+ completedAt: row.completedAt ?? void 0,
131659
+ maxTurns: row.maxTurns ?? void 0,
131660
+ mode: row.mode ?? void 0,
131661
+ model: row.model ?? void 0,
131662
+ codingAgentId: row.codingAgentId ?? void 0,
131663
+ chatId: row.chatId ?? void 0
131664
+ };
131665
+ }
131666
+
131210
131667
  // src/lib/workspace.ts
131211
131668
  function resolveWorkspace(workspaceId) {
131212
131669
  const state2 = loadState();
@@ -131240,13 +131697,26 @@ var MAX_BUFFER_SIZE = 2e3;
131240
131697
  var TASKS_KEY = Symbol.for("band.task-runner.tasks");
131241
131698
  var LISTENERS_KEY2 = Symbol.for("band.task-runner.listeners");
131242
131699
  var BUFFERS_KEY = Symbol.for("band.task-runner.sessionBuffers");
131700
+ var USAGE_KEY = Symbol.for("band.task-runner.sessionUsage");
131243
131701
  var g12 = globalThis;
131244
131702
  if (!g12[TASKS_KEY]) g12[TASKS_KEY] = /* @__PURE__ */ new Map();
131245
131703
  if (!g12[LISTENERS_KEY2]) g12[LISTENERS_KEY2] = /* @__PURE__ */ new Map();
131246
131704
  if (!g12[BUFFERS_KEY]) g12[BUFFERS_KEY] = /* @__PURE__ */ new Map();
131705
+ if (!g12[USAGE_KEY]) g12[USAGE_KEY] = /* @__PURE__ */ new Map();
131247
131706
  var tasks2 = g12[TASKS_KEY];
131248
131707
  var listeners2 = g12[LISTENERS_KEY2];
131249
131708
  var sessionBuffers = g12[BUFFERS_KEY];
131709
+ var sessionUsage = g12[USAGE_KEY];
131710
+ var MAX_SESSION_USAGE = 1e3;
131711
+ function lruSet3(map2, key, value, cap) {
131712
+ if (map2.has(key)) map2.delete(key);
131713
+ map2.set(key, value);
131714
+ while (map2.size > cap) {
131715
+ const oldest = map2.keys().next().value;
131716
+ if (oldest === void 0) break;
131717
+ map2.delete(oldest);
131718
+ }
131719
+ }
131250
131720
  function persistTask(task) {
131251
131721
  const workspace = resolveWorkspace(task.workspaceId);
131252
131722
  try {
@@ -131560,6 +132030,57 @@ async function runTask(chatId, task) {
131560
132030
  });
131561
132031
  break;
131562
132032
  }
132033
+ case "usage": {
132034
+ if (task.sessionId) {
132035
+ const prev = sessionUsage.get(task.sessionId);
132036
+ const shouldStore = prev?.totalProcessedTokens !== void 0 && event.totalProcessedTokens !== void 0 ? event.totalProcessedTokens >= prev.totalProcessedTokens : usageContextSize(event) >= usageContextSize(prev);
132037
+ if (shouldStore) {
132038
+ lruSet3(
132039
+ sessionUsage,
132040
+ task.sessionId,
132041
+ {
132042
+ provider: event.provider,
132043
+ inputTokens: event.inputTokens,
132044
+ outputTokens: event.outputTokens,
132045
+ cacheReadTokens: event.cacheReadTokens,
132046
+ cacheCreationTokens: event.cacheCreationTokens,
132047
+ reasoningOutputTokens: event.reasoningOutputTokens,
132048
+ contextTokens: event.contextTokens,
132049
+ totalProcessedTokens: event.totalProcessedTokens,
132050
+ maxContextTokens: event.maxContextTokens
132051
+ },
132052
+ MAX_SESSION_USAGE
132053
+ );
132054
+ }
132055
+ }
132056
+ broadcast(chatId, {
132057
+ type: "data-usage",
132058
+ data: {
132059
+ inputTokens: event.inputTokens,
132060
+ outputTokens: event.outputTokens,
132061
+ ...event.provider !== void 0 && { provider: event.provider },
132062
+ ...event.cacheReadTokens !== void 0 && {
132063
+ cacheReadTokens: event.cacheReadTokens
132064
+ },
132065
+ ...event.cacheCreationTokens !== void 0 && {
132066
+ cacheCreationTokens: event.cacheCreationTokens
132067
+ },
132068
+ ...event.reasoningOutputTokens !== void 0 && {
132069
+ reasoningOutputTokens: event.reasoningOutputTokens
132070
+ },
132071
+ ...event.contextTokens !== void 0 && {
132072
+ contextTokens: event.contextTokens
132073
+ },
132074
+ ...event.totalProcessedTokens !== void 0 && {
132075
+ totalProcessedTokens: event.totalProcessedTokens
132076
+ },
132077
+ ...event.maxContextTokens !== void 0 && {
132078
+ maxContextTokens: event.maxContextTokens
132079
+ }
132080
+ }
132081
+ });
132082
+ break;
132083
+ }
131563
132084
  case "session-result": {
131564
132085
  endText();
131565
132086
  if (event.success) {
@@ -131603,6 +132124,11 @@ async function runTask(chatId, task) {
131603
132124
  sessionBuffers.set(event.resolvedSessionId, oldBuf);
131604
132125
  sessionBuffers.delete(event.previousSessionId);
131605
132126
  }
132127
+ const oldUsage = sessionUsage.get(event.previousSessionId);
132128
+ if (oldUsage) {
132129
+ lruSet3(sessionUsage, event.resolvedSessionId, oldUsage, MAX_SESSION_USAGE);
132130
+ sessionUsage.delete(event.previousSessionId);
132131
+ }
131606
132132
  if (task.sessionId === event.previousSessionId) {
131607
132133
  task.sessionId = event.resolvedSessionId;
131608
132134
  persistTask(task);
@@ -131682,6 +132208,18 @@ function getTask(chatId) {
131682
132208
  function getSessionBuffer(sessionId) {
131683
132209
  return sessionBuffers.get(sessionId);
131684
132210
  }
132211
+ function usageContextSize(usage) {
132212
+ if (!usage) return 0;
132213
+ if (usage.contextTokens !== void 0) return usage.contextTokens;
132214
+ const isClaude = usage.provider === "claude" || usage.cacheCreationTokens !== void 0;
132215
+ if (isClaude) {
132216
+ return usage.inputTokens + (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0) + (usage.reasoningOutputTokens ?? 0);
132217
+ }
132218
+ return usage.inputTokens + (usage.reasoningOutputTokens ?? 0);
132219
+ }
132220
+ function getSessionUsage(sessionId) {
132221
+ return sessionUsage.get(sessionId);
132222
+ }
131685
132223
  function subscribe2(chatId, listener) {
131686
132224
  let subs = listeners2.get(chatId);
131687
132225
  if (!subs) {
@@ -131897,7 +132435,7 @@ async function handlePost(req, res, chatId) {
131897
132435
  return;
131898
132436
  }
131899
132437
  const { workspaceId, prompt, sessionId, maxTurns, mode, model, codingAgentId, files } = body;
131900
- if (!workspaceId || !prompt) {
132438
+ if (!workspaceId || !prompt?.trim()) {
131901
132439
  res.writeHead(400, { "Content-Type": "application/json" });
131902
132440
  res.end(JSON.stringify({ error: "workspaceId and prompt are required" }));
131903
132441
  return;
@@ -133400,6 +133938,32 @@ async function ensureClaudeHooks() {
133400
133938
  init_src();
133401
133939
  import { existsSync as existsSync5 } from "node:fs";
133402
133940
  import { join as join20 } from "node:path";
133941
+
133942
+ // src/lib/terminal-layout-manager.ts
133943
+ var manager2 = new DockviewLayoutManager("terminal_layout");
133944
+ var getTerminalLayout = (workspaceId) => manager2.get(workspaceId);
133945
+ var saveTerminalLayout = (workspaceId, tree) => manager2.save(workspaceId, tree);
133946
+ var deleteTerminalLayout = (workspaceId) => manager2.delete(workspaceId);
133947
+ function addTerminalToLayout(workspaceId, terminalId, opts) {
133948
+ manager2.addPanel(workspaceId, {
133949
+ id: terminalId,
133950
+ contentComponent: "terminalTab",
133951
+ tabComponent: "terminalTab",
133952
+ title: opts?.title ?? "Terminal",
133953
+ params: {
133954
+ workspaceId,
133955
+ terminalId,
133956
+ ...opts?.command ? { command: opts.command } : {},
133957
+ ...opts?.cwd ? { cwd: opts.cwd } : {},
133958
+ ...opts?.env ? { env: opts.env } : {}
133959
+ }
133960
+ });
133961
+ }
133962
+ function removeTerminalFromLayout(workspaceId, terminalId) {
133963
+ manager2.removePanel(workspaceId, terminalId);
133964
+ }
133965
+
133966
+ // src/lib/terminal-manager.ts
133403
133967
  var log17 = createLogger("terminal");
133404
133968
  var MAX_SCROLLBACK_SIZE = 1e5;
133405
133969
  var terminals = /* @__PURE__ */ new Map();
@@ -133477,6 +134041,11 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
133477
134041
  workspaceTerminals.set(workspaceId, ids);
133478
134042
  }
133479
134043
  ids.add(terminalId);
134044
+ addTerminalToLayout(workspaceId, terminalId, {
134045
+ command: options2?.command,
134046
+ cwd: options2?.cwd,
134047
+ env: options2?.env
134048
+ });
133480
134049
  ptyProcess.onData((data) => {
133481
134050
  session.scrollback += data;
133482
134051
  if (session.scrollback.length > MAX_SCROLLBACK_SIZE) {
@@ -140762,155 +141331,13 @@ import { promisify } from "node:util";
140762
141331
  init_src();
140763
141332
  init_zod();
140764
141333
 
140765
- // src/lib/dockview-layout-manager.ts
140766
- function isLeaf(node) {
140767
- return node.type === "leaf" && typeof node.data === "object" && !Array.isArray(node.data);
140768
- }
140769
- function isBranch(node) {
140770
- return node.type === "branch" && Array.isArray(node.data);
140771
- }
140772
- function findFirstLeaf(node) {
140773
- if (isLeaf(node)) return node.data;
140774
- if (isBranch(node)) {
140775
- for (const child of node.data) {
140776
- const found = findFirstLeaf(child);
140777
- if (found) return found;
140778
- }
140779
- }
140780
- return null;
140781
- }
140782
- function removeFromGrid(node, panelId) {
140783
- if (isLeaf(node)) {
140784
- const idx = node.data.views.indexOf(panelId);
140785
- if (idx !== -1) {
140786
- node.data.views.splice(idx, 1);
140787
- if (node.data.activeView === panelId) {
140788
- node.data.activeView = node.data.views[0];
140789
- }
140790
- }
140791
- } else if (isBranch(node)) {
140792
- for (const child of node.data) {
140793
- removeFromGrid(child, panelId);
140794
- }
140795
- }
140796
- }
140797
- function isDockviewLayout(obj) {
140798
- if (typeof obj !== "object" || obj === null) return false;
140799
- const o2 = obj;
140800
- return typeof o2.grid === "object" && typeof o2.panels === "object";
140801
- }
140802
- var DockviewLayoutManager = class {
140803
- constructor(panelType) {
140804
- this.panelType = panelType;
140805
- }
140806
- layoutId(workspaceId) {
140807
- return `${this.panelType}_${workspaceId}`;
140808
- }
140809
- /**
140810
- * Get the layout tree for a workspace.
140811
- * Returns the parsed JSON tree or null if no layout is stored.
140812
- */
140813
- get(workspaceId) {
140814
- const rows = listPanelStatesForWorkspace(workspaceId, this.panelType);
140815
- if (rows.length === 0) return null;
140816
- try {
140817
- return JSON.parse(rows[0].state);
140818
- } catch {
140819
- return null;
140820
- }
140821
- }
140822
- /**
140823
- * Save (upsert) the layout tree for a workspace.
140824
- */
140825
- save(workspaceId, tree) {
140826
- const id = this.layoutId(workspaceId);
140827
- const state2 = JSON.stringify(tree);
140828
- const now = Date.now();
140829
- const rows = listPanelStatesForWorkspace(workspaceId, this.panelType);
140830
- if (rows.length > 0) {
140831
- updatePanelState(id, { state: state2, updatedAt: now });
140832
- } else {
140833
- insertPanelState({
140834
- id,
140835
- workspaceId,
140836
- panelType: this.panelType,
140837
- state: state2,
140838
- createdAt: now,
140839
- updatedAt: now
140840
- });
140841
- }
140842
- }
140843
- /**
140844
- * Delete the layout for a workspace.
140845
- */
140846
- delete(workspaceId) {
140847
- deletePanelStatesForWorkspace(workspaceId, this.panelType);
140848
- }
140849
- /**
140850
- * Add a panel to the saved dockview layout.
140851
- *
140852
- * Appends the panel to the first group's `views` array and adds the panel
140853
- * entry to the `panels` map. If no layout exists, creates a fresh one-tab layout.
140854
- */
140855
- addPanel(workspaceId, panel) {
140856
- const raw = this.get(workspaceId);
140857
- if (raw && isDockviewLayout(raw)) {
140858
- raw.panels[panel.id] = panel;
140859
- const leaf = findFirstLeaf(raw.grid.root);
140860
- if (leaf) {
140861
- leaf.views.push(panel.id);
140862
- leaf.activeView = panel.id;
140863
- }
140864
- this.save(workspaceId, raw);
140865
- } else {
140866
- const groupId = `group_${panel.id}`;
140867
- const layout = {
140868
- grid: {
140869
- root: {
140870
- type: "leaf",
140871
- data: { id: groupId, views: [panel.id], activeView: panel.id },
140872
- size: 1
140873
- },
140874
- height: 500,
140875
- width: 500,
140876
- orientation: "HORIZONTAL"
140877
- },
140878
- panels: { [panel.id]: panel },
140879
- activeGroup: groupId
140880
- };
140881
- this.save(workspaceId, layout);
140882
- }
140883
- }
140884
- /**
140885
- * Remove a panel from the saved dockview layout.
140886
- *
140887
- * Removes the panel from the `panels` map and from any group's `views` array.
140888
- */
140889
- removePanel(workspaceId, panelId) {
140890
- const raw = this.get(workspaceId);
140891
- if (!raw || !isDockviewLayout(raw)) return;
140892
- delete raw.panels[panelId];
140893
- removeFromGrid(raw.grid.root, panelId);
140894
- this.save(workspaceId, raw);
140895
- }
140896
- /**
140897
- * List all panel IDs in the saved layout.
140898
- * Useful for reconciling layout with live records.
140899
- */
140900
- listPanelIds(workspaceId) {
140901
- const raw = this.get(workspaceId);
140902
- if (!raw || !isDockviewLayout(raw)) return [];
140903
- return Object.keys(raw.panels);
140904
- }
140905
- };
140906
-
140907
141334
  // src/lib/browser-layout-manager.ts
140908
- var manager = new DockviewLayoutManager("browser_layout");
140909
- var getBrowserLayout = (workspaceId) => manager.get(workspaceId);
140910
- var saveBrowserLayout = (workspaceId, tree) => manager.save(workspaceId, tree);
140911
- var deleteBrowserLayout = (workspaceId) => manager.delete(workspaceId);
141335
+ var manager3 = new DockviewLayoutManager("browser_layout");
141336
+ var getBrowserLayout = (workspaceId) => manager3.get(workspaceId);
141337
+ var saveBrowserLayout = (workspaceId, tree) => manager3.save(workspaceId, tree);
141338
+ var deleteBrowserLayout = (workspaceId) => manager3.delete(workspaceId);
140912
141339
  function addBrowserToLayout(workspaceId, browserId, opts) {
140913
- manager.addPanel(workspaceId, {
141340
+ manager3.addPanel(workspaceId, {
140914
141341
  id: browserId,
140915
141342
  contentComponent: "browserTab",
140916
141343
  tabComponent: "browserTab",
@@ -140923,7 +141350,7 @@ function addBrowserToLayout(workspaceId, browserId, opts) {
140923
141350
  });
140924
141351
  }
140925
141352
  function removeBrowserFromLayout(workspaceId, browserId) {
140926
- manager.removePanel(workspaceId, browserId);
141353
+ manager3.removePanel(workspaceId, browserId);
140927
141354
  }
140928
141355
 
140929
141356
  // src/lib/browser-manager.ts
@@ -140985,6 +141412,10 @@ function createBrowser(workspaceId, options2) {
140985
141412
  updatedAt: now
140986
141413
  });
140987
141414
  addToIndex2(tab);
141415
+ addBrowserToLayout(workspaceId, tab.id, {
141416
+ title: tab.name,
141417
+ initialUrl: tab.url || void 0
141418
+ });
140988
141419
  log20.info({ browserId: tab.id, workspaceId, url: tab.url }, "browser tab created");
140989
141420
  return tab;
140990
141421
  }
@@ -141068,12 +141499,6 @@ function loadBrowsersFromDb() {
141068
141499
  return rows.length;
141069
141500
  }
141070
141501
 
141071
- // src/lib/chat-layout-manager.ts
141072
- var manager2 = new DockviewLayoutManager("chat_layout");
141073
- var getChatLayout = (workspaceId) => manager2.get(workspaceId);
141074
- var saveChatLayout = (workspaceId, tree) => manager2.save(workspaceId, tree);
141075
- var deleteChatLayout = (workspaceId) => manager2.delete(workspaceId);
141076
-
141077
141502
  // src/lib/chat-session-summary.ts
141078
141503
  init_src();
141079
141504
  var log21 = createLogger("chat-session-summary");
@@ -141261,6 +141686,7 @@ function convertEventsToUIMessages(events) {
141261
141686
  }
141262
141687
  case "data-session":
141263
141688
  case "data-result":
141689
+ case "data-usage":
141264
141690
  case "finish-step":
141265
141691
  case "finish":
141266
141692
  case "start-step":
@@ -141477,30 +141903,6 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
141477
141903
  return result.data;
141478
141904
  }
141479
141905
 
141480
- // src/lib/terminal-layout-manager.ts
141481
- var manager3 = new DockviewLayoutManager("terminal_layout");
141482
- var getTerminalLayout = (workspaceId) => manager3.get(workspaceId);
141483
- var saveTerminalLayout = (workspaceId, tree) => manager3.save(workspaceId, tree);
141484
- var deleteTerminalLayout = (workspaceId) => manager3.delete(workspaceId);
141485
- function addTerminalToLayout(workspaceId, terminalId, opts) {
141486
- manager3.addPanel(workspaceId, {
141487
- id: terminalId,
141488
- contentComponent: "terminalTab",
141489
- tabComponent: "terminalTab",
141490
- title: opts?.title ?? "Terminal",
141491
- params: {
141492
- workspaceId,
141493
- terminalId,
141494
- ...opts?.command ? { command: opts.command } : {},
141495
- ...opts?.cwd ? { cwd: opts.cwd } : {},
141496
- ...opts?.env ? { env: opts.env } : {}
141497
- }
141498
- });
141499
- }
141500
- function removeTerminalFromLayout(workspaceId, terminalId) {
141501
- manager3.removePanel(workspaceId, terminalId);
141502
- }
141503
-
141504
141906
  // src/trpc/router.ts
141505
141907
  var execFileAsync = promisify(execFile4);
141506
141908
  var log23 = createLogger("trpc");
@@ -142592,6 +142994,7 @@ var sessionsRouter = t2.router({
142592
142994
  })
142593
142995
  ).query(async ({ input }) => {
142594
142996
  const pageSize = input.limit ?? 100;
142997
+ const lastUsage = input.beforeEventId ? null : getSessionUsage(input.sessionId) ?? null;
142595
142998
  if (input.beforeMessageIndex === void 0) {
142596
142999
  const events = input.beforeEventId ? getSessionEventsBefore(input.sessionId, input.beforeEventId, pageSize) : getSessionEventsTail(input.sessionId, pageSize);
142597
143000
  if (events.length > 0) {
@@ -142606,7 +143009,8 @@ var sessionsRouter = t2.router({
142606
143009
  firstEventId,
142607
143010
  lastEventId,
142608
143011
  firstMessageIndex: null,
142609
- hasMore: hasMoreInBuffer
143012
+ hasMore: hasMoreInBuffer,
143013
+ lastUsage
142610
143014
  };
142611
143015
  }
142612
143016
  try {
@@ -142626,7 +143030,8 @@ var sessionsRouter = t2.router({
142626
143030
  firstEventId: null,
142627
143031
  lastEventId,
142628
143032
  firstMessageIndex: jsonl2.firstMessageIndex,
142629
- hasMore: jsonl2.hasMore
143033
+ hasMore: jsonl2.hasMore,
143034
+ lastUsage
142630
143035
  };
142631
143036
  }
142632
143037
  }
@@ -142637,7 +143042,8 @@ var sessionsRouter = t2.router({
142637
143042
  firstEventId,
142638
143043
  lastEventId,
142639
143044
  firstMessageIndex: null,
142640
- hasMore: false
143045
+ hasMore: false,
143046
+ lastUsage
142641
143047
  };
142642
143048
  }
142643
143049
  }
@@ -142661,7 +143067,8 @@ var sessionsRouter = t2.router({
142661
143067
  firstEventId: null,
142662
143068
  lastEventId: null,
142663
143069
  firstMessageIndex: jsonl.firstMessageIndex,
142664
- hasMore: jsonl.hasMore
143070
+ hasMore: jsonl.hasMore,
143071
+ lastUsage
142665
143072
  };
142666
143073
  })
142667
143074
  });
@@ -143156,10 +143563,6 @@ var browsersRouter = t2.router({
143156
143563
  name: input.name,
143157
143564
  url: input.url
143158
143565
  });
143159
- addBrowserToLayout(input.workspaceId, browser2.id, {
143160
- title: input.name,
143161
- initialUrl: input.url
143162
- });
143163
143566
  emit({ kind: "browser-created", workspaceId: input.workspaceId, browserId: browser2.id });
143164
143567
  return { browser: browser2 };
143165
143568
  }),
@@ -143291,11 +143694,6 @@ var terminalRouter = t2.router({
143291
143694
  cwd: input.cwd,
143292
143695
  env: input.env
143293
143696
  });
143294
- addTerminalToLayout(input.workspaceId, terminalId, {
143295
- command: input.command,
143296
- cwd: input.cwd,
143297
- env: input.env
143298
- });
143299
143697
  emit({ kind: "terminal-created", workspaceId: input.workspaceId, terminalId });
143300
143698
  return { terminalId, workspaceId: input.workspaceId, pid: session.pty.pid };
143301
143699
  }),