@band-app/server 0.16.9 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/dist/client/assets/DockviewBrowserContainer-B_oEene2.js +5 -0
  2. package/dist/client/assets/DockviewTerminalContainer-CfQMvR_k.js +2 -0
  3. package/dist/client/assets/TerminalPanel-DxZK0ClB.js +5 -0
  4. package/dist/client/assets/{_basePickBy-uVqvgsJc.js → _basePickBy-Ct-e0Qqq.js} +1 -1
  5. package/dist/client/assets/{_baseUniq-7i7L1uNE.js → _baseUniq-CxKOXF1k.js} +1 -1
  6. package/dist/client/assets/arc-CKSDLbJ_.js +1 -0
  7. package/dist/client/assets/architectureDiagram-VXUJARFQ-DX7YfptV.js +36 -0
  8. package/dist/client/assets/{blockDiagram-VD42YOAC-CXQSSz3O.js → blockDiagram-VD42YOAC-CsuIx-c9.js} +5 -5
  9. package/dist/client/assets/{c4Diagram-YG6GDRKO-DplRXCR2.js → c4Diagram-YG6GDRKO-DychwT1W.js} +3 -3
  10. package/dist/client/assets/channel-B-u6m7I1.js +1 -0
  11. package/dist/client/assets/chunk-4BX2VUAB-loz8MPPD.js +1 -0
  12. package/dist/client/assets/chunk-55IACEB6-D29ChrqC.js +1 -0
  13. package/dist/client/assets/{chunk-B4BG7PRW-DlN9tUxh.js → chunk-B4BG7PRW-DKCONMEK.js} +6 -6
  14. package/dist/client/assets/{chunk-DI55MBZ5-a11zyhq4.js → chunk-DI55MBZ5-D5zzjeE8.js} +1 -1
  15. package/dist/client/assets/{chunk-FMBD7UC4-aGGVV1yn.js → chunk-FMBD7UC4-D1xESdhD.js} +1 -1
  16. package/dist/client/assets/chunk-QN33PNHL-DXisPMUT.js +1 -0
  17. package/dist/client/assets/chunk-QZHKN3VN-Ch8ZVx4Y.js +1 -0
  18. package/dist/client/assets/chunk-TZMSLE5B-GuM5n4Rs.js +1 -0
  19. package/dist/client/assets/classDiagram-2ON5EDUG-ZLOOfEOW.js +1 -0
  20. package/dist/client/assets/classDiagram-v2-WZHVMYZB-ZLOOfEOW.js +1 -0
  21. package/dist/client/assets/clone-CDLv4lRU.js +1 -0
  22. package/dist/client/assets/cose-bilkent-S5V4N54A-Cf0f3nH9.js +1 -0
  23. package/dist/client/assets/dagre-6UL2VRFP-BEjucV14.js +4 -0
  24. package/dist/client/assets/diagram-PSM6KHXK-4UTMLb3J.js +24 -0
  25. package/dist/client/assets/diagram-QEK2KX5R-B9rhi9zE.js +43 -0
  26. package/dist/client/assets/diagram-S2PKOQOG-CS7F4WJO.js +24 -0
  27. package/dist/client/assets/{erDiagram-Q2GNP2WA-kUd-gmjz.js → erDiagram-Q2GNP2WA-D-EqIR9o.js} +4 -4
  28. package/dist/client/assets/{flowDiagram-NV44I4VS-CHbLqCKB.js → flowDiagram-NV44I4VS-_GH1A_sS.js} +5 -5
  29. package/dist/client/assets/ganttDiagram-JELNMOA3-Dtb6N1ze.js +267 -0
  30. package/dist/client/assets/gitGraphDiagram-V2S2FVAM-B_QsP5ak.js +65 -0
  31. package/dist/client/assets/{graph-CSi_akmB.js → graph-H6OCDpse.js} +1 -1
  32. package/dist/client/assets/highlighted-body-B3W2YXNL-Pz2rshlt.js +1 -0
  33. package/dist/client/assets/index-B-KsZlI_.js +1 -0
  34. package/dist/client/assets/{index-udv0M-ix.js → index-BCbe81ki.js} +2 -2
  35. package/dist/client/assets/index-BOdifnXB.js +1 -0
  36. package/dist/client/assets/{index-BPf6S9f1.js → index-BQW7Zpk7.js} +1 -1
  37. package/dist/client/assets/index-BX_7-t5E.js +1 -0
  38. package/dist/client/assets/{index-B0ZcEU4c.js → index-BktK8Iwc.js} +1 -1
  39. package/dist/client/assets/{index-C-6dsPog.js → index-BtEs1oEp.js} +1 -1
  40. package/dist/client/assets/{index-T_1b5WRg.js → index-BtajlvkF.js} +1 -1
  41. package/dist/client/assets/{index-CNQHGhCu.js → index-Bx3rRbZG.js} +1 -1
  42. package/dist/client/assets/{index-DfHcm4JM.js → index-C6MgAn1q.js} +1 -1
  43. package/dist/client/assets/{index-C4ee_PQ0.js → index-CzCjpAqZ.js} +5 -5
  44. package/dist/client/assets/{index-oolizINO.js → index-DQAckahj.js} +1 -1
  45. package/dist/client/assets/index-DaRnNd02.js +7 -0
  46. package/dist/client/assets/{index-BJP1qdPz.js → index-Im7rGMYn.js} +1 -1
  47. package/dist/client/assets/{index-CA1NuCd_.js → index-WmGuuT8Z.js} +1 -1
  48. package/dist/client/assets/{index-C-3PAt1d.js → index-aTt3zXBv.js} +1 -1
  49. package/dist/client/assets/{index-5X7JRvnK.js → index-nPplcWzt.js} +1 -1
  50. package/dist/client/assets/{index-spwNnd85.js → index-vaGaAlmP.js} +1 -1
  51. package/dist/client/assets/infoDiagram-HS3SLOUP-Dp2iuUeA.js +2 -0
  52. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-DIY8FE8Z.js → journeyDiagram-XKPGCS4Q-BaVzrE3V.js} +3 -3
  53. package/dist/client/assets/{kanban-definition-3W4ZIXB7-Cd_JJ8FN.js → kanban-definition-3W4ZIXB7-DdbWsnm7.js} +8 -8
  54. package/dist/client/assets/{layout-Bhb5FQCr.js → layout-vxWf40Ht.js} +1 -1
  55. package/dist/client/assets/{linear-Cmk2RyH_.js → linear-BstrgKy8.js} +1 -1
  56. package/dist/client/assets/{main-BlRcPsmZ.js → main-DRq9Axai.js} +227 -226
  57. package/dist/client/assets/main-evBJruhw.css +1 -0
  58. package/dist/client/assets/{mindmap-definition-VGOIOE7T-B-WhBVeY.js → mindmap-definition-VGOIOE7T-CAEEMYhK.js} +3 -3
  59. package/dist/client/assets/pieDiagram-ADFJNKIX-DCNv4UlO.js +30 -0
  60. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-DHBoMUCQ.js → quadrantDiagram-AYHSOK5B-BeP4t0hp.js} +2 -2
  61. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-DjS5RONh.js → requirementDiagram-UZGBJVZJ-CAdiLb_M.js} +2 -2
  62. package/dist/client/assets/sankeyDiagram-TZEHDZUN-DW9xKT5Y.js +10 -0
  63. package/dist/client/assets/{sequenceDiagram-WL72ISMW-CzqbRfb_.js → sequenceDiagram-WL72ISMW-D9y8fK_R.js} +1 -1
  64. package/dist/client/assets/{square-terminal-CNHJa6OY.js → square-terminal-VjG9-RoZ.js} +1 -1
  65. package/dist/client/assets/stateDiagram-FKZM4ZOC-QYuyBeVm.js +1 -0
  66. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-VVONI0Hb.js +1 -0
  67. package/dist/client/assets/{timeline-definition-IT6M3QCI-CNKMKDwq.js → timeline-definition-IT6M3QCI-Ci_SXZdO.js} +4 -4
  68. package/dist/client/assets/{treemap-GDKQZRPO-DCEPrZh7.js → treemap-GDKQZRPO-fDacl-jS.js} +1 -1
  69. package/dist/client/assets/workspace._workspaceId-C9BVWo6-.js +2 -0
  70. package/dist/client/assets/workspace._workspaceId-CMlw9wn8.js +1 -0
  71. package/dist/client/assets/{xychartDiagram-PRI3JC2R-Cr18I3A3.js → xychartDiagram-PRI3JC2R-rRpBADcB.js} +4 -4
  72. package/dist/migrations/20260525163504_add_projects_has_origin/migration.sql +1 -0
  73. package/dist/migrations/20260525163504_add_projects_has_origin/snapshot.json +866 -0
  74. package/dist/openapi.json +414 -4
  75. package/dist/server/assets/{DockviewBrowserContainer-Bm7ARaqd.js → DockviewBrowserContainer-BAe7TLKD.js} +42 -22
  76. package/dist/server/assets/{DockviewTerminalContainer-BbMZgBJ8.js → DockviewTerminalContainer-CC7i0yMZ.js} +44 -24
  77. package/dist/server/assets/{TerminalPanel-BmhYCf33.js → TerminalPanel-gBh8VBn0.js} +1 -1
  78. package/dist/server/assets/{_basePickBy-C7CNOUDi.js → _basePickBy-CTks6QXq.js} +2 -2
  79. package/dist/server/assets/{_baseUniq-DeF47vVO.js → _baseUniq-BJI4qneQ.js} +1 -1
  80. package/dist/server/assets/_tanstack-start-manifest_v-CfuSyuIp.js +4 -0
  81. package/dist/server/assets/{arc-P5FY7IYH.js → arc-Fdc_l0PB.js} +1 -1
  82. package/dist/server/assets/{architecture-7HQA4BMR-LvprLHYS.js → architecture-7HQA4BMR-CfPXboDr.js} +6 -6
  83. package/dist/server/assets/{architectureDiagram-VXUJARFQ-Br4iiUzH.js → architectureDiagram-VXUJARFQ-D6UEkzy_.js} +6 -6
  84. package/dist/server/assets/{blockDiagram-VD42YOAC-BahODDhX.js → blockDiagram-VD42YOAC-BvasIENt.js} +6 -6
  85. package/dist/server/assets/{c4Diagram-YG6GDRKO-CQcZX6cr.js → c4Diagram-YG6GDRKO-MW5H9zoJ.js} +2 -2
  86. package/dist/server/assets/{channel-BmAB_ZKU.js → channel-XhTiPor2.js} +1 -1
  87. package/dist/server/assets/{chunk-4BX2VUAB-YUvszr4w.js → chunk-4BX2VUAB-C6POw9HJ.js} +1 -1
  88. package/dist/server/assets/{chunk-55IACEB6-BUgBPiJd.js → chunk-55IACEB6-BZ0x-UQb.js} +1 -1
  89. package/dist/server/assets/{chunk-B4BG7PRW-BxuWeZlV.js → chunk-B4BG7PRW-BAYqNQHL.js} +4 -4
  90. package/dist/server/assets/{chunk-DI55MBZ5-DuGkdvte.js → chunk-DI55MBZ5-DbsR50vR.js} +3 -3
  91. package/dist/server/assets/{chunk-FMBD7UC4-qY-BVG34.js → chunk-FMBD7UC4-D_KXTL87.js} +1 -1
  92. package/dist/server/assets/{chunk-QN33PNHL-BM_oi8-e.js → chunk-QN33PNHL-RXXHu7T0.js} +1 -1
  93. package/dist/server/assets/{chunk-QZHKN3VN-BL6_-at8.js → chunk-QZHKN3VN-5QE6weTd.js} +1 -1
  94. package/dist/server/assets/{chunk-TZMSLE5B-38NhX5at.js → chunk-TZMSLE5B-HlRXkCDZ.js} +1 -1
  95. package/dist/server/assets/{classDiagram-v2-WZHVMYZB-CwIsZ53p.js → classDiagram-2ON5EDUG-B90fR_EV.js} +5 -5
  96. package/dist/server/assets/{classDiagram-2ON5EDUG-CwIsZ53p.js → classDiagram-v2-WZHVMYZB-B90fR_EV.js} +5 -5
  97. package/dist/server/assets/{clone-BXHuGM8i.js → clone-Bjcb6OQr.js} +1 -1
  98. package/dist/server/assets/{cose-bilkent-S5V4N54A-D1CdgGvI.js → cose-bilkent-S5V4N54A-BgnWrjAl.js} +1 -1
  99. package/dist/server/assets/{dagre-6UL2VRFP-UMvdMLG3.js → dagre-6UL2VRFP-LfRXD26Q.js} +6 -6
  100. package/dist/server/assets/{diagram-PSM6KHXK-DtOD93m7.js → diagram-PSM6KHXK-DLrJ9Eja.js} +7 -7
  101. package/dist/server/assets/{diagram-QEK2KX5R-DViyYq-y.js → diagram-QEK2KX5R-atbHIh96.js} +6 -6
  102. package/dist/server/assets/{diagram-S2PKOQOG-C42mRVEn.js → diagram-S2PKOQOG-BnxctnIJ.js} +6 -6
  103. package/dist/server/assets/{erDiagram-Q2GNP2WA-D14z9IvB.js → erDiagram-Q2GNP2WA-Ct1zXovC.js} +4 -4
  104. package/dist/server/assets/{flowDiagram-NV44I4VS-BYBNOZwM.js → flowDiagram-NV44I4VS-DtWHb6Ay.js} +5 -5
  105. package/dist/server/assets/{ganttDiagram-JELNMOA3-CaG3uoK-.js → ganttDiagram-JELNMOA3-CySyldy4.js} +2 -2
  106. package/dist/server/assets/{gitGraph-G5XIXVHT-Dsx3dV0R.js → gitGraph-G5XIXVHT-DFo7FJzL.js} +6 -6
  107. package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-CrSfx7b3.js → gitGraphDiagram-V2S2FVAM-DvT5EUG7.js} +7 -7
  108. package/dist/server/assets/{graph-gBFInK6H.js → graph-B5XlkLf_.js} +2 -2
  109. package/dist/server/assets/{highlighted-body-B3W2YXNL-DjTWk17l.js → highlighted-body-B3W2YXNL-CLJWhRU_.js} +1 -1
  110. package/dist/server/assets/{index-C3N_Nx6h.js → index--4MijjkY.js} +2 -2
  111. package/dist/server/assets/{index-C245EJn1.js → index-4SOjxyuO.js} +2 -2
  112. package/dist/server/assets/{index-3wtbr7va.js → index-BQ5LDgRA.js} +3 -3
  113. package/dist/server/assets/{index-CD97pPmc.js → index-BanzNq86.js} +1 -1
  114. package/dist/server/assets/{index-2gWBdIrR.js → index-BvJzvUfR.js} +2 -2
  115. package/dist/server/assets/{index-B84Urg23.js → index-C2GzB22l.js} +2 -2
  116. package/dist/server/assets/{index-QxgXX0fb.js → index-CAJcSCqE.js} +2 -2
  117. package/dist/server/assets/{index-Bs6a6-xI.js → index-CLUle2oh.js} +5 -5
  118. package/dist/server/assets/{index-5N2Gh0ba.js → index-CMO4FLK_.js} +2 -2
  119. package/dist/server/assets/{index-6Zof9vm8.js → index-CXMNOcuN.js} +1 -1
  120. package/dist/server/assets/{index-Dv-16VYI.js → index-CXmMBSCL.js} +2 -2
  121. package/dist/server/assets/{index-DXgP0Lsu.js → index-CdgmRfZg.js} +2 -2
  122. package/dist/server/assets/{index-CwQ5qWPC.js → index-DJ8A5E65.js} +5 -5
  123. package/dist/server/assets/{index-DZZ6NiTf.js → index-DjySh3G7.js} +3 -3
  124. package/dist/server/assets/{index-Bd5jTryJ.js → index-DuXjusjn.js} +2 -2
  125. package/dist/server/assets/{index-DsGPaWHg.js → index-QiPzMfSX.js} +2 -2
  126. package/dist/server/assets/{index-Bw42FDwO.js → index-SuLB6TaE.js} +2 -2
  127. package/dist/server/assets/{index-egmIrLx2.js → index-bmq-aMYV.js} +4 -4
  128. package/dist/server/assets/{info-VBDWY6EO-CueOsYFZ.js → info-VBDWY6EO-CW57QiJi.js} +6 -6
  129. package/dist/server/assets/{infoDiagram-HS3SLOUP-CeyMzohL.js → infoDiagram-HS3SLOUP-D_Zdx-MM.js} +5 -5
  130. package/dist/server/assets/{journeyDiagram-XKPGCS4Q-ANqeM_TM.js → journeyDiagram-XKPGCS4Q-BcO9qzr2.js} +4 -4
  131. package/dist/server/assets/{kanban-definition-3W4ZIXB7-B0RkH45q.js → kanban-definition-3W4ZIXB7-BatZ7RKG.js} +2 -2
  132. package/dist/server/assets/{layout-JjP5jdu6.js → layout-Cwuj9CwZ.js} +4 -4
  133. package/dist/server/assets/{linear-BJgoq5J4.js → linear-CP3xC85V.js} +1 -1
  134. package/dist/server/assets/{mermaid-3ZIDBTTL-CFPuUseQ.js → mermaid-3ZIDBTTL-BZm8jQDo.js} +1 -1
  135. package/dist/server/assets/{mermaid-parser.core-CKKZ1VFr.js → mermaid-parser.core-Cx17C8XR.js} +11 -11
  136. package/dist/server/assets/{mindmap-definition-VGOIOE7T-DlEXF5z8.js → mindmap-definition-VGOIOE7T-CpzqFomk.js} +3 -3
  137. package/dist/server/assets/{packet-DYOGHKS2-CvyxHTRM.js → packet-DYOGHKS2-x3ihoqUO.js} +6 -6
  138. package/dist/server/assets/{pie-VRWISCQL-DfpVZlpC.js → pie-VRWISCQL-DsMBDe8r.js} +6 -6
  139. package/dist/server/assets/{pieDiagram-ADFJNKIX-CWkrHsNk.js → pieDiagram-ADFJNKIX-DI4Hh6KE.js} +7 -7
  140. package/dist/server/assets/{quadrantDiagram-AYHSOK5B-C25p2xz7.js → quadrantDiagram-AYHSOK5B-Cqc_vrUG.js} +2 -2
  141. package/dist/server/assets/{radar-ZZBFDIW7-DWqPsDMi.js → radar-ZZBFDIW7-CqwCJm3D.js} +6 -6
  142. package/dist/server/assets/{requirementDiagram-UZGBJVZJ-ACRVXQGO.js → requirementDiagram-UZGBJVZJ-96ab-40P.js} +3 -3
  143. package/dist/server/assets/{router-GhGSLKfP.js → router-CYNdQEN4.js} +1116 -579
  144. package/dist/server/assets/{sankeyDiagram-TZEHDZUN-uzNSHudY.js → sankeyDiagram-TZEHDZUN-Bux2-BQd.js} +1 -1
  145. package/dist/server/assets/{sequenceDiagram-WL72ISMW-C_wFtq8b.js → sequenceDiagram-WL72ISMW-CFKyfvmC.js} +3 -3
  146. package/dist/server/assets/{square-terminal-cghvb5Il.js → square-terminal-gVSeBp7-.js} +1 -1
  147. package/dist/server/assets/{stateDiagram-FKZM4ZOC-B9MGwsuS.js → stateDiagram-FKZM4ZOC-DGZQd18J.js} +8 -8
  148. package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-CLHd8oUa.js → stateDiagram-v2-4FDKWEC3-DJXeLDOB.js} +4 -4
  149. package/dist/server/assets/{timeline-definition-IT6M3QCI-CqKot5RT.js → timeline-definition-IT6M3QCI-DzTJZPN5.js} +2 -2
  150. package/dist/server/assets/{treemap-GDKQZRPO-mMRojqRQ.js → treemap-GDKQZRPO-CD9jkQrA.js} +6 -6
  151. package/dist/server/assets/workspace._workspaceId-ClAAZ5aq.js +23 -0
  152. package/dist/server/assets/{workspace._workspaceId-DwsRTXCg.js → workspace._workspaceId-DT6Kz8RH.js} +125 -97
  153. package/dist/server/assets/{xychartDiagram-PRI3JC2R-j8PckQEj.js → xychartDiagram-PRI3JC2R-ByA0_p8p.js} +2 -2
  154. package/dist/server/server.js +2 -2
  155. package/dist/start-server.mjs +489 -242
  156. package/package.json +4 -4
  157. package/dist/client/assets/DockviewBrowserContainer-CCBAkU1p.js +0 -5
  158. package/dist/client/assets/DockviewTerminalContainer-B9hdDoMz.js +0 -2
  159. package/dist/client/assets/TerminalPanel-BKfWmj6W.js +0 -5
  160. package/dist/client/assets/arc-DiYEQGs3.js +0 -1
  161. package/dist/client/assets/architectureDiagram-VXUJARFQ-C5z8L1iK.js +0 -36
  162. package/dist/client/assets/channel-BnMJuhcI.js +0 -1
  163. package/dist/client/assets/chunk-4BX2VUAB-B4Mk_d7A.js +0 -1
  164. package/dist/client/assets/chunk-55IACEB6-B0hf8Eje.js +0 -1
  165. package/dist/client/assets/chunk-QN33PNHL-Dit4S-yJ.js +0 -1
  166. package/dist/client/assets/chunk-QZHKN3VN-L-h1VSi0.js +0 -1
  167. package/dist/client/assets/chunk-TZMSLE5B-DpK-hWaC.js +0 -1
  168. package/dist/client/assets/classDiagram-2ON5EDUG-D89oCSXI.js +0 -1
  169. package/dist/client/assets/classDiagram-v2-WZHVMYZB-D89oCSXI.js +0 -1
  170. package/dist/client/assets/clone-X7FA7kE2.js +0 -1
  171. package/dist/client/assets/cose-bilkent-S5V4N54A-CzoIK-3W.js +0 -1
  172. package/dist/client/assets/dagre-6UL2VRFP-BhfXeb7k.js +0 -4
  173. package/dist/client/assets/diagram-PSM6KHXK-BwFVwR1b.js +0 -24
  174. package/dist/client/assets/diagram-QEK2KX5R-BO-CEopy.js +0 -43
  175. package/dist/client/assets/diagram-S2PKOQOG-BxiH83lN.js +0 -24
  176. package/dist/client/assets/ganttDiagram-JELNMOA3-B7gBcAFl.js +0 -267
  177. package/dist/client/assets/gitGraphDiagram-V2S2FVAM-gca_jqKQ.js +0 -65
  178. package/dist/client/assets/highlighted-body-B3W2YXNL-C2a-lsk8.js +0 -1
  179. package/dist/client/assets/index-2F-slvqo.js +0 -1
  180. package/dist/client/assets/index-C4PISrIW.js +0 -1
  181. package/dist/client/assets/index-CiKTedrx.js +0 -1
  182. package/dist/client/assets/index-DNrK0iIn.js +0 -7
  183. package/dist/client/assets/infoDiagram-HS3SLOUP-BK3MmhkJ.js +0 -2
  184. package/dist/client/assets/main-BLOY6Nam.css +0 -1
  185. package/dist/client/assets/pieDiagram-ADFJNKIX-CYoHsaM9.js +0 -30
  186. package/dist/client/assets/sankeyDiagram-TZEHDZUN-DmhEbBY-.js +0 -10
  187. package/dist/client/assets/stateDiagram-FKZM4ZOC-CafvdTb3.js +0 -1
  188. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BkKHK-CQ.js +0 -1
  189. package/dist/client/assets/useSessionListContext-xer-Wcmf.js +0 -1
  190. package/dist/client/assets/workspace._workspaceId-CgG1n_1x.js +0 -1
  191. package/dist/client/assets/workspace._workspaceId.changes-BKX7lUhX.js +0 -1
  192. package/dist/client/assets/workspace._workspaceId.code-BcnxRdZi.js +0 -1
  193. package/dist/client/assets/workspace._workspaceId.code._-BbOt6tOD.js +0 -1
  194. package/dist/client/assets/workspace._workspaceId.code.index-DC2535x-.js +0 -1
  195. package/dist/client/assets/workspace._workspaceId.index-CNjq1nDf.js +0 -1
  196. package/dist/client/assets/workspace._workspaceId.terminal-DhYn8I5t.js +0 -2
  197. package/dist/server/assets/_tanstack-start-manifest_v-BNCQ-izx.js +0 -4
  198. package/dist/server/assets/useSessionListContext-D_vX6E2e.js +0 -23
  199. package/dist/server/assets/workspace._workspaceId.changes-C6vwSbUh.js +0 -38
  200. package/dist/server/assets/workspace._workspaceId.code-Cuj0zH98.js +0 -12
  201. package/dist/server/assets/workspace._workspaceId.code._-BJdg1-Gs.js +0 -44
  202. package/dist/server/assets/workspace._workspaceId.code.index-CE_CMD_I.js +0 -36
  203. package/dist/server/assets/workspace._workspaceId.index-BPhXMwl8.js +0 -112
  204. package/dist/server/assets/workspace._workspaceId.terminal-BdVDaWNH.js +0 -24
@@ -6501,11 +6501,11 @@ var require_tools = __commonJS({
6501
6501
  }
6502
6502
  }
6503
6503
  }
6504
- function buildFormatters(level, bindings, log29) {
6504
+ function buildFormatters(level, bindings, log31) {
6505
6505
  return {
6506
6506
  level,
6507
6507
  bindings,
6508
- log: log29
6508
+ log: log31
6509
6509
  };
6510
6510
  }
6511
6511
  function normalizeDestFileDescriptor(destination) {
@@ -6888,11 +6888,11 @@ var require_proto = __commonJS({
6888
6888
  }
6889
6889
  } else instance[serializersSym] = serializers;
6890
6890
  if (options2.hasOwnProperty("formatters")) {
6891
- const { level, bindings: chindings, log: log29 } = options2.formatters;
6891
+ const { level, bindings: chindings, log: log31 } = options2.formatters;
6892
6892
  instance[formattersSym] = buildFormatters(
6893
6893
  level || formatters.level,
6894
6894
  chindings || resetChildingsFormatter,
6895
- log29 || formatters.log
6895
+ log31 || formatters.log
6896
6896
  );
6897
6897
  } else {
6898
6898
  instance[formattersSym] = buildFormatters(
@@ -86574,11 +86574,11 @@ var require_core = __commonJS({
86574
86574
  Ajv2.ValidationError = validation_error_1.default;
86575
86575
  Ajv2.MissingRefError = ref_error_1.default;
86576
86576
  exports.default = Ajv2;
86577
- function checkOptions(checkOpts, options2, msg, log29 = "error") {
86577
+ function checkOptions(checkOpts, options2, msg, log31 = "error") {
86578
86578
  for (const key in checkOpts) {
86579
86579
  const opt = key;
86580
86580
  if (opt in options2)
86581
- this.logger[log29](`${msg}: option ${key}. ${checkOpts[opt]}`);
86581
+ this.logger[log31](`${msg}: option ${key}. ${checkOpts[opt]}`);
86582
86582
  }
86583
86583
  }
86584
86584
  function getSchEnv(keyRef) {
@@ -106688,6 +106688,9 @@ var import_react15 = __toESM(require_react(), 1);
106688
106688
  // src/dashboard/hooks/use-label-filter.ts
106689
106689
  var import_react16 = __toESM(require_react(), 1);
106690
106690
 
106691
+ // src/dashboard/hooks/use-projects.ts
106692
+ var EMPTY_PROJECTS = Object.freeze([]);
106693
+
106691
106694
  // src/dashboard/hooks/use-status.ts
106692
106695
  var import_react17 = __toESM(require_react(), 1);
106693
106696
 
@@ -106849,6 +106852,11 @@ var WorkspaceCard = (0, import_react20.memo)(function WorkspaceCard2({
106849
106852
  // "currently-active link in a list of related links".
106850
106853
  "data-active": isActive || void 0,
106851
106854
  "aria-current": isActive ? "page" : void 0,
106855
+ // Stable test hook keyed by workspaceId so integration tests can right-
106856
+ // click the specific card (issue #508). Branches with `/` in them are
106857
+ // collapsed to `-` by `toWorkspaceId` so the attribute value matches
106858
+ // the canonical workspace id used everywhere else in the UI.
106859
+ "data-testid": `project-list__workspace-card--${workspaceId}`,
106852
106860
  onClick: (e2) => {
106853
106861
  e2.stopPropagation();
106854
106862
  handleClick();
@@ -116453,7 +116461,15 @@ var projects = sqliteTable("projects", {
116453
116461
  // branches, PR/CI features) and plain folders (single implicit workspace,
116454
116462
  // no isolation, git features disabled). Defaults to "git" so existing
116455
116463
  // rows keep their behavior unchanged after migration.
116456
- kind: text2("kind", { enum: ["git", "plain"] }).notNull().default("git")
116464
+ kind: text2("kind", { enum: ["git", "plain"] }).notNull().default("git"),
116465
+ // Whether the project's git repo has an `origin` remote we can use for
116466
+ // CI / PR queries. Populated by `syncWorktrees` (see `sync-state.ts`) at
116467
+ // the CI tick cadence — `null` means "not yet probed" and is treated as
116468
+ // `true` (best-effort) so the first poll after a fresh boot still issues
116469
+ // the CI query before sync has had a chance to write the real value.
116470
+ // Defaults to 1 (true) so existing rows behave the same after migration.
116471
+ // See issue #458.
116472
+ hasOrigin: integer2("has_origin", { mode: "boolean" }).notNull().default(true)
116457
116473
  });
116458
116474
  var worktrees = sqliteTable("worktrees", {
116459
116475
  id: integer2("id").primaryKey({ autoIncrement: true }),
@@ -116589,10 +116605,15 @@ function loadState() {
116589
116605
  defaultBranch: row.defaultBranch,
116590
116606
  label: row.label ?? void 0,
116591
116607
  kind: row.kind ?? "git",
116608
+ hasOrigin: row.hasOrigin,
116592
116609
  worktrees: wtByProject.get(row.name) ?? []
116593
116610
  }))
116594
116611
  };
116595
116612
  }
116613
+ function setProjectHasOrigin(name3, hasOrigin) {
116614
+ const db2 = getDb();
116615
+ db2.update(projects).set({ hasOrigin }).where(eq2(projects.name, name3)).run();
116616
+ }
116596
116617
  function saveState(state2) {
116597
116618
  const db2 = getDb();
116598
116619
  db2.transaction((tx) => {
@@ -116606,7 +116627,11 @@ function saveState(state2) {
116606
116627
  defaultBranch: project.defaultBranch,
116607
116628
  label: project.label ?? null,
116608
116629
  sortOrder: i2,
116609
- kind: project.kind
116630
+ kind: project.kind,
116631
+ // Default to true for any caller that hasn't probed yet (e.g.
116632
+ // `projects.add` creating a brand-new row before the first
116633
+ // sync tick has run). The real value lands at the next sync.
116634
+ hasOrigin: project.hasOrigin ?? true
116610
116635
  }).run();
116611
116636
  for (const wt of project.worktrees) {
116612
116637
  tx.insert(worktrees).values({
@@ -116870,9 +116895,9 @@ async function getOrCreateAgent(chatId, worktreePath, agentId) {
116870
116895
  return existing.agent;
116871
116896
  }
116872
116897
  const defId = resolveAgentDefId(agentId);
116873
- const inFlight = pending.get(chatId);
116874
- if (inFlight && inFlight.agentDefId === defId) {
116875
- return inFlight.promise;
116898
+ const inFlight2 = pending.get(chatId);
116899
+ if (inFlight2 && inFlight2.agentDefId === defId) {
116900
+ return inFlight2.promise;
116876
116901
  }
116877
116902
  const config2 = getAgentConfig(worktreePath, agentId);
116878
116903
  log8.info({ chatId, type: config2.type, defId, cwd: worktreePath }, "creating agent");
@@ -117166,15 +117191,30 @@ function removeChatFromLayout(workspaceId, chatId) {
117166
117191
  manager.removePanel(workspaceId, chatId);
117167
117192
  }
117168
117193
 
117194
+ // src/lib/branch-status-poller.ts
117195
+ init_src();
117196
+
117169
117197
  // src/lib/git.ts
117198
+ init_src();
117170
117199
  import { execFile as execFile2 } from "node:child_process";
117171
117200
  import { readFile, stat as stat3 } from "node:fs/promises";
117172
117201
  import { join as join13 } from "node:path";
117202
+ var log9 = createLogger("git");
117173
117203
  function parseGitRemoteUrl(url) {
117174
117204
  const sshMatch = url.match(/^[\w.-]+@([^:]+):([^/]+)\/(.+?)(?:\.git)?$/);
117175
117205
  if (sshMatch) {
117176
117206
  return { host: sshMatch[1], owner: sshMatch[2], repo: sshMatch[3] };
117177
117207
  }
117208
+ const sshSchemeMatch = url.match(
117209
+ /^ssh:\/\/(?:[\w.-]+@)?([^/:]+)(?::\d+)?\/([^/]+)\/(.+?)(?:\.git)?$/
117210
+ );
117211
+ if (sshSchemeMatch) {
117212
+ return {
117213
+ host: sshSchemeMatch[1],
117214
+ owner: sshSchemeMatch[2],
117215
+ repo: sshSchemeMatch[3]
117216
+ };
117217
+ }
117178
117218
  const httpsMatch = url.match(/^https?:\/\/([^/]+)\/([^/]+)\/(.+?)(?:\.git)?$/);
117179
117219
  if (httpsMatch) {
117180
117220
  return { host: httpsMatch[1], owner: httpsMatch[2], repo: httpsMatch[3] };
@@ -117186,13 +117226,14 @@ async function getRepoInfo(worktreePath) {
117186
117226
  const remoteUrl = (await execGit(["remote", "get-url", "origin"], worktreePath)).trim();
117187
117227
  const parsed = parseGitRemoteUrl(remoteUrl);
117188
117228
  if (!parsed) {
117189
- console.error(`getRepoInfo: failed to parse remote URL "${remoteUrl}" for ${worktreePath}`);
117229
+ log9.debug('getRepoInfo: failed to parse remote URL "%s" for %s', remoteUrl, worktreePath);
117190
117230
  }
117191
117231
  return parsed;
117192
117232
  } catch (err) {
117193
- console.error(
117194
- `getRepoInfo: failed for ${worktreePath}:`,
117195
- err instanceof Error ? err.message : err
117233
+ log9.debug(
117234
+ "getRepoInfo: failed for %s: %s",
117235
+ worktreePath,
117236
+ err instanceof Error ? err.message : String(err)
117196
117237
  );
117197
117238
  return null;
117198
117239
  }
@@ -117479,6 +117520,10 @@ async function reconcileOneProject(project) {
117479
117520
  pinned: pinnedByBranch.get(wt.branch) ?? false
117480
117521
  }));
117481
117522
  } catch {
117523
+ if (project.hasOrigin) {
117524
+ setProjectHasOrigin(project.name, false);
117525
+ project.hasOrigin = false;
117526
+ }
117482
117527
  return false;
117483
117528
  }
117484
117529
  const existingSet = new Set(project.worktrees.map((wt) => `${wt.branch}\0${wt.path}`));
@@ -117492,10 +117537,19 @@ async function reconcileOneProject(project) {
117492
117537
  project.defaultBranch = remoteBranch;
117493
117538
  mutated = true;
117494
117539
  }
117540
+ const hasOrigin = await getRepoInfo(project.path) !== null;
117541
+ if (hasOrigin !== project.hasOrigin) {
117542
+ try {
117543
+ setProjectHasOrigin(project.name, hasOrigin);
117544
+ project.hasOrigin = hasOrigin;
117545
+ } catch {
117546
+ }
117547
+ }
117495
117548
  return mutated;
117496
117549
  }
117497
117550
 
117498
117551
  // src/lib/branch-status-poller.ts
117552
+ var log10 = createLogger("branch-status-poller");
117499
117553
  var INTERVALS = {
117500
117554
  // 5 s git / 30 s CI — the original cadence, used when the user is actively looking at the UI on AC power.
117501
117555
  active: { pollMs: 5e3, ciTicks: 6 },
@@ -117507,7 +117561,6 @@ var INTERVALS = {
117507
117561
  var pollerTimer = null;
117508
117562
  var tickCount = 0;
117509
117563
  var currentActivity = "active";
117510
- var repoInfoCache = /* @__PURE__ */ new Map();
117511
117564
  function getWorkspaces() {
117512
117565
  const state2 = loadState();
117513
117566
  const workspaces = [];
@@ -117520,7 +117573,8 @@ function getWorkspaces() {
117520
117573
  branch: wt.branch,
117521
117574
  defaultBranch: project.defaultBranch,
117522
117575
  worktreePath: wt.path,
117523
- projectPath: project.path
117576
+ projectPath: project.path,
117577
+ hasOrigin: project.hasOrigin
117524
117578
  });
117525
117579
  }
117526
117580
  }
@@ -117571,30 +117625,29 @@ async function getGitStatus(worktreePath) {
117571
117625
  }
117572
117626
  return status;
117573
117627
  }
117574
- async function resolveRepoInfo(projectPath) {
117575
- const cached2 = repoInfoCache.get(projectPath);
117576
- if (cached2 !== void 0) return cached2;
117577
- const info = await getRepoInfo(projectPath);
117578
- if (info) {
117579
- repoInfoCache.set(projectPath, info);
117580
- }
117581
- return info;
117582
- }
117583
117628
  async function getBatchedCIStatuses(workspaces) {
117584
- repoInfoCache.clear();
117585
- const resolved = [];
117586
- await Promise.allSettled(
117587
- workspaces.map(async (ws, index3) => {
117588
- const repoInfo = await resolveRepoInfo(ws.projectPath);
117589
- if (repoInfo) {
117590
- resolved.push({ ws, repoInfo, alias: `ws_${index3}` });
117591
- } else {
117592
- console.error(
117593
- `CI poll: failed to resolve repo info for ${ws.workspaceId} (${ws.projectPath})`
117594
- );
117595
- }
117629
+ const uniqueProjectPaths = [...new Set(workspaces.map((ws) => ws.projectPath))];
117630
+ const repoInfoByPath = /* @__PURE__ */ new Map();
117631
+ await Promise.all(
117632
+ uniqueProjectPaths.map(async (path3) => {
117633
+ repoInfoByPath.set(path3, await getRepoInfo(path3));
117596
117634
  })
117597
117635
  );
117636
+ for (const path3 of uniqueProjectPaths) {
117637
+ if (repoInfoByPath.get(path3) === null) {
117638
+ log10.warn(
117639
+ "CI poll: getRepoInfo returned null for %s despite hasOrigin=true; will reconcile on next sync tick",
117640
+ path3
117641
+ );
117642
+ }
117643
+ }
117644
+ const resolved = [];
117645
+ for (const [index3, ws] of workspaces.entries()) {
117646
+ const repoInfo = repoInfoByPath.get(ws.projectPath);
117647
+ if (repoInfo) {
117648
+ resolved.push({ ws, repoInfo, alias: `ws_${index3}` });
117649
+ }
117650
+ }
117598
117651
  if (resolved.length === 0) {
117599
117652
  const results = /* @__PURE__ */ new Map();
117600
117653
  for (const ws of workspaces) {
@@ -117676,7 +117729,10 @@ async function pollTick() {
117676
117729
  const db2 = getDb();
117677
117730
  let ciStatuses = /* @__PURE__ */ new Map();
117678
117731
  if (isCITick) {
117679
- ciStatuses = await getBatchedCIStatuses(workspaces);
117732
+ const ciWorkspaces = workspaces.filter((w2) => w2.hasOrigin);
117733
+ if (ciWorkspaces.length > 0) {
117734
+ ciStatuses = await getBatchedCIStatuses(ciWorkspaces);
117735
+ }
117680
117736
  }
117681
117737
  await Promise.allSettled(
117682
117738
  workspaces.map(async (ws) => {
@@ -117880,7 +117936,7 @@ function subscribe(listener) {
117880
117936
  }
117881
117937
 
117882
117938
  // src/lib/chat-manager.ts
117883
- var log9 = createLogger("chat-manager");
117939
+ var log11 = createLogger("chat-manager");
117884
117940
  var PANEL_TYPE = "chat";
117885
117941
  var chatSessions = /* @__PURE__ */ new Map();
117886
117942
  var workspaceChats = /* @__PURE__ */ new Map();
@@ -117951,7 +118007,7 @@ function createChat(workspaceId, options2) {
117951
118007
  addToIndex(session);
117952
118008
  addChatToLayout(workspaceId, session.id, { title: session.name });
117953
118009
  emit({ kind: "chat-created", workspaceId, chatId: session.id });
117954
- log9.info({ chatId: session.id, workspaceId, agent: session.agent }, "chat pane created");
118010
+ log11.info({ chatId: session.id, workspaceId, agent: session.agent }, "chat pane created");
117955
118011
  return session;
117956
118012
  }
117957
118013
  function getChat(chatId) {
@@ -117980,7 +118036,7 @@ function updateChat(chatId, updates) {
117980
118036
  state: serializeState(session),
117981
118037
  updatedAt: Date.now()
117982
118038
  });
117983
- log9.info({ chatId, updates }, "chat pane updated");
118039
+ log11.info({ chatId, updates }, "chat pane updated");
117984
118040
  return session;
117985
118041
  }
117986
118042
  function updateChatStatus(chatId, status) {
@@ -118032,7 +118088,7 @@ function removeChat(chatId) {
118032
118088
  removeChatFromLayout(session.workspaceId, chatId);
118033
118089
  removeFromIndex(chatId);
118034
118090
  emit({ kind: "chat-removed", workspaceId: session.workspaceId, chatId });
118035
- log9.info({ chatId, workspaceId: session.workspaceId }, "chat pane removed");
118091
+ log11.info({ chatId, workspaceId: session.workspaceId }, "chat pane removed");
118036
118092
  return true;
118037
118093
  }
118038
118094
  function removeWorkspaceChats(workspaceId) {
@@ -118044,7 +118100,7 @@ function removeWorkspaceChats(workspaceId) {
118044
118100
  }
118045
118101
  deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE);
118046
118102
  workspaceChats.delete(workspaceId);
118047
- log9.info({ workspaceId }, "all chat panes removed for workspace");
118103
+ log11.info({ workspaceId }, "all chat panes removed for workspace");
118048
118104
  }
118049
118105
  function loadChatsFromDb() {
118050
118106
  _initialized = true;
@@ -118072,7 +118128,7 @@ function loadChatsFromDb() {
118072
118128
  addToIndex(session);
118073
118129
  }
118074
118130
  if (rows.length > 0) {
118075
- log9.info({ count: rows.length }, "loaded chat panes from database");
118131
+ log11.info({ count: rows.length }, "loaded chat panes from database");
118076
118132
  }
118077
118133
  return rows.length;
118078
118134
  }
@@ -118090,6 +118146,67 @@ function getOrCreateDefaultChat(workspaceId) {
118090
118146
  return createChat(workspaceId, { name: "Chat" });
118091
118147
  }
118092
118148
 
118149
+ // src/lib/jsonl-message-to-events.ts
118150
+ function stripFileSharingHint(text3) {
118151
+ return text3.replace(/\n\n\[File sharing:[\s\S]*?\]\s*$/, "");
118152
+ }
118153
+ function jsonlMessageToEvents(msg, startId) {
118154
+ const events = [];
118155
+ let id = startId;
118156
+ if (msg.role === "user") {
118157
+ let textBuf = "";
118158
+ let hasText = false;
118159
+ for (const part of msg.content) {
118160
+ if (part.type === "text") {
118161
+ hasText = true;
118162
+ textBuf += part.text;
118163
+ } else if (part.type === "tool_result") {
118164
+ events.push({
118165
+ type: "tool-output-available",
118166
+ toolCallId: part.toolCallId,
118167
+ output: part.output,
118168
+ isError: part.isError,
118169
+ eventId: id++
118170
+ });
118171
+ }
118172
+ }
118173
+ if (hasText) {
118174
+ events.push({
118175
+ type: "user-message",
118176
+ text: stripFileSharingHint(textBuf),
118177
+ eventId: id++
118178
+ });
118179
+ }
118180
+ return events;
118181
+ }
118182
+ for (const part of msg.content) {
118183
+ if (part.type === "text") {
118184
+ const textPartId = `${msg.id}-text-${id}`;
118185
+ events.push({ type: "text-start", id: textPartId, eventId: id++ });
118186
+ events.push({ type: "text-delta", id: textPartId, delta: part.text, eventId: id++ });
118187
+ events.push({ type: "text-end", id: textPartId, eventId: id++ });
118188
+ } else if (part.type === "tool_use") {
118189
+ events.push({
118190
+ type: "tool-input-available",
118191
+ toolCallId: part.toolCallId,
118192
+ toolName: part.toolName,
118193
+ displayTitle: part.displayTitle,
118194
+ input: part.input,
118195
+ eventId: id++
118196
+ });
118197
+ } else if (part.type === "tool_result") {
118198
+ events.push({
118199
+ type: "tool-output-available",
118200
+ toolCallId: part.toolCallId,
118201
+ output: part.output,
118202
+ isError: part.isError,
118203
+ eventId: id++
118204
+ });
118205
+ }
118206
+ }
118207
+ return events;
118208
+ }
118209
+
118093
118210
  // src/lib/queued-message-store.ts
118094
118211
  import { randomUUID } from "node:crypto";
118095
118212
  function toWireQueuedMessages(messages) {
@@ -118265,7 +118382,7 @@ function hasPendingInputForWorkspace(workspaceId) {
118265
118382
 
118266
118383
  // src/lib/task-store.ts
118267
118384
  init_src();
118268
- var log10 = createLogger("task-store");
118385
+ var log12 = createLogger("task-store");
118269
118386
  function generateTaskId() {
118270
118387
  return `tsk_${Date.now()}`;
118271
118388
  }
@@ -118338,7 +118455,7 @@ function cleanupStaleTasks() {
118338
118455
  const result = db2.update(tasks).set({ status: "failed", completedAt: now }).where(eq2(tasks.status, "running")).run();
118339
118456
  const count3 = result.changes;
118340
118457
  if (count3 > 0) {
118341
- log10.info({ count: count3 }, "cleaned up stale tasks on startup");
118458
+ log12.info({ count: count3 }, "cleaned up stale tasks on startup");
118342
118459
  }
118343
118460
  return count3;
118344
118461
  }
@@ -118375,7 +118492,7 @@ function pruneOldTasks(retentionMs = TASK_RETENTION_MS) {
118375
118492
  const cutoff = Date.now() - retentionMs;
118376
118493
  const count3 = deleteTasksOlderThan(cutoff);
118377
118494
  if (count3 > 0) {
118378
- log10.info({ count: count3, retentionMs }, "pruned tasks older than retention window");
118495
+ log12.info({ count: count3, retentionMs }, "pruned tasks older than retention window");
118379
118496
  }
118380
118497
  return count3;
118381
118498
  }
@@ -118386,13 +118503,13 @@ function startTaskPruneScheduler(options2 = {}) {
118386
118503
  try {
118387
118504
  pruneOldTasks(retentionMs);
118388
118505
  } catch (err) {
118389
- log10.error({ err }, "initial task prune on boot failed");
118506
+ log12.error({ err }, "initial task prune on boot failed");
118390
118507
  }
118391
118508
  const timer = setInterval(() => {
118392
118509
  try {
118393
118510
  pruneOldTasks(retentionMs);
118394
118511
  } catch (err) {
118395
- log10.error({ err }, "scheduled task prune failed");
118512
+ log12.error({ err }, "scheduled task prune failed");
118396
118513
  }
118397
118514
  }, intervalMs);
118398
118515
  timer.unref();
@@ -118447,7 +118564,7 @@ function resolveWorkspace(workspaceId) {
118447
118564
  }
118448
118565
 
118449
118566
  // src/lib/task-runner.ts
118450
- var log11 = createLogger("task-runner");
118567
+ var log13 = createLogger("task-runner");
118451
118568
  function listFiles(dir) {
118452
118569
  try {
118453
118570
  return new Set(readdirSync6(dir));
@@ -118506,7 +118623,7 @@ function persistTask(task) {
118506
118623
  chatId: task.chatId
118507
118624
  });
118508
118625
  } catch (err) {
118509
- log11.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
118626
+ log13.warn({ err, taskId: task.taskRecordId }, "failed to persist task");
118510
118627
  }
118511
118628
  }
118512
118629
  function broadcast(chatId, chunk) {
@@ -118530,7 +118647,7 @@ function broadcast(chatId, chunk) {
118530
118647
  }
118531
118648
  const subs = listeners2.get(chatId);
118532
118649
  if (!subs || subs.size === 0) {
118533
- log11.warn({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
118650
+ log13.warn({ chatId, chunkType: chunk.type }, "broadcast: no listeners");
118534
118651
  return;
118535
118652
  }
118536
118653
  for (const listener of subs) {
@@ -118596,7 +118713,7 @@ function submitTask(options2) {
118596
118713
  });
118597
118714
  }
118598
118715
  runTask(chatId, task).catch((err) => {
118599
- log11.error({ chatId, err }, "task execution failed");
118716
+ log13.error({ chatId, err }, "task execution failed");
118600
118717
  if (task.status === "running") {
118601
118718
  task.status = "failed";
118602
118719
  task.completedAt = Date.now();
@@ -118638,7 +118755,7 @@ function abortTask(chatId) {
118638
118755
  updateChatStatus(chatId, "idle");
118639
118756
  const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
118640
118757
  emit({ kind: "update", status: updated });
118641
- log11.info({ chatId }, "task aborted by user");
118758
+ log13.info({ chatId }, "task aborted by user");
118642
118759
  return true;
118643
118760
  }
118644
118761
  function cancelTask(taskId) {
@@ -118663,7 +118780,7 @@ function cancelTask(taskId) {
118663
118780
  updateChatStatus(chatId, "idle");
118664
118781
  const updated = upsertWorkspaceStatus(task.workspaceId, { status: "waiting" });
118665
118782
  emit({ kind: "update", status: updated });
118666
- log11.info({ chatId, taskId }, "task cancelled (was running in-memory)");
118783
+ log13.info({ chatId, taskId }, "task cancelled (was running in-memory)");
118667
118784
  return { cancelled: true, workspaceId: task.workspaceId };
118668
118785
  }
118669
118786
  }
@@ -118671,7 +118788,7 @@ function cancelTask(taskId) {
118671
118788
  if (record2) {
118672
118789
  const updated = upsertWorkspaceStatus(record2.workspaceId, { status: "waiting" });
118673
118790
  emit({ kind: "update", status: updated });
118674
- log11.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
118791
+ log13.info({ taskId, workspaceId: record2.workspaceId }, "orphaned task cancelled");
118675
118792
  return { cancelled: true, workspaceId: record2.workspaceId };
118676
118793
  }
118677
118794
  return { cancelled: false };
@@ -118691,7 +118808,7 @@ async function runTask(chatId, task) {
118691
118808
  const taskAgentId = task.codingAgentId;
118692
118809
  const resolvedAgentId = taskAgentId ?? chatSession?.agent;
118693
118810
  const needsReplace = taskAgentId && taskAgentId !== chatSession?.agent;
118694
- log11.info(
118811
+ log13.info(
118695
118812
  { chatId, taskAgentId, chatAgent: chatSession?.agent, resolvedAgentId, needsReplace },
118696
118813
  "resolving agent for task"
118697
118814
  );
@@ -118740,7 +118857,7 @@ async function runTask(chatId, task) {
118740
118857
  [File sharing: to send a file to the user, write or copy it to ${sharedDir}/ and it will appear as a downloadable file card in the chat.]`;
118741
118858
  const effectivePrompt = task.sessionId ? task.agentPrompt : task.agentPrompt + fileSharingHint;
118742
118859
  for await (const event of agent.runSession(effectivePrompt, task.sessionId, sessionOptions)) {
118743
- log11.info({ chatId, eventType: event.type }, "task event");
118860
+ log13.info({ chatId, eventType: event.type }, "task event");
118744
118861
  switch (event.type) {
118745
118862
  case "session-start": {
118746
118863
  task.sessionId = event.sessionId;
@@ -118940,7 +119057,7 @@ async function runTask(chatId, task) {
118940
119057
  break;
118941
119058
  }
118942
119059
  case "session-id-resolved": {
118943
- log11.info(
119060
+ log13.info(
118944
119061
  { chatId, previous: event.previousSessionId, resolved: event.resolvedSessionId },
118945
119062
  "session ID resolved"
118946
119063
  );
@@ -119035,7 +119152,7 @@ ${queued.text}`;
119035
119152
  });
119036
119153
  autoStarted = true;
119037
119154
  } catch (err) {
119038
- log11.warn({ chatId, err }, "failed to auto-start queued task");
119155
+ log13.warn({ chatId, err }, "failed to auto-start queued task");
119039
119156
  }
119040
119157
  }
119041
119158
  }
@@ -119188,7 +119305,7 @@ function openSseStream(res) {
119188
119305
  }
119189
119306
 
119190
119307
  // src/api/chat-events.ts
119191
- var log12 = createLogger("chat-events");
119308
+ var log14 = createLogger("chat-events");
119192
119309
  async function handleChatEvents(req, res, chatId) {
119193
119310
  const url = new URL(req.url, `http://${req.headers.host}`);
119194
119311
  const lastEventIdHeader = req.headers["last-event-id"];
@@ -119268,7 +119385,7 @@ async function handleChatEvents(req, res, chatId) {
119268
119385
  chatWorkspaceId: chat?.workspaceId ?? explicitWorkspaceId,
119269
119386
  agentTypeHint: chat?.agent
119270
119387
  }).catch((err) => {
119271
- log12.warn({ chatId, err }, "replay phase failed; continuing to live tail");
119388
+ log14.warn({ chatId, err }, "replay phase failed; continuing to live tail");
119272
119389
  });
119273
119390
  try {
119274
119391
  while (!res.destroyed && !writer.closed) {
@@ -119327,7 +119444,7 @@ async function replayPast(opts) {
119327
119444
  }
119328
119445
  }
119329
119446
  } catch (err) {
119330
- log12.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
119447
+ log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
119331
119448
  }
119332
119449
  }
119333
119450
  if (!jsonlEmittedAny && buf) {
@@ -119361,7 +119478,7 @@ async function replayPast(opts) {
119361
119478
  }
119362
119479
  }
119363
119480
  } catch (err) {
119364
- log12.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
119481
+ log14.warn({ chatId, sessionId, err }, "JSONL backfill failed; falling through to buffer");
119365
119482
  }
119366
119483
  }
119367
119484
  if (buf) {
@@ -119374,50 +119491,6 @@ async function replayPast(opts) {
119374
119491
  }
119375
119492
  }
119376
119493
  }
119377
- function stripFileSharingHint(text3) {
119378
- return text3.replace(/\n\n\[File sharing:[\s\S]*?\]\s*$/, "");
119379
- }
119380
- function jsonlMessageToEvents(msg, startId) {
119381
- const events = [];
119382
- let id = startId;
119383
- if (msg.role === "user") {
119384
- const textPart = msg.content.find(
119385
- (p6) => p6.type === "text"
119386
- );
119387
- events.push({
119388
- type: "user-message",
119389
- text: stripFileSharingHint(textPart?.text ?? ""),
119390
- eventId: id++
119391
- });
119392
- return events;
119393
- }
119394
- for (const part of msg.content) {
119395
- if (part.type === "text") {
119396
- const textPartId = `${msg.id}-text-${id}`;
119397
- events.push({ type: "text-start", id: textPartId, eventId: id++ });
119398
- events.push({ type: "text-delta", id: textPartId, delta: part.text, eventId: id++ });
119399
- events.push({ type: "text-end", id: textPartId, eventId: id++ });
119400
- } else if (part.type === "tool_use") {
119401
- events.push({
119402
- type: "tool-input-available",
119403
- toolCallId: part.toolCallId,
119404
- toolName: part.toolName,
119405
- displayTitle: part.displayTitle,
119406
- input: part.input,
119407
- eventId: id++
119408
- });
119409
- } else if (part.type === "tool_result") {
119410
- events.push({
119411
- type: "tool-output-available",
119412
- toolCallId: part.toolCallId,
119413
- output: part.output,
119414
- isError: part.isError,
119415
- eventId: id++
119416
- });
119417
- }
119418
- }
119419
- return events;
119420
- }
119421
119494
  function chunkToChatEvent(chunk, _sessionId) {
119422
119495
  const c2 = chunk;
119423
119496
  switch (c2.type) {
@@ -119547,7 +119620,7 @@ async function saveUploadedFiles(fileParts) {
119547
119620
  }
119548
119621
 
119549
119622
  // src/api/chat-submit.ts
119550
- var log13 = createLogger("chat-submit");
119623
+ var log15 = createLogger("chat-submit");
119551
119624
  function readBody(req) {
119552
119625
  return new Promise((resolve7, reject) => {
119553
119626
  const chunks = [];
@@ -119584,7 +119657,7 @@ async function handleChatSubmit(req, res, chatId) {
119584
119657
  if (files && files.length > 0) {
119585
119658
  savedFiles = await saveUploadedFilesDetailed(files);
119586
119659
  if (savedFiles.length !== files.length) {
119587
- log13.warn(
119660
+ log15.warn(
119588
119661
  { chatId, submitted: files.length, saved: savedFiles.length },
119589
119662
  "chat-submit: some file uploads were dropped (malformed data URL?)"
119590
119663
  );
@@ -119615,7 +119688,7 @@ ${text3}`;
119615
119688
  model,
119616
119689
  codingAgentId
119617
119690
  });
119618
- log13.info({ chatId, workspaceId }, "chat-submit: task started");
119691
+ log15.info({ chatId, workspaceId }, "chat-submit: task started");
119619
119692
  sendJson(res, 200, { ok: true, queued: false });
119620
119693
  } catch (err) {
119621
119694
  if (err instanceof TaskConflictError) {
@@ -119630,7 +119703,7 @@ ${text3}`;
119630
119703
  }))
119631
119704
  }
119632
119705
  });
119633
- log13.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
119706
+ log15.info({ chatId, workspaceId }, "chat-submit: task busy, message queued");
119634
119707
  sendJson(res, 200, { ok: true, queued: true });
119635
119708
  return;
119636
119709
  }
@@ -119638,7 +119711,7 @@ ${text3}`;
119638
119711
  sendJson(res, 404, { error: err.message });
119639
119712
  return;
119640
119713
  }
119641
- log13.error({ chatId, err }, "chat-submit: unexpected error");
119714
+ log15.error({ chatId, err }, "chat-submit: unexpected error");
119642
119715
  sendJson(res, 500, { error: "Internal server error" });
119643
119716
  }
119644
119717
  }
@@ -119672,7 +119745,7 @@ function removeBrowserFromLayout(workspaceId, browserId) {
119672
119745
  }
119673
119746
 
119674
119747
  // src/lib/browser-manager.ts
119675
- var log14 = createLogger("browser-manager");
119748
+ var log16 = createLogger("browser-manager");
119676
119749
  var PANEL_TYPE2 = "browser";
119677
119750
  var browserTabs = /* @__PURE__ */ new Map();
119678
119751
  var workspaceBrowsers = /* @__PURE__ */ new Map();
@@ -119733,7 +119806,7 @@ function createBrowser(workspaceId, options2) {
119733
119806
  title: tab.name,
119734
119807
  initialUrl: tab.url || void 0
119735
119808
  });
119736
- log14.info({ browserId: tab.id, workspaceId, url: tab.url }, "browser tab created");
119809
+ log16.info({ browserId: tab.id, workspaceId, url: tab.url }, "browser tab created");
119737
119810
  return tab;
119738
119811
  }
119739
119812
  function getBrowser(browserId) {
@@ -119760,7 +119833,7 @@ function updateBrowser(browserId, updates) {
119760
119833
  state: serializeState2(tab),
119761
119834
  updatedAt: Date.now()
119762
119835
  });
119763
- log14.info({ browserId, updates }, "browser tab updated");
119836
+ log16.info({ browserId, updates }, "browser tab updated");
119764
119837
  return tab;
119765
119838
  }
119766
119839
  function updateBrowserUrl(browserId, url) {
@@ -119777,7 +119850,7 @@ function removeBrowser(browserId) {
119777
119850
  if (!tab) return false;
119778
119851
  deletePanelState(browserId);
119779
119852
  removeFromIndex2(browserId);
119780
- log14.info({ browserId, workspaceId: tab.workspaceId }, "browser tab removed");
119853
+ log16.info({ browserId, workspaceId: tab.workspaceId }, "browser tab removed");
119781
119854
  return true;
119782
119855
  }
119783
119856
  function removeWorkspaceBrowsers(workspaceId) {
@@ -119788,7 +119861,7 @@ function removeWorkspaceBrowsers(workspaceId) {
119788
119861
  }
119789
119862
  deletePanelStatesForWorkspace(workspaceId, PANEL_TYPE2);
119790
119863
  workspaceBrowsers.delete(workspaceId);
119791
- log14.info({ workspaceId }, "all browser tabs removed for workspace");
119864
+ log16.info({ workspaceId }, "all browser tabs removed for workspace");
119792
119865
  }
119793
119866
  function loadBrowsersFromDb() {
119794
119867
  _initialized2 = true;
@@ -119807,13 +119880,13 @@ function loadBrowsersFromDb() {
119807
119880
  addToIndex2(tab);
119808
119881
  }
119809
119882
  if (rows.length > 0) {
119810
- log14.info({ count: rows.length }, "loaded browser tabs from database");
119883
+ log16.info({ count: rows.length }, "loaded browser tabs from database");
119811
119884
  }
119812
119885
  return rows.length;
119813
119886
  }
119814
119887
 
119815
119888
  // src/lib/browser-host.ts
119816
- var log15 = createLogger("browser-host");
119889
+ var log17 = createLogger("browser-host");
119817
119890
  var DESKTOP_CDP_HOST = "127.0.0.1";
119818
119891
  var DESKTOP_CDP_PORT = 9223;
119819
119892
  var globalAny = globalThis;
@@ -119864,7 +119937,7 @@ async function ensureCdpTargetId(bandTabId) {
119864
119937
  reject: rejectFn,
119865
119938
  timeoutId
119866
119939
  });
119867
- log15.info(
119940
+ log17.info(
119868
119941
  "ensureCdpTargetId emitting ensureView for %s (url=%s, listeners=%d)",
119869
119942
  bandTabId,
119870
119943
  tab.url,
@@ -119878,13 +119951,13 @@ async function ensureCdpTargetId(bandTabId) {
119878
119951
  url: tab.url
119879
119952
  });
119880
119953
  } catch (err) {
119881
- log15.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
119954
+ log17.warn("ensureView listener threw: %s", err instanceof Error ? err.message : err);
119882
119955
  }
119883
119956
  }
119884
119957
  return promise;
119885
119958
  }
119886
119959
  function resolveTargetReady(bandTabId, cdpTargetId) {
119887
- log15.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
119960
+ log17.info("resolveTargetReady %s \u2192 %s", bandTabId, cdpTargetId);
119888
119961
  targetIdByBandTabId.set(bandTabId, cdpTargetId);
119889
119962
  const pending2 = pendingEnsures.get(bandTabId);
119890
119963
  if (pending2) {
@@ -119894,7 +119967,7 @@ function resolveTargetReady(bandTabId, cdpTargetId) {
119894
119967
  }
119895
119968
  }
119896
119969
  function markTargetDestroyed(bandTabId) {
119897
- log15.info("markTargetDestroyed %s", bandTabId);
119970
+ log17.info("markTargetDestroyed %s", bandTabId);
119898
119971
  targetIdByBandTabId.delete(bandTabId);
119899
119972
  const pending2 = pendingEnsures.get(bandTabId);
119900
119973
  if (pending2) {
@@ -119905,10 +119978,10 @@ function markTargetDestroyed(bandTabId) {
119905
119978
  }
119906
119979
  function onEnsureView(listener) {
119907
119980
  ensureListeners.add(listener);
119908
- log15.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
119981
+ log17.info("onEnsureView subscriber added (total=%d)", ensureListeners.size);
119909
119982
  return () => {
119910
119983
  ensureListeners.delete(listener);
119911
- log15.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
119984
+ log17.info("onEnsureView subscriber removed (total=%d)", ensureListeners.size);
119912
119985
  if (ensureListeners.size === 0) {
119913
119986
  for (const [bandTabId, pending2] of pendingEnsures) {
119914
119987
  clearTimeout(pending2.timeoutId);
@@ -119925,7 +119998,7 @@ function isDesktopHostConnected() {
119925
119998
 
119926
119999
  // src/lib/cdp-proxy.ts
119927
120000
  init_src();
119928
- var log16 = createLogger("cdp-proxy");
120001
+ var log18 = createLogger("cdp-proxy");
119929
120002
  async function handleCdpConnection(ws, req) {
119930
120003
  const url = new URL(req.url ?? "", `http://${req.headers.host}`);
119931
120004
  const bandTabId = url.searchParams.get("bandTabId");
@@ -119948,17 +120021,17 @@ async function handleCdpConnection(ws, req) {
119948
120021
  cdpTargetId = await ensureCdpTargetId(bandTabId);
119949
120022
  } catch (err) {
119950
120023
  const message = err instanceof Error ? err.message : String(err);
119951
- log16.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
120024
+ log18.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
119952
120025
  if (ws.readyState === ws.OPEN) {
119953
120026
  ws.close(4001, message.slice(0, 123));
119954
120027
  }
119955
120028
  return;
119956
120029
  }
119957
120030
  const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
119958
- log16.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
120031
+ log18.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
119959
120032
  upstream = new wrapper_default(upstreamUrl);
119960
120033
  upstream.on("open", () => {
119961
- log16.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
120034
+ log18.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
119962
120035
  for (const msg of pending2) {
119963
120036
  upstream?.send(msg);
119964
120037
  }
@@ -119970,20 +120043,20 @@ async function handleCdpConnection(ws, req) {
119970
120043
  }
119971
120044
  });
119972
120045
  upstream.on("error", (err) => {
119973
- log16.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
120046
+ log18.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
119974
120047
  markTargetDestroyed(bandTabId);
119975
120048
  if (ws.readyState === ws.OPEN) {
119976
120049
  ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
119977
120050
  }
119978
120051
  });
119979
120052
  upstream.on("close", (code) => {
119980
- log16.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
120053
+ log18.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
119981
120054
  if (ws.readyState === ws.OPEN) {
119982
120055
  ws.close(1e3, "Upstream closed");
119983
120056
  }
119984
120057
  });
119985
120058
  ws.on("close", () => {
119986
- log16.debug("CDP client closed bandTabId=%s", bandTabId);
120059
+ log18.debug("CDP client closed bandTabId=%s", bandTabId);
119987
120060
  if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
119988
120061
  try {
119989
120062
  upstream.close();
@@ -119992,7 +120065,7 @@ async function handleCdpConnection(ws, req) {
119992
120065
  }
119993
120066
  });
119994
120067
  ws.on("error", (err) => {
119995
- log16.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
120068
+ log18.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
119996
120069
  try {
119997
120070
  upstream?.close();
119998
120071
  } catch {
@@ -120002,7 +120075,7 @@ async function handleCdpConnection(ws, req) {
120002
120075
 
120003
120076
  // src/lib/cdp-targets.ts
120004
120077
  init_src();
120005
- var log17 = createLogger("cdp-targets");
120078
+ var log19 = createLogger("cdp-targets");
120006
120079
  var CdpUnreachableError = class extends Error {
120007
120080
  constructor(message) {
120008
120081
  super(message);
@@ -120058,7 +120131,7 @@ async function captureSnapshot(bandTabId) {
120058
120131
  });
120059
120132
  ws.on("error", (err) => {
120060
120133
  clearTimeout(timeout);
120061
- log17.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
120134
+ log19.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
120062
120135
  markTargetDestroyed(bandTabId);
120063
120136
  settle(new CdpUnreachableError(err.message));
120064
120137
  });
@@ -120778,7 +120851,7 @@ function rowToDefinition(row) {
120778
120851
  }
120779
120852
 
120780
120853
  // src/lib/cronjob-scheduler.ts
120781
- var log18 = createLogger("cronjob-scheduler");
120854
+ var log20 = createLogger("cronjob-scheduler");
120782
120855
  var SCHEDULER_KEY = Symbol.for("band.cronjob-scheduler");
120783
120856
  var g14 = globalThis;
120784
120857
  if (!g14[SCHEDULER_KEY]) {
@@ -120798,16 +120871,16 @@ function scheduleJob(job, fileKey) {
120798
120871
  try {
120799
120872
  const cronInstance = new E2(job.cronExpression, () => {
120800
120873
  executeCronjob(job, fileKey).catch((err) => {
120801
- log18.error({ jobId: job.id, err }, "unhandled error in cronjob execution");
120874
+ log20.error({ jobId: job.id, err }, "unhandled error in cronjob execution");
120802
120875
  });
120803
120876
  });
120804
120877
  state.jobs.set(job.id, cronInstance);
120805
- log18.info(
120878
+ log20.info(
120806
120879
  { jobId: job.id, name: job.name, cron: job.cronExpression, scope: job.scope },
120807
120880
  "scheduled cronjob"
120808
120881
  );
120809
120882
  } catch (err) {
120810
- log18.error(
120883
+ log20.error(
120811
120884
  { jobId: job.id, cronExpression: job.cronExpression, err },
120812
120885
  "invalid cron expression, skipping job"
120813
120886
  );
@@ -120821,24 +120894,24 @@ async function executeCronjob(job, fileKey) {
120821
120894
  const appState = loadState();
120822
120895
  const project = appState.projects.find((p6) => p6.name === fileKey);
120823
120896
  if (!project) {
120824
- log18.warn({ jobId: job.id, fileKey }, "project not found for cronjob, skipping");
120897
+ log20.warn({ jobId: job.id, fileKey }, "project not found for cronjob, skipping");
120825
120898
  updateLastRun(job.id, "failed");
120826
120899
  return;
120827
120900
  }
120828
120901
  workspaceId = toWorkspaceId(project.name, project.defaultBranch);
120829
120902
  }
120830
- log18.info({ jobId: job.id, name: job.name, workspaceId }, "executing cronjob");
120903
+ log20.info({ jobId: job.id, name: job.name, workspaceId }, "executing cronjob");
120831
120904
  try {
120832
120905
  const chat = getOrCreateDefaultChat(workspaceId);
120833
120906
  submitTask({ workspaceId, chatId: chat.id, prompt: job.prompt });
120834
120907
  updateLastRun(job.id, "completed");
120835
120908
  } catch (err) {
120836
120909
  if (err instanceof TaskConflictError) {
120837
- log18.info({ jobId: job.id, workspaceId }, "task already running, skipping cronjob execution");
120910
+ log20.info({ jobId: job.id, workspaceId }, "task already running, skipping cronjob execution");
120838
120911
  updateLastRun(job.id, "skipped");
120839
120912
  return;
120840
120913
  }
120841
- log18.error({ jobId: job.id, err }, "cronjob execution failed");
120914
+ log20.error({ jobId: job.id, err }, "cronjob execution failed");
120842
120915
  updateLastRun(job.id, "failed");
120843
120916
  }
120844
120917
  }
@@ -120847,7 +120920,7 @@ function updateLastRun(jobId, status) {
120847
120920
  const db2 = getDb();
120848
120921
  db2.update(cronjobs).set({ lastRunAt: (/* @__PURE__ */ new Date()).toISOString(), lastRunStatus: status }).where(eq2(cronjobs.id, jobId)).run();
120849
120922
  } catch (err) {
120850
- log18.warn({ jobId, err }, "failed to update lastRun on cronjob");
120923
+ log20.warn({ jobId, err }, "failed to update lastRun on cronjob");
120851
120924
  }
120852
120925
  }
120853
120926
  function loadAndScheduleAll() {
@@ -120858,13 +120931,13 @@ function loadAndScheduleAll() {
120858
120931
  for (const job of listAllCronjobs()) {
120859
120932
  scheduleJob(job, job.fileKey);
120860
120933
  }
120861
- log18.info({ count: state.jobs.size }, "loaded cronjob schedules");
120934
+ log20.info({ count: state.jobs.size }, "loaded cronjob schedules");
120862
120935
  }
120863
120936
  function startCronjobScheduler() {
120864
120937
  if (state.started) return;
120865
120938
  state.started = true;
120866
120939
  loadAndScheduleAll();
120867
- log18.info("cronjob scheduler started");
120940
+ log20.info("cronjob scheduler started");
120868
120941
  }
120869
120942
  function stopCronjobScheduler() {
120870
120943
  for (const [, cron] of state.jobs) {
@@ -120872,7 +120945,7 @@ function stopCronjobScheduler() {
120872
120945
  }
120873
120946
  state.jobs.clear();
120874
120947
  state.started = false;
120875
- log18.info("cronjob scheduler stopped");
120948
+ log20.info("cronjob scheduler stopped");
120876
120949
  }
120877
120950
  function reloadSchedules() {
120878
120951
  if (!state.started) return;
@@ -120885,7 +120958,7 @@ function stopJobsForKey(key) {
120885
120958
  if (cron) {
120886
120959
  cron.stop();
120887
120960
  state.jobs.delete(job.id);
120888
- log18.info({ jobId: job.id, key }, "stopped cronjob");
120961
+ log20.info({ jobId: job.id, key }, "stopped cronjob");
120889
120962
  }
120890
120963
  }
120891
120964
  }
@@ -120951,7 +121024,7 @@ async function checkPrereqs() {
120951
121024
 
120952
121025
  // src/lib/lsp-manager.ts
120953
121026
  var __dirname2 = dirname2(fileURLToPath(import.meta.url));
120954
- var log19 = createLogger("lsp");
121027
+ var log21 = createLogger("lsp");
120955
121028
  var LANG_SERVER_CONFIG = {
120956
121029
  typescript: { command: "typescript-language-server", args: ["--stdio"] }
120957
121030
  };
@@ -120979,7 +121052,7 @@ async function getOrSpawnServer(workspaceId, lang) {
120979
121052
  const workspaceBin = join17(cwd, "node_modules/.bin");
120980
121053
  const pathSep = process.platform === "win32" ? ";" : ":";
120981
121054
  const combinedPath = [bundledBin, appBin, workspaceBin, resolvedPath].join(pathSep);
120982
- log19.debug("Spawning %s language server in %s for workspace %s", lang, cwd, workspaceId);
121055
+ log21.debug("Spawning %s language server in %s for workspace %s", lang, cwd, workspaceId);
120983
121056
  const child = spawn6(config2.command, config2.args, {
120984
121057
  cwd,
120985
121058
  stdio: ["pipe", "pipe", "pipe"],
@@ -121007,15 +121080,15 @@ async function getOrSpawnServer(workspaceId, lang) {
121007
121080
  }
121008
121081
  ids.add(serverId);
121009
121082
  child.on("exit", (code) => {
121010
- log19.debug("Language server exited: %s (code %s)", serverId, String(code));
121083
+ log21.debug("Language server exited: %s (code %s)", serverId, String(code));
121011
121084
  removeSession();
121012
121085
  });
121013
121086
  child.on("error", (err) => {
121014
- log19.error("Language server error: %s \u2014 %s", serverId, err.message);
121087
+ log21.error("Language server error: %s \u2014 %s", serverId, err.message);
121015
121088
  removeSession();
121016
121089
  });
121017
121090
  child.stderr?.on("data", (chunk) => {
121018
- log19.debug("LSP stderr [%s]: %s", serverId, chunk.toString().trimEnd());
121091
+ log21.debug("LSP stderr [%s]: %s", serverId, chunk.toString().trimEnd());
121019
121092
  });
121020
121093
  await new Promise((resolve7, reject) => {
121021
121094
  child.once("spawn", resolve7);
@@ -121045,7 +121118,7 @@ function killAllServers() {
121045
121118
 
121046
121119
  // src/lib/lsp-proxy.ts
121047
121120
  init_src();
121048
- var log20 = createLogger("lsp-proxy");
121121
+ var log22 = createLogger("lsp-proxy");
121049
121122
  function frameMessage(json2) {
121050
121123
  const body = Buffer.from(json2, "utf-8");
121051
121124
  const header = `Content-Length: ${body.byteLength}\r
@@ -121063,7 +121136,7 @@ function createFrameParser(onMessage) {
121063
121136
  const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
121064
121137
  const match = headerStr.match(/Content-Length:\s*(\d+)/i);
121065
121138
  if (!match) {
121066
- log20.warn("Malformed LSP header: %s", headerStr);
121139
+ log22.warn("Malformed LSP header: %s", headerStr);
121067
121140
  buffer = buffer.subarray(separatorIdx + 4);
121068
121141
  continue;
121069
121142
  }
@@ -121096,7 +121169,7 @@ async function handleLspConnection(ws, req) {
121096
121169
  session = await getOrSpawnServer(workspaceId, lang);
121097
121170
  } catch (err) {
121098
121171
  const message = err instanceof Error ? err.message : String(err);
121099
- log20.error(
121172
+ log22.error(
121100
121173
  "Failed to spawn %s language server for workspace %s: %s",
121101
121174
  lang,
121102
121175
  workspaceId,
@@ -121110,12 +121183,12 @@ async function handleLspConnection(ws, req) {
121110
121183
  ws.close(4002, "Language server stdio not available");
121111
121184
  return;
121112
121185
  }
121113
- log20.debug("LSP client connected: %s/%s", workspaceId, lang);
121186
+ log22.debug("LSP client connected: %s/%s", workspaceId, lang);
121114
121187
  const pendingRequests = /* @__PURE__ */ new Map();
121115
121188
  const retriedIds = /* @__PURE__ */ new Set();
121116
121189
  const RETRY_DELAY_MS = 2e3;
121117
121190
  const parseFrame = createFrameParser((json2) => {
121118
- log20.debug(
121191
+ log22.debug(
121119
121192
  "LSP stdout [%s/%s]: %s",
121120
121193
  workspaceId,
121121
121194
  lang,
@@ -121127,7 +121200,7 @@ async function handleLspConnection(ws, req) {
121127
121200
  const originalRequest = pendingRequests.get(msg.id);
121128
121201
  retriedIds.add(msg.id);
121129
121202
  pendingRequests.delete(msg.id);
121130
- log20.debug(
121203
+ log22.debug(
121131
121204
  "LSP retrying request %d after 'No Project' error [%s/%s]",
121132
121205
  msg.id,
121133
121206
  workspaceId,
@@ -121149,14 +121222,14 @@ async function handleLspConnection(ws, req) {
121149
121222
  const onStdoutData = (chunk) => parseFrame(chunk);
121150
121223
  lspProcess.stdout.on("data", onStdoutData);
121151
121224
  const onExit = (code) => {
121152
- log20.debug("LSP server exited (code %s), closing WebSocket", String(code));
121225
+ log22.debug("LSP server exited (code %s), closing WebSocket", String(code));
121153
121226
  if (ws.readyState === ws.OPEN) {
121154
121227
  ws.close(1e3, "Language server exited");
121155
121228
  }
121156
121229
  };
121157
121230
  lspProcess.on("exit", onExit);
121158
121231
  function forwardToStdin(json2) {
121159
- log20.debug(
121232
+ log22.debug(
121160
121233
  "LSP stdin [%s/%s]: %s",
121161
121234
  workspaceId,
121162
121235
  lang,
@@ -121183,7 +121256,7 @@ async function handleLspConnection(ws, req) {
121183
121256
  ws.on("close", () => {
121184
121257
  lspProcess.stdout?.off("data", onStdoutData);
121185
121258
  lspProcess.off("exit", onExit);
121186
- log20.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
121259
+ log22.debug("LSP client disconnected: %s/%s (server kept alive)", workspaceId, lang);
121187
121260
  });
121188
121261
  }
121189
121262
 
@@ -121712,7 +121785,7 @@ async function installHooks() {
121712
121785
  }
121713
121786
 
121714
121787
  // src/lib/setup.ts
121715
- var log21 = createLogger("setup");
121788
+ var log23 = createLogger("setup");
121716
121789
  var AGENT_CHECKS = [
121717
121790
  { id: "claude-code", type: "claude-code", label: "Claude Code", binary: "claude" },
121718
121791
  { id: "codex", type: "codex", label: "Codex", binary: "codex" },
@@ -121729,7 +121802,7 @@ async function runFirstTimeSetup() {
121729
121802
  ]);
121730
121803
  for (const r6 of results) {
121731
121804
  if (r6.status === "rejected") {
121732
- log21.warn(
121805
+ log23.warn(
121733
121806
  "Setup step failed: %s",
121734
121807
  r6.reason instanceof Error ? r6.reason.message : String(r6.reason)
121735
121808
  );
@@ -121744,7 +121817,7 @@ async function ensureProjectStateInSync() {
121744
121817
  try {
121745
121818
  await syncWorktrees();
121746
121819
  } catch (err) {
121747
- log21.warn(
121820
+ log23.warn(
121748
121821
  "Failed to sync project state at boot: %s",
121749
121822
  err instanceof Error ? err.message : String(err)
121750
121823
  );
@@ -121755,22 +121828,22 @@ async function ensureCliInstalled() {
121755
121828
  try {
121756
121829
  cliStatus = await checkCli();
121757
121830
  } catch (err) {
121758
- log21.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
121831
+ log23.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
121759
121832
  return;
121760
121833
  }
121761
121834
  if (cliStatus === "Installed") {
121762
121835
  return;
121763
121836
  }
121764
121837
  if (cliStatus !== "NotInstalled") {
121765
- log21.warn("CLI not auto-installed (status: %s)", cliStatus);
121838
+ log23.warn("CLI not auto-installed (status: %s)", cliStatus);
121766
121839
  return;
121767
121840
  }
121768
- log21.info("Installing band CLI...");
121841
+ log23.info("Installing band CLI...");
121769
121842
  try {
121770
121843
  await installCli();
121771
- log21.info("CLI installed to /usr/local/bin/band");
121844
+ log23.info("CLI installed to /usr/local/bin/band");
121772
121845
  } catch (err) {
121773
- log21.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
121846
+ log23.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
121774
121847
  }
121775
121848
  }
121776
121849
  async function ensureDefaultCodingAgents() {
@@ -121779,17 +121852,17 @@ async function ensureDefaultCodingAgents() {
121779
121852
  if (Array.isArray(existing) && existing.length > 0) {
121780
121853
  return;
121781
121854
  }
121782
- log21.info("Detecting installed coding agents...");
121855
+ log23.info("Detecting installed coding agents...");
121783
121856
  const detected = [];
121784
121857
  for (const check2 of AGENT_CHECKS) {
121785
121858
  const path3 = await whichBinary(check2.binary);
121786
121859
  if (path3) {
121787
- log21.info("Detected coding agent: %s (%s)", check2.id, path3);
121860
+ log23.info("Detected coding agent: %s (%s)", check2.id, path3);
121788
121861
  detected.push({ id: check2.id, type: check2.type, label: check2.label });
121789
121862
  }
121790
121863
  }
121791
121864
  if (detected.length === 0) {
121792
- log21.info("No coding agent CLIs detected on PATH");
121865
+ log23.info("No coding agent CLIs detected on PATH");
121793
121866
  return;
121794
121867
  }
121795
121868
  const current = loadSettings();
@@ -121798,7 +121871,7 @@ async function ensureDefaultCodingAgents() {
121798
121871
  current.defaultCodingAgent = detected[0].id;
121799
121872
  }
121800
121873
  saveSettings(current);
121801
- log21.info("Enabled %d coding agent(s); default = %s", detected.length, current.defaultCodingAgent);
121874
+ log23.info("Enabled %d coding agent(s); default = %s", detected.length, current.defaultCodingAgent);
121802
121875
  }
121803
121876
  function ensureNotificationDefaults() {
121804
121877
  const settings = loadSettings();
@@ -121810,7 +121883,7 @@ function ensureNotificationDefaults() {
121810
121883
  ...settings,
121811
121884
  notifications: { ...notifications, soundOnNeedsAttention: true }
121812
121885
  });
121813
- log21.info("Set default notifications.soundOnNeedsAttention = true");
121886
+ log23.info("Set default notifications.soundOnNeedsAttention = true");
121814
121887
  }
121815
121888
  async function ensureClaudeHooks() {
121816
121889
  try {
@@ -121819,9 +121892,9 @@ async function ensureClaudeHooks() {
121819
121892
  return;
121820
121893
  }
121821
121894
  await installHooks();
121822
- log21.info("Installed Claude Code hooks");
121895
+ log23.info("Installed Claude Code hooks");
121823
121896
  } catch (err) {
121824
- log21.warn(
121897
+ log23.warn(
121825
121898
  "Failed to install Claude Code hooks: %s",
121826
121899
  err instanceof Error ? err.message : String(err)
121827
121900
  );
@@ -121829,11 +121902,11 @@ async function ensureClaudeHooks() {
121829
121902
  }
121830
121903
  async function ensureSkillsInstalled() {
121831
121904
  try {
121832
- const result = await installSkills({ log: log21 });
121905
+ const result = await installSkills({ log: log23 });
121833
121906
  const wrote = result.written.length + result.updated.length;
121834
121907
  const linkChange = result.linked.length;
121835
121908
  if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
121836
- log21.info(
121909
+ log23.info(
121837
121910
  "Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
121838
121911
  result.written.length,
121839
121912
  result.updated.length,
@@ -121845,7 +121918,7 @@ async function ensureSkillsInstalled() {
121845
121918
  );
121846
121919
  }
121847
121920
  } catch (err) {
121848
- log21.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
121921
+ log23.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
121849
121922
  }
121850
121923
  }
121851
121924
 
@@ -121879,7 +121952,7 @@ function removeTerminalFromLayout(workspaceId, terminalId) {
121879
121952
  }
121880
121953
 
121881
121954
  // src/lib/terminal-manager.ts
121882
- var log22 = createLogger("terminal");
121955
+ var log24 = createLogger("terminal");
121883
121956
  var MAX_SCROLLBACK_SIZE = 1e5;
121884
121957
  var terminals = /* @__PURE__ */ new Map();
121885
121958
  var workspaceTerminals = /* @__PURE__ */ new Map();
@@ -121910,11 +121983,11 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
121910
121983
  if (options2?.cwd) {
121911
121984
  const resolved = join21(workspaceRoot, options2.cwd);
121912
121985
  if (!resolved.startsWith(workspaceRoot)) {
121913
- log22.warn("Ignoring cwd %s \u2014 resolves outside workspace root %s", options2.cwd, workspaceRoot);
121986
+ log24.warn("Ignoring cwd %s \u2014 resolves outside workspace root %s", options2.cwd, workspaceRoot);
121914
121987
  } else if (existsSync7(resolved)) {
121915
121988
  cwd = resolved;
121916
121989
  } else {
121917
- log22.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
121990
+ log24.warn("Ignoring cwd %s \u2014 directory does not exist", options2.cwd);
121918
121991
  }
121919
121992
  }
121920
121993
  if (!existsSync7(cwd)) {
@@ -121923,7 +121996,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
121923
121996
  if (!existsSync7(shell)) {
121924
121997
  throw new Error(`Shell not found: ${shell}`);
121925
121998
  }
121926
- log22.debug(
121999
+ log24.debug(
121927
122000
  "Spawning shell %s in %s for terminal %s (PATH=%s)",
121928
122001
  shell,
121929
122002
  cwd,
@@ -121942,7 +122015,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
121942
122015
  });
121943
122016
  } catch (err) {
121944
122017
  const msg = err instanceof Error ? err.message : String(err);
121945
- log22.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
122018
+ log24.error("pty.spawn failed: %s (shell=%s, cwd=%s)", msg, shell, cwd);
121946
122019
  throw err;
121947
122020
  }
121948
122021
  const session = { pty: ptyProcess, scrollback: "", workspaceId };
@@ -121978,7 +122051,7 @@ async function spawnTerminal(workspaceId, terminalId, options2) {
121978
122051
  }
121979
122052
  });
121980
122053
  ptyProcess.onExit(() => {
121981
- log22.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
122054
+ log24.debug("Terminal exited: %s (workspace %s)", terminalId, workspaceId);
121982
122055
  terminals.delete(terminalId);
121983
122056
  outputListeners.delete(terminalId);
121984
122057
  const set = workspaceTerminals.get(workspaceId);
@@ -122086,7 +122159,7 @@ function killAllTerminals() {
122086
122159
 
122087
122160
  // src/lib/terminal-ws.ts
122088
122161
  init_src();
122089
- var log23 = createLogger("terminal-ws");
122162
+ var log25 = createLogger("terminal-ws");
122090
122163
  var MAX_CLOSE_REASON_BYTES = 123;
122091
122164
  function clampCloseReason(reason) {
122092
122165
  const enc = new TextEncoder();
@@ -122150,7 +122223,7 @@ async function handleTerminalConnection(ws, req) {
122150
122223
  session = await spawnTerminal(workspaceId, terminalId, spawnOpts);
122151
122224
  } catch (err) {
122152
122225
  const msg = err instanceof Error ? err.message : String(err);
122153
- log23.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
122226
+ log25.error("Failed to spawn terminal %s for workspace %s: %s", terminalId, workspaceId, msg);
122154
122227
  safeClose(ws, 4001, msg);
122155
122228
  return;
122156
122229
  }
@@ -122164,7 +122237,7 @@ async function handleTerminalConnection(ws, req) {
122164
122237
  });
122165
122238
  }
122166
122239
  function attachSession(ws, terminalId, workspaceId, session, isNew) {
122167
- log23.debug(
122240
+ log25.debug(
122168
122241
  "Terminal %s: %s (workspace %s)",
122169
122242
  isNew ? "connected" : "reconnected",
122170
122243
  terminalId,
@@ -122193,7 +122266,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
122193
122266
  }, 3e3);
122194
122267
  const exitDisposable = session.pty.onExit(({ exitCode }) => {
122195
122268
  clearInterval(processInterval);
122196
- log23.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
122269
+ log25.debug("PTY exited with code %d for terminal %s", exitCode, terminalId);
122197
122270
  if (ws.readyState === ws.OPEN) {
122198
122271
  ws.close(1e3, "Terminal exited");
122199
122272
  }
@@ -122205,7 +122278,7 @@ function attachSession(ws, terminalId, workspaceId, session, isNew) {
122205
122278
  clearInterval(processInterval);
122206
122279
  dataDisposable.dispose();
122207
122280
  exitDisposable.dispose();
122208
- log23.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
122281
+ log25.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
122209
122282
  });
122210
122283
  }
122211
122284
  function handleMessage(ws, terminalId, session, message) {
@@ -122243,7 +122316,7 @@ function getToken() {
122243
122316
  }
122244
122317
 
122245
122318
  // src/lib/tunnel.ts
122246
- var log24 = createLogger("tunnel");
122319
+ var log26 = createLogger("tunnel");
122247
122320
  var tunnelProcess = null;
122248
122321
  var tunnelUrl = null;
122249
122322
  var startInProgress = null;
@@ -122257,7 +122330,7 @@ function appendToken(baseUrl, token) {
122257
122330
  }
122258
122331
  function spawnTunnel(options2, resolvedPath) {
122259
122332
  const args = ["tunnel", "--config", "/dev/null", "--url", `http://localhost:${options2.port}`];
122260
- log24.debug("spawning cloudflared %s", args.join(" "));
122333
+ log26.debug("spawning cloudflared %s", args.join(" "));
122261
122334
  return new Promise((resolve7, reject) => {
122262
122335
  const child = spawn7("cloudflared", args, {
122263
122336
  env: { ...process.env, PATH: resolvedPath },
@@ -122271,12 +122344,12 @@ function spawnTunnel(options2, resolvedPath) {
122271
122344
  for (const line2 of text3.split("\n")) {
122272
122345
  const trimmed = line2.trim();
122273
122346
  if (!trimmed) continue;
122274
- log24.debug("output: %s", trimmed);
122347
+ log26.debug("output: %s", trimmed);
122275
122348
  const url = extractUrl(trimmed);
122276
122349
  if (url) {
122277
122350
  const token = getToken();
122278
122351
  tunnelUrl = appendToken(url, token);
122279
- log24.debug("detected URL: %s", tunnelUrl);
122352
+ log26.debug("detected URL: %s", tunnelUrl);
122280
122353
  emit({ kind: "tunnel-url", url: tunnelUrl });
122281
122354
  if (!settled) {
122282
122355
  settled = true;
@@ -122291,7 +122364,7 @@ function spawnTunnel(options2, resolvedPath) {
122291
122364
  handleOutput(data);
122292
122365
  });
122293
122366
  child.on("error", (err) => {
122294
- log24.debug("process error: %s", err.message);
122367
+ log26.debug("process error: %s", err.message);
122295
122368
  tunnelProcess = null;
122296
122369
  tunnelUrl = null;
122297
122370
  emit({ kind: "tunnel-error", error: err.message });
@@ -122301,7 +122374,7 @@ function spawnTunnel(options2, resolvedPath) {
122301
122374
  }
122302
122375
  });
122303
122376
  child.on("exit", (code) => {
122304
- log24.debug("process exited with code: %d", code ?? -1);
122377
+ log26.debug("process exited with code: %d", code ?? -1);
122305
122378
  const wasRunning = tunnelProcess !== null && settled;
122306
122379
  tunnelProcess = null;
122307
122380
  tunnelUrl = null;
@@ -122323,7 +122396,7 @@ function spawnTunnel(options2, resolvedPath) {
122323
122396
  });
122324
122397
  setTimeout(() => {
122325
122398
  if (!settled) {
122326
- log24.debug("30s timeout reached, resolving without URL");
122399
+ log26.debug("30s timeout reached, resolving without URL");
122327
122400
  settled = true;
122328
122401
  resolve7();
122329
122402
  }
@@ -122332,12 +122405,12 @@ function spawnTunnel(options2, resolvedPath) {
122332
122405
  }
122333
122406
  async function startTunnel(options2) {
122334
122407
  if (startInProgress) {
122335
- log24.debug("startTunnel: start already in progress, waiting...");
122408
+ log26.debug("startTunnel: start already in progress, waiting...");
122336
122409
  await startInProgress;
122337
122410
  return;
122338
122411
  }
122339
122412
  if (tunnelProcess) {
122340
- log24.debug("startTunnel: already running, re-emitting URL");
122413
+ log26.debug("startTunnel: already running, re-emitting URL");
122341
122414
  if (tunnelUrl) {
122342
122415
  emit({ kind: "tunnel-url", url: tunnelUrl });
122343
122416
  }
@@ -133763,7 +133836,7 @@ function createContext8() {
133763
133836
 
133764
133837
  // src/trpc/router.ts
133765
133838
  init_src();
133766
- import { execFile as execFile5, execFileSync as execFileSync2, spawn as spawn8 } from "node:child_process";
133839
+ import { execFile as execFile6, execFileSync as execFileSync2, spawn as spawn8 } from "node:child_process";
133767
133840
  import { randomUUID as randomUUID2 } from "node:crypto";
133768
133841
  import {
133769
133842
  existsSync as existsSync9,
@@ -133885,7 +133958,7 @@ function clearHistory(workspaceId, range, now = Date.now()) {
133885
133958
 
133886
133959
  // src/lib/chat-session-summary.ts
133887
133960
  init_src();
133888
- var log25 = createLogger("chat-session-summary");
133961
+ var log27 = createLogger("chat-session-summary");
133889
133962
  var REFRESH_KEY = Symbol.for("band.chat-session-summary.refresh");
133890
133963
  var g15 = globalThis;
133891
133964
  if (!g15[REFRESH_KEY]) g15[REFRESH_KEY] = /* @__PURE__ */ new Map();
@@ -133907,7 +133980,7 @@ async function ensureActiveSessionSummary(chatId, worktreePath) {
133907
133980
  }
133908
133981
  return chat;
133909
133982
  } catch (err) {
133910
- log25.warn({ chatId, err }, "ensureActiveSessionSummary failed");
133983
+ log27.warn({ chatId, err }, "ensureActiveSessionSummary failed");
133911
133984
  return chat;
133912
133985
  }
133913
133986
  }
@@ -133934,7 +134007,56 @@ async function doRefresh(chatId, worktreePath) {
133934
134007
  return;
133935
134008
  }
133936
134009
  } catch (err) {
133937
- log25.warn({ chatId, err }, "active session refresh failed");
134010
+ log27.warn({ chatId, err }, "active session refresh failed");
134011
+ }
134012
+ }
134013
+
134014
+ // src/lib/disk-usage.ts
134015
+ import { execFile as execFile5 } from "node:child_process";
134016
+ var MAX_BUFFER2 = 10 * 1024 * 1024;
134017
+ var DU_TIMEOUT_MS = 3e4;
134018
+ var DU_GLOBAL_CONCURRENCY = 8;
134019
+ var inFlight = 0;
134020
+ var waiting = [];
134021
+ function acquireSlot() {
134022
+ return new Promise((resolve7) => {
134023
+ const grant = () => {
134024
+ inFlight++;
134025
+ resolve7(() => {
134026
+ inFlight--;
134027
+ const next = waiting.shift();
134028
+ if (next) next();
134029
+ });
134030
+ };
134031
+ if (inFlight < DU_GLOBAL_CONCURRENCY) grant();
134032
+ else waiting.push(grant);
134033
+ });
134034
+ }
134035
+ async function duBytes(path3) {
134036
+ const release = await acquireSlot();
134037
+ try {
134038
+ const stdout = await new Promise((resolve7, reject) => {
134039
+ execFile5(
134040
+ "du",
134041
+ ["-sk", path3],
134042
+ { maxBuffer: MAX_BUFFER2, timeout: DU_TIMEOUT_MS },
134043
+ (err, out) => {
134044
+ if (err && !out) {
134045
+ reject(err);
134046
+ return;
134047
+ }
134048
+ resolve7(out);
134049
+ }
134050
+ );
134051
+ });
134052
+ const kbStr = stdout.trim().split(/\s+/)[0];
134053
+ const kb2 = Number.parseInt(kbStr, 10);
134054
+ if (!Number.isFinite(kb2)) {
134055
+ throw new Error(`du output not numeric: ${JSON.stringify(stdout)}`);
134056
+ }
134057
+ return kb2 * 1024;
134058
+ } finally {
134059
+ release();
133938
134060
  }
133939
134061
  }
133940
134062
 
@@ -134035,7 +134157,7 @@ init_src();
134035
134157
  import { existsSync as existsSync8, realpathSync as realpathSync4 } from "node:fs";
134036
134158
  import { basename, dirname as dirname6, isAbsolute, join as join22, resolve as resolvePath } from "node:path";
134037
134159
  import prettier from "prettier";
134038
- var log26 = createLogger("formatter");
134160
+ var log28 = createLogger("formatter");
134039
134161
  var FormatterError = class extends Error {
134040
134162
  code;
134041
134163
  detail;
@@ -134090,7 +134212,7 @@ async function formatFile(worktreePath, filePath, content2, options2 = {}) {
134090
134212
  }
134091
134213
  const changed = formatted !== content2;
134092
134214
  if (changed) {
134093
- log26.info(
134215
+ log28.info(
134094
134216
  "Formatted %s with parser=%s (%d bytes in)",
134095
134217
  absFile,
134096
134218
  info.inferredParser,
@@ -134229,7 +134351,7 @@ function fuzzyScore(query, filePath) {
134229
134351
  // src/lib/terminal-config.ts
134230
134352
  init_src();
134231
134353
  init_zod();
134232
- var log27 = createLogger("terminal-config");
134354
+ var log29 = createLogger("terminal-config");
134233
134355
  var TerminalPaneConfigSchema = external_exports.object({
134234
134356
  name: external_exports.string().optional(),
134235
134357
  command: external_exports.string().optional(),
@@ -134260,7 +134382,7 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
134260
134382
  if (!terminalBlock) return null;
134261
134383
  const result = WorkspaceTerminalConfigSchema.safeParse(terminalBlock);
134262
134384
  if (!result.success) {
134263
- log27.warn(
134385
+ log29.warn(
134264
134386
  "Invalid workspace.terminal config: %s",
134265
134387
  result.error.issues.map((i2) => `${i2.path.join(".")}: ${i2.message}`).join("; ")
134266
134388
  );
@@ -134270,8 +134392,8 @@ function loadWorkspaceTerminalConfig(worktreePath, projectPath) {
134270
134392
  }
134271
134393
 
134272
134394
  // src/trpc/router.ts
134273
- var execFileAsync = promisify(execFile5);
134274
- var log28 = createLogger("trpc");
134395
+ var execFileAsync = promisify(execFile6);
134396
+ var log30 = createLogger("trpc");
134275
134397
  var t2 = initTRPC.context().create();
134276
134398
  var publicProcedure = t2.procedure;
134277
134399
  var projectsRouter = t2.router({
@@ -134381,7 +134503,14 @@ var projectsRouter = t2.router({
134381
134503
  defaultBranch,
134382
134504
  worktrees: worktrees2,
134383
134505
  label: input.label ?? void 0,
134384
- kind
134506
+ kind,
134507
+ // For git projects, default to `true` so the first CI poll
134508
+ // still runs the GraphQL query — `syncWorktrees` writes the
134509
+ // real value on the next tick. For plain projects there's no
134510
+ // remote by construction, so set `false` directly: sync skips
134511
+ // plain projects (`kind !== "plain"` filter), so this initial
134512
+ // value sticks for the lifetime of the row. See issue #458.
134513
+ hasOrigin: kind === "git"
134385
134514
  };
134386
134515
  state2.projects.push(project);
134387
134516
  saveState(state2);
@@ -134572,13 +134701,13 @@ var workspacesRouter = t2.router({
134572
134701
  try {
134573
134702
  const deletedTasks = deleteWorkspaceTasks(workspaceId);
134574
134703
  if (deletedTasks > 0) {
134575
- log28.info(
134704
+ log30.info(
134576
134705
  { workspaceId, count: deletedTasks },
134577
134706
  "deleted workspace tasks on removal"
134578
134707
  );
134579
134708
  }
134580
134709
  } catch (err) {
134581
- log28.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
134710
+ log30.error({ workspaceId, err }, "failed to delete workspace tasks on removal");
134582
134711
  }
134583
134712
  emit({ kind: "remove", workspaceId });
134584
134713
  const projPath = proj.path;
@@ -134596,7 +134725,7 @@ var workspacesRouter = t2.router({
134596
134725
  timeout: 6e4
134597
134726
  });
134598
134727
  } catch (err) {
134599
- log28.warn({ err, workspaceId }, "teardown script failed");
134728
+ log30.warn({ err, workspaceId }, "teardown script failed");
134600
134729
  }
134601
134730
  }
134602
134731
  try {
@@ -134614,7 +134743,7 @@ var workspacesRouter = t2.router({
134614
134743
  encoding: "utf-8"
134615
134744
  });
134616
134745
  } catch (err) {
134617
- log28.warn({ err, workspaceId }, "git worktree prune failed");
134746
+ log30.warn({ err, workspaceId }, "git worktree prune failed");
134618
134747
  }
134619
134748
  }
134620
134749
  try {
@@ -134626,7 +134755,7 @@ var workspacesRouter = t2.router({
134626
134755
  } catch {
134627
134756
  }
134628
134757
  })().catch((err) => {
134629
- log28.error({ err, workspaceId }, "background workspace cleanup failed");
134758
+ log30.error({ err, workspaceId }, "background workspace cleanup failed");
134630
134759
  });
134631
134760
  });
134632
134761
  return { ok: true };
@@ -134707,7 +134836,7 @@ var workspacesRouter = t2.router({
134707
134836
  throw new Error(`Script "${input.scriptType}" not found`);
134708
134837
  }
134709
134838
  return new Promise((resolve7, reject) => {
134710
- execFile5("bash", [scriptPath], { cwd: input.path }, (err) => {
134839
+ execFile6("bash", [scriptPath], { cwd: input.path }, (err) => {
134711
134840
  if (err) {
134712
134841
  reject(new Error(err.message));
134713
134842
  } else {
@@ -134978,7 +135107,7 @@ var workspaceRouter = t2.router({
134978
135107
  );
134979
135108
  branches = output.trim().split("\n").map((b10) => b10.trim()).filter(Boolean);
134980
135109
  } catch (err) {
134981
- log28.error(
135110
+ log30.error(
134982
135111
  `listBranches: for-each-ref failed for ${cwd}: ${err instanceof Error ? err.message : err}`
134983
135112
  );
134984
135113
  }
@@ -135838,21 +135967,21 @@ var tunnelRouter = t2.router({
135838
135967
  return getTunnelStatus();
135839
135968
  }),
135840
135969
  start: publicProcedure.input(external_exports.object({}).optional()).mutation(async () => {
135841
- log28.debug("tunnel.start called");
135970
+ log30.debug("tunnel.start called");
135842
135971
  const port = parseInt(process.env.BAND_PORT || "3456", 10);
135843
- log28.debug("tunnel.start: port=%d", port);
135972
+ log30.debug("tunnel.start: port=%d", port);
135844
135973
  try {
135845
135974
  await startTunnel({ port });
135846
135975
  } catch (err) {
135847
- log28.debug({ err }, "tunnel.start: startTunnel failed");
135976
+ log30.debug({ err }, "tunnel.start: startTunnel failed");
135848
135977
  return { ok: true, url: null };
135849
135978
  }
135850
135979
  const status = getTunnelStatus();
135851
- log28.debug({ status }, "tunnel.start: after startTunnel");
135980
+ log30.debug({ status }, "tunnel.start: after startTunnel");
135852
135981
  if (status.url) {
135853
135982
  return { ok: true, url: status.url };
135854
135983
  }
135855
- log28.debug("tunnel.start: no URL available");
135984
+ log30.debug("tunnel.start: no URL available");
135856
135985
  return { ok: true, url: null };
135857
135986
  }),
135858
135987
  stop: publicProcedure.mutation(async () => {
@@ -135867,7 +135996,7 @@ var prereqsRouter = t2.router({
135867
135996
  installTunnel: publicProcedure.mutation(async () => {
135868
135997
  const resolvedPath = await shellPath();
135869
135998
  await new Promise((resolve7, reject) => {
135870
- execFile5(
135999
+ execFile6(
135871
136000
  "brew",
135872
136001
  ["install", "cloudflared"],
135873
136002
  { env: { ...process.env, PATH: resolvedPath }, timeout: 12e4 },
@@ -136071,15 +136200,15 @@ var sessionsRouter = t2.router({
136071
136200
  });
136072
136201
  var servicesRouter = t2.router({
136073
136202
  health: publicProcedure.query(() => {
136074
- log28.debug("services.health called");
136203
+ log30.debug("services.health called");
136075
136204
  const tunnel = getTunnelStatus();
136076
- log28.debug({ tunnel }, "services.health: tunnel status");
136205
+ log30.debug({ tunnel }, "services.health: tunnel status");
136077
136206
  const result = {
136078
136207
  webserver: true,
136079
136208
  tunnel: tunnel.running,
136080
136209
  tunnel_url: tunnel.url
136081
136210
  };
136082
- log28.debug({ result }, "services.health result");
136211
+ log30.debug({ result }, "services.health result");
136083
136212
  return result;
136084
136213
  }),
136085
136214
  // Activity level controls how often the branch-status poller fires.
@@ -136089,7 +136218,124 @@ var servicesRouter = t2.router({
136089
136218
  setPollerActivity(input.activity);
136090
136219
  return { activity: input.activity };
136091
136220
  }),
136092
- getActivity: publicProcedure.query(() => ({ activity: getPollerActivity() }))
136221
+ getActivity: publicProcedure.query(() => ({ activity: getPollerActivity() })),
136222
+ // Resources dashboard — server CPU/memory snapshot (cheap, instant).
136223
+ // `process.cpuUsage()` is cumulative since process start; the UI labels
136224
+ // it "Total CPU time" so callers don't read it as instantaneous load.
136225
+ resourcesServer: publicProcedure.query(() => {
136226
+ const mem = process.memoryUsage();
136227
+ const cpu = process.cpuUsage();
136228
+ return {
136229
+ pid: process.pid,
136230
+ uptimeSeconds: process.uptime(),
136231
+ nodeVersion: process.version,
136232
+ platform: process.platform,
136233
+ arch: process.arch,
136234
+ memory: {
136235
+ rssBytes: mem.rss,
136236
+ heapTotalBytes: mem.heapTotal,
136237
+ heapUsedBytes: mem.heapUsed,
136238
+ externalBytes: mem.external,
136239
+ arrayBuffersBytes: mem.arrayBuffers
136240
+ },
136241
+ cpu: {
136242
+ userMicros: cpu.user,
136243
+ systemMicros: cpu.system
136244
+ }
136245
+ };
136246
+ }),
136247
+ // Resources dashboard — list every tracked git project + its
136248
+ // worktree paths *without* doing any disk walks. Instant: just
136249
+ // reads state + a single `git worktree list --porcelain` per
136250
+ // project (in parallel). The client uses this to paint rows
136251
+ // immediately, then fetches each project's size individually
136252
+ // via `resourcesProjectSize` so the slow `du` work is amortised
136253
+ // and observable per-row.
136254
+ resourcesProjects: publicProcedure.query(async () => {
136255
+ const state2 = loadState();
136256
+ const projects2 = await Promise.all(
136257
+ state2.projects.filter((p6) => p6.kind === "git").map(async (project) => {
136258
+ try {
136259
+ const list2 = await listWorktrees(project.path);
136260
+ const worktrees2 = list2.filter((wt) => !wt.isBare).map((wt) => ({
136261
+ // Detached HEAD (mid-rebase, mid-bisect, or
136262
+ // explicit `git checkout <sha>`) produces an empty
136263
+ // branch string. Keep the row with a sentinel
136264
+ // label so the size still gets counted — silently
136265
+ // dropping it would make a developer's largest
136266
+ // worktree disappear from the accounting whenever
136267
+ // they happened to be on a detached HEAD.
136268
+ branch: wt.branch || "(detached HEAD)",
136269
+ path: wt.path
136270
+ }));
136271
+ return {
136272
+ project: project.name,
136273
+ path: project.path,
136274
+ worktrees: worktrees2,
136275
+ error: void 0
136276
+ };
136277
+ } catch (err) {
136278
+ return {
136279
+ project: project.name,
136280
+ path: project.path,
136281
+ worktrees: [],
136282
+ error: err instanceof Error ? err.message : String(err)
136283
+ };
136284
+ }
136285
+ })
136286
+ );
136287
+ return { projects: projects2 };
136288
+ }),
136289
+ // Resources dashboard — measure disk usage for a single project.
136290
+ //
136291
+ // Slow: runs `du -sk` once per worktree, in parallel via
136292
+ // Promise.all. The client fan-outs are concurrency-limited so the
136293
+ // server doesn't see a thundering herd of `du` processes from a
136294
+ // single page open. Per-worktree errors are absorbed into the
136295
+ // response (sizeBytes 0, `error` populated) so a single broken
136296
+ // worktree doesn't fail the whole query.
136297
+ resourcesProjectSize: publicProcedure.input(external_exports.object({ project: external_exports.string() })).query(async ({ input }) => {
136298
+ const state2 = loadState();
136299
+ const project = state2.projects.find((p6) => p6.name === input.project && p6.kind === "git");
136300
+ if (!project) {
136301
+ throw new TRPCError({ code: "NOT_FOUND", message: "Project not found" });
136302
+ }
136303
+ let worktreePaths;
136304
+ try {
136305
+ const list2 = await listWorktrees(project.path);
136306
+ worktreePaths = list2.filter((wt) => !wt.isBare).map((wt) => ({
136307
+ // See `resourcesProjects` above — detached HEAD gets a
136308
+ // sentinel label rather than being dropped.
136309
+ branch: wt.branch || "(detached HEAD)",
136310
+ path: wt.path
136311
+ }));
136312
+ } catch (err) {
136313
+ return {
136314
+ project: project.name,
136315
+ sizeBytes: 0,
136316
+ worktrees: [],
136317
+ error: err instanceof Error ? err.message : String(err)
136318
+ };
136319
+ }
136320
+ const worktrees2 = await Promise.all(
136321
+ worktreePaths.map(async (wt) => {
136322
+ try {
136323
+ const sizeBytes2 = await duBytes(wt.path);
136324
+ return { branch: wt.branch, path: wt.path, sizeBytes: sizeBytes2 };
136325
+ } catch (err) {
136326
+ return {
136327
+ branch: wt.branch,
136328
+ path: wt.path,
136329
+ sizeBytes: 0,
136330
+ error: err instanceof Error ? err.message : String(err)
136331
+ };
136332
+ }
136333
+ })
136334
+ );
136335
+ worktrees2.sort((a6, b10) => b10.sizeBytes - a6.sizeBytes);
136336
+ const sizeBytes = worktrees2.reduce((sum, wt) => sum + wt.sizeBytes, 0);
136337
+ return { project: project.name, sizeBytes, worktrees: worktrees2 };
136338
+ })
136093
136339
  });
136094
136340
  function canonicalizeMaybeMissing(p6) {
136095
136341
  if (existsSync9(p6)) {
@@ -136132,11 +136378,12 @@ var editorRouter = t2.router({
136132
136378
  /**
136133
136379
  * Either an absolute filesystem path or a workspace-relative
136134
136380
  * path. Paths inside the workspace root open as normal editor
136135
- * tabs (routed via `/workspace/$id/code/$splat`); paths outside
136136
- * any workspace root open as external tabs (same surface as
136137
- * desktop Cmd+O / "Open File…"). May include a trailing
136138
- * line / column suffix in the standard `path:line[:column]` /
136139
- * `path:line-lineEnd` notation.
136381
+ * tabs (the renderer routes to the Files panel via the
136382
+ * `open-file` SSE event; see `dispatchOpenFileEvent`); paths
136383
+ * outside any workspace root open as external tabs (same
136384
+ * surface as desktop Cmd+O / "Open File…"). May include a
136385
+ * trailing line / column suffix in the standard
136386
+ * `path:line[:column]` / `path:line-lineEnd` notation.
136140
136387
  */
136141
136388
  filePath: external_exports.string().min(1),
136142
136389
  line: external_exports.number().int().positive().optional(),
@@ -136609,7 +136856,7 @@ var chatsRouter = t2.router({
136609
136856
  summary = info?.summary;
136610
136857
  lastModified = info?.lastModified;
136611
136858
  } catch (err) {
136612
- log28.warn(
136859
+ log30.warn(
136613
136860
  { chatId: input.chatId, sessionId: input.sessionId, err },
136614
136861
  "setActiveSession: getSessionInfo failed"
136615
136862
  );
@@ -136729,7 +136976,7 @@ var browserHostRouter = t2.router({
136729
136976
  // can confirm in the server log that the bridge component actually
136730
136977
  // executed. Drop once the experiment is stable.
136731
136978
  ping: publicProcedure.input(external_exports.object({ where: external_exports.string() })).mutation(({ input }) => {
136732
- log28.info("browserHost.ping from %s", input.where);
136979
+ log30.info("browserHost.ping from %s", input.where);
136733
136980
  return { ok: true };
136734
136981
  }),
136735
136982
  ensureView: publicProcedure.subscription(async function* (opts) {
@@ -136883,7 +137130,7 @@ async function resolveQueuedFiles(chatId, files) {
136883
137130
  const derivedPath = file.path ?? (uploadsUrlMatch ? join23(bandHome(), "uploads", uploadsUrlMatch[1]) : void 0);
136884
137131
  if (derivedPath) {
136885
137132
  if (!isPathWithinUploadDir(derivedPath)) {
136886
- log28.warn(
137133
+ log30.warn(
136887
137134
  { chatId, path: derivedPath, filename: file.filename },
136888
137135
  "queue: dropping file with path outside uploads directory"
136889
137136
  );
@@ -136908,7 +137155,7 @@ async function resolveQueuedFiles(chatId, files) {
136908
137155
  });
136909
137156
  continue;
136910
137157
  }
136911
- log28.warn(
137158
+ log30.warn(
136912
137159
  { chatId, url: file.url, filename: file.filename },
136913
137160
  "queue: dropping file with no path and non-data URL \u2014 cannot recover disk path"
136914
137161
  );
@@ -136916,7 +137163,7 @@ async function resolveQueuedFiles(chatId, files) {
136916
137163
  if (needsSave.length > 0) {
136917
137164
  const saved = await saveUploadedFilesDetailed(needsSave);
136918
137165
  if (saved.length !== needsSave.length) {
136919
- log28.error(
137166
+ log30.error(
136920
137167
  { chatId, expected: needsSave.length, got: saved.length },
136921
137168
  "queue: saveUploadedFilesDetailed returned unexpected count \u2014 dropping data-URL files (cannot map 1:1)"
136922
137169
  );
@@ -136949,7 +137196,7 @@ var queueRouter = t2.router({
136949
137196
  try {
136950
137197
  files = await resolveQueuedFiles(chatId, input.files);
136951
137198
  } catch (err) {
136952
- log28.error(
137199
+ log30.error(
136953
137200
  { chatId, err: err instanceof Error ? err.message : err },
136954
137201
  "queue.push: failed to persist file uploads; enqueuing text only"
136955
137202
  );
@@ -136985,7 +137232,7 @@ var queueRouter = t2.router({
136985
137232
  files: await resolveQueuedFiles(chatId, m11.files)
136986
137233
  };
136987
137234
  } catch (err) {
136988
- log28.error(
137235
+ log30.error(
136989
137236
  { chatId, messageId: m11.id, err: err instanceof Error ? err.message : err },
136990
137237
  "queue: failed to resolve files for queued message; dropping its files"
136991
137238
  );