@band-app/server 0.11.0 → 0.13.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 (173) hide show
  1. package/dist/client/assets/{DockviewTerminalContainer-B_d7xICn.js → DockviewTerminalContainer-CLlvqDbZ.js} +2 -2
  2. package/dist/client/assets/TerminalPanel-BE9r8rEY.js +4 -0
  3. package/dist/client/assets/{_basePickBy-CGUp_yxK.js → _basePickBy-Dh2WFRMd.js} +1 -1
  4. package/dist/client/assets/{_baseUniq-Dw6GHoL9.js → _baseUniq-2BIwN7J1.js} +1 -1
  5. package/dist/client/assets/{arc-XlfWbXyq.js → arc-Wsw6SggN.js} +1 -1
  6. package/dist/client/assets/{architectureDiagram-VXUJARFQ-DrbWYU6-.js → architectureDiagram-VXUJARFQ-XSuarAoX.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-VD42YOAC-CnGWSi-4.js → blockDiagram-VD42YOAC-DSc5TOI1.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-YG6GDRKO-XgYkwrO4.js → c4Diagram-YG6GDRKO-DLlwzfnX.js} +1 -1
  9. package/dist/client/assets/channel-C5uboiOE.js +1 -0
  10. package/dist/client/assets/{chunk-4BX2VUAB-Bni0jj5l.js → chunk-4BX2VUAB-CWduv96U.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-CP2DHV4G.js → chunk-55IACEB6-D9A39zkK.js} +1 -1
  12. package/dist/client/assets/{chunk-B4BG7PRW-LorOGQCt.js → chunk-B4BG7PRW-CUMptYWA.js} +1 -1
  13. package/dist/client/assets/{chunk-DI55MBZ5-BGfyRUcq.js → chunk-DI55MBZ5-DIwkyxaQ.js} +1 -1
  14. package/dist/client/assets/{chunk-FMBD7UC4-DSwbm1gv.js → chunk-FMBD7UC4-D8F2lei-.js} +1 -1
  15. package/dist/client/assets/{chunk-QN33PNHL-EtPi_Ji9.js → chunk-QN33PNHL-C83_AULb.js} +1 -1
  16. package/dist/client/assets/{chunk-QZHKN3VN-DO6tEA7r.js → chunk-QZHKN3VN-Dtw-3_KI.js} +1 -1
  17. package/dist/client/assets/{chunk-TZMSLE5B-Nj40qaVe.js → chunk-TZMSLE5B-Cg9TlQ9E.js} +1 -1
  18. package/dist/client/assets/classDiagram-2ON5EDUG-CbG2RU7R.js +1 -0
  19. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CbG2RU7R.js +1 -0
  20. package/dist/client/assets/clone-vDxxg1dv.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-S5V4N54A-ak82Fzvq.js → cose-bilkent-S5V4N54A-Drnoe6yO.js} +1 -1
  22. package/dist/client/assets/{dagre-6UL2VRFP-BhRq81p8.js → dagre-6UL2VRFP-BgY7fnyf.js} +2 -2
  23. package/dist/client/assets/{diagram-PSM6KHXK-CdCO4ElG.js → diagram-PSM6KHXK-bmxBt_Q-.js} +1 -1
  24. package/dist/client/assets/{diagram-QEK2KX5R-ZTP_AdCr.js → diagram-QEK2KX5R-DGUqlb8j.js} +1 -1
  25. package/dist/client/assets/{diagram-S2PKOQOG-CUwvj0ij.js → diagram-S2PKOQOG-DxXpOhvW.js} +1 -1
  26. package/dist/client/assets/{erDiagram-Q2GNP2WA-_TAh-IWD.js → erDiagram-Q2GNP2WA-eZBtaSzD.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-NV44I4VS-BuwDJSn1.js → flowDiagram-NV44I4VS-Dfwd3PGB.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-JELNMOA3-B7yQG2sO.js → ganttDiagram-JELNMOA3-BAMeSthd.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-BO5T-8Lr.js → gitGraphDiagram-V2S2FVAM-Dts_Yrpu.js} +1 -1
  30. package/dist/client/assets/{graph-D-uGD-0H.js → graph-BuNOEI6L.js} +1 -1
  31. package/dist/client/assets/{highlighted-body-B3W2YXNL-BhBwg9zK.js → highlighted-body-B3W2YXNL-Btj0UZe1.js} +1 -1
  32. package/dist/client/assets/{index-CJMoNto1.js → index-B4xvdE9X.js} +1 -1
  33. package/dist/client/assets/{index-CxT2NPzl.js → index-BFyseSVV.js} +1 -1
  34. package/dist/client/assets/{index-Go-0lxNN.js → index-Bmhh2EB_.js} +1 -1
  35. package/dist/client/assets/{index-BMvH6RWO.js → index-CF7iJtA6.js} +1 -1
  36. package/dist/client/assets/{index-P603ebp4.js → index-D7TqJ9RF.js} +1 -1
  37. package/dist/client/assets/{index-DxHeWcH9.js → index-DOb48mtv.js} +2 -2
  38. package/dist/client/assets/{index-DiaEWqnN.js → index-DR-TpUg3.js} +1 -1
  39. package/dist/client/assets/{index-Qgt9bjPe.js → index-DaorCZSP.js} +1 -1
  40. package/dist/client/assets/{index-B1UdfbJU.js → index-JytYW91Z.js} +1 -1
  41. package/dist/client/assets/{index-CvA0I31h.js → index-Ktl6P-nc.js} +1 -1
  42. package/dist/client/assets/{index-ei6PilZv.js → index-Qm_HbX1-.js} +1 -1
  43. package/dist/client/assets/{index-C9CkZeNx.js → index-Vaa1H_pP.js} +1 -1
  44. package/dist/client/assets/{index-DyXCT17y.js → index-cErwJT25.js} +1 -1
  45. package/dist/client/assets/{index-CQ8y5zr7.js → index-g5xXrehm.js} +1 -1
  46. package/dist/client/assets/{index-DZeEuAVf.js → index-gv6bT0S4.js} +1 -1
  47. package/dist/client/assets/{index-BCvOU1J9.js → index-sMR7WunY.js} +1 -1
  48. package/dist/client/assets/{index-B9YuCMCp.js → index-tIReXko0.js} +1 -1
  49. package/dist/client/assets/{index-DB_ThGxo.js → index-xEL9mxnj.js} +1 -1
  50. package/dist/client/assets/{infoDiagram-HS3SLOUP-CXG0VFXc.js → infoDiagram-HS3SLOUP-ygUopIDr.js} +1 -1
  51. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-DHFwgvUa.js → journeyDiagram-XKPGCS4Q-C7fCACOj.js} +1 -1
  52. package/dist/client/assets/{kanban-definition-3W4ZIXB7-Dz5WwtmO.js → kanban-definition-3W4ZIXB7-4jf7Ztsb.js} +1 -1
  53. package/dist/client/assets/{layout-Br-A41yG.js → layout-DBEGDIe2.js} +1 -1
  54. package/dist/client/assets/{linear-eN-Z_k3e.js → linear-2Gp1gLY9.js} +1 -1
  55. package/dist/client/assets/main-4FaYQ5DQ.css +1 -0
  56. package/dist/client/assets/{main-CfXjc_JR.js → main-CzHZzsmJ.js} +264 -264
  57. package/dist/client/assets/{mindmap-definition-VGOIOE7T-KtSITXQp.js → mindmap-definition-VGOIOE7T-CiziEudd.js} +1 -1
  58. package/dist/client/assets/{pieDiagram-ADFJNKIX-BQmo4537.js → pieDiagram-ADFJNKIX-DTFtaGug.js} +1 -1
  59. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-Cftd-sa5.js → quadrantDiagram-AYHSOK5B-fbALF3fd.js} +1 -1
  60. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-Cbad3gPG.js → requirementDiagram-UZGBJVZJ-CRl9BPyr.js} +1 -1
  61. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-CT0Fvveb.js → sankeyDiagram-TZEHDZUN-RgshY6u-.js} +1 -1
  62. package/dist/client/assets/{sequenceDiagram-WL72ISMW-D_VHvSKc.js → sequenceDiagram-WL72ISMW-BbgPIX0Q.js} +1 -1
  63. package/dist/client/assets/{square-terminal-BIHVvHoK.js → square-terminal-DCU0c-OS.js} +1 -1
  64. package/dist/client/assets/{stateDiagram-FKZM4ZOC-BXtCQjOy.js → stateDiagram-FKZM4ZOC-feRu8oRh.js} +1 -1
  65. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-By7mP9TH.js +1 -0
  66. package/dist/client/assets/{timeline-definition-IT6M3QCI-DG4t2xHw.js → timeline-definition-IT6M3QCI-BqWKbKID.js} +1 -1
  67. package/dist/client/assets/{treemap-GDKQZRPO-DQP5MG32.js → treemap-GDKQZRPO-D0xFOnga.js} +1 -1
  68. package/dist/client/assets/{useSessionListContext-CbzNRAeC.js → useSessionListContext-PZqsgbdH.js} +1 -1
  69. package/dist/client/assets/workspace._workspaceId-djkhDM0B.js +1 -0
  70. package/dist/client/assets/{workspace._workspaceId.changes-C0w9GX6M.js → workspace._workspaceId.changes-InUdTCW0.js} +1 -1
  71. package/dist/client/assets/workspace._workspaceId.code-B2HMVWnI.js +1 -0
  72. package/dist/client/assets/{workspace._workspaceId.code._-BlXLI8oa.js → workspace._workspaceId.code._-iCOKNXeZ.js} +1 -1
  73. package/dist/client/assets/{workspace._workspaceId.code.index-C-ai4qSV.js → workspace._workspaceId.code.index-DMKkXryF.js} +1 -1
  74. package/dist/client/assets/{workspace._workspaceId.index-B4ICOQa_.js → workspace._workspaceId.index-BZyamHNS.js} +1 -1
  75. package/dist/client/assets/{workspace._workspaceId.terminal-twItT7MS.js → workspace._workspaceId.terminal-4F7quTy3.js} +2 -2
  76. package/dist/client/assets/{xychartDiagram-PRI3JC2R-B3wc6a3i.js → xychartDiagram-PRI3JC2R-DicPcjot.js} +1 -1
  77. package/dist/migrations/20260513141710_browser_history/migration.sql +12 -0
  78. package/dist/migrations/20260513141710_browser_history/snapshot.json +846 -0
  79. package/dist/server/assets/{DockviewTerminalContainer-C08cAuxR.js → DockviewTerminalContainer-BBQnIZa3.js} +3 -3
  80. package/dist/server/assets/TerminalPanel-B1dKqOMK.js +1016 -0
  81. package/dist/server/assets/{_basePickBy-sZPuo3Ci.js → _basePickBy-BoCJVKe_.js} +2 -2
  82. package/dist/server/assets/{_baseUniq-AWKOFGZz.js → _baseUniq-DCXNOsnI.js} +1 -1
  83. package/dist/server/assets/{_tanstack-start-manifest_v-BxDrbOKJ.js → _tanstack-start-manifest_v-2CeISY5W.js} +1 -1
  84. package/dist/server/assets/{arc-BHB8CdVw.js → arc-BFMEbbxV.js} +1 -1
  85. package/dist/server/assets/{architecture-7HQA4BMR-CegM3zV0.js → architecture-7HQA4BMR-4b2GJppC.js} +6 -6
  86. package/dist/server/assets/{architectureDiagram-VXUJARFQ-C0Hc_lzz.js → architectureDiagram-VXUJARFQ-iVW_FQ4S.js} +6 -6
  87. package/dist/server/assets/{blockDiagram-VD42YOAC-CGmRuJNx.js → blockDiagram-VD42YOAC-D1iPUb9l.js} +6 -6
  88. package/dist/server/assets/{c4Diagram-YG6GDRKO-45kx6aRF.js → c4Diagram-YG6GDRKO-DI4Ztwr3.js} +2 -2
  89. package/dist/server/assets/{channel-YRi2PtmI.js → channel-VwPrL84U.js} +1 -1
  90. package/dist/server/assets/{chunk-4BX2VUAB-CdQZhoNV.js → chunk-4BX2VUAB-B9WFGVXO.js} +1 -1
  91. package/dist/server/assets/{chunk-55IACEB6-3Guaa5mF.js → chunk-55IACEB6-cnFKsxmn.js} +1 -1
  92. package/dist/server/assets/{chunk-B4BG7PRW-crikL5R-.js → chunk-B4BG7PRW-DVIhTopX.js} +4 -4
  93. package/dist/server/assets/{chunk-DI55MBZ5-cdG5TMcl.js → chunk-DI55MBZ5-a2cj65b-.js} +3 -3
  94. package/dist/server/assets/{chunk-FMBD7UC4-BfJRchHH.js → chunk-FMBD7UC4-D79uNYe4.js} +1 -1
  95. package/dist/server/assets/{chunk-QN33PNHL--Lwmy-qD.js → chunk-QN33PNHL-BDbkmWdo.js} +1 -1
  96. package/dist/server/assets/{chunk-QZHKN3VN-BjRv3GOJ.js → chunk-QZHKN3VN-CIC4C0nk.js} +1 -1
  97. package/dist/server/assets/{chunk-TZMSLE5B-H_DXTbB4.js → chunk-TZMSLE5B-BQBr1RGS.js} +1 -1
  98. package/dist/server/assets/{classDiagram-v2-WZHVMYZB-89eor2RH.js → classDiagram-2ON5EDUG-CtbqESgu.js} +5 -5
  99. package/dist/server/assets/{classDiagram-2ON5EDUG-89eor2RH.js → classDiagram-v2-WZHVMYZB-CtbqESgu.js} +5 -5
  100. package/dist/server/assets/{clone-ehRaGIPL.js → clone-Bnbf9Iqg.js} +1 -1
  101. package/dist/server/assets/{cose-bilkent-S5V4N54A-CaxWP-ls.js → cose-bilkent-S5V4N54A-DQl5SFk6.js} +1 -1
  102. package/dist/server/assets/{dagre-6UL2VRFP-nML2GoFm.js → dagre-6UL2VRFP-DWcFImvS.js} +6 -6
  103. package/dist/server/assets/{diagram-PSM6KHXK-DNGTWSIt.js → diagram-PSM6KHXK-CAIVqsc3.js} +7 -7
  104. package/dist/server/assets/{diagram-QEK2KX5R-v8VJEGaP.js → diagram-QEK2KX5R-Dc8wo9c1.js} +6 -6
  105. package/dist/server/assets/{diagram-S2PKOQOG-BaL9LGkK.js → diagram-S2PKOQOG-ZNcpDFrx.js} +6 -6
  106. package/dist/server/assets/{erDiagram-Q2GNP2WA-D8492WtW.js → erDiagram-Q2GNP2WA-BYLAWy_j.js} +4 -4
  107. package/dist/server/assets/{flowDiagram-NV44I4VS-9EzGsZaT.js → flowDiagram-NV44I4VS-CzcX8svk.js} +5 -5
  108. package/dist/server/assets/{ganttDiagram-JELNMOA3-DXT8NWPe.js → ganttDiagram-JELNMOA3-Dxwzox2R.js} +2 -2
  109. package/dist/server/assets/{gitGraph-G5XIXVHT-Bz8_hJ5u.js → gitGraph-G5XIXVHT-LK8-a2sz.js} +6 -6
  110. package/dist/server/assets/{gitGraphDiagram-V2S2FVAM-CnBNPMun.js → gitGraphDiagram-V2S2FVAM-DlgLrJB0.js} +7 -7
  111. package/dist/server/assets/{graph-CkD4QR_J.js → graph-BXmxFNFp.js} +2 -2
  112. package/dist/server/assets/{highlighted-body-B3W2YXNL-Cx9TQQOi.js → highlighted-body-B3W2YXNL-DsSe47sR.js} +1 -1
  113. package/dist/server/assets/{index-Du0s-OSL.js → index-4YgzFKOD.js} +5 -5
  114. package/dist/server/assets/{index-DefaG_Jr.js → index-5upQdcP2.js} +2 -2
  115. package/dist/server/assets/{index-CaMi2wJ-.js → index-B-LK0PYZ.js} +2 -2
  116. package/dist/server/assets/{index-ip3CXBin.js → index-BSojqZdf.js} +2 -2
  117. package/dist/server/assets/{index-BIGELKaL.js → index-BbjwIyTa.js} +5 -5
  118. package/dist/server/assets/{index-DRuNJuxv.js → index-BdNVOcCL.js} +2 -2
  119. package/dist/server/assets/{index-D0EeXiux.js → index-BrkgyCV3.js} +2 -2
  120. package/dist/server/assets/{index-Cuzbefg5.js → index-BsoOL_wq.js} +2 -2
  121. package/dist/server/assets/{index-frDhjK4t.js → index-CVjIVbLj.js} +2 -2
  122. package/dist/server/assets/{index-Ys57JqHp.js → index-CWtvbkAQ.js} +3 -3
  123. package/dist/server/assets/{index-Di60ebJg.js → index-CXycOokw.js} +2 -2
  124. package/dist/server/assets/{index-D-gmsExo.js → index-CaaOSPL7.js} +3 -3
  125. package/dist/server/assets/{index-C4UsgNUp.js → index-CnLND4um.js} +1 -1
  126. package/dist/server/assets/{index-Dl8jeLrk.js → index-DM2r-vGW.js} +2 -2
  127. package/dist/server/assets/{index-CURBmg8q.js → index-DdVNSMNY.js} +2 -2
  128. package/dist/server/assets/{index-BnbsIRq2.js → index-Do1Nx4aA.js} +1 -1
  129. package/dist/server/assets/{index-dHlIt0bs.js → index-nKutdysv.js} +2 -2
  130. package/dist/server/assets/{index-CYaseS8g.js → index-oC76KgvT.js} +4 -4
  131. package/dist/server/assets/{info-VBDWY6EO-Cn3hNsdX.js → info-VBDWY6EO-CM7NSJD8.js} +6 -6
  132. package/dist/server/assets/{infoDiagram-HS3SLOUP-7CfAt4Uh.js → infoDiagram-HS3SLOUP-QMxyRHM5.js} +5 -5
  133. package/dist/server/assets/{journeyDiagram-XKPGCS4Q-BSONqKAA.js → journeyDiagram-XKPGCS4Q-BoA6PlCZ.js} +4 -4
  134. package/dist/server/assets/{kanban-definition-3W4ZIXB7-D6yZMd8l.js → kanban-definition-3W4ZIXB7-r6KtKaEH.js} +2 -2
  135. package/dist/server/assets/{layout-mg-BM0ah.js → layout-D3Do3Tbk.js} +4 -4
  136. package/dist/server/assets/{linear-BMOZWebZ.js → linear-CC2CX22M.js} +1 -1
  137. package/dist/server/assets/{mermaid-3ZIDBTTL-BaXUHzN6.js → mermaid-3ZIDBTTL-De3B4GT2.js} +1 -1
  138. package/dist/server/assets/{mermaid-parser.core-rzveH7k9.js → mermaid-parser.core-BNbfHMQU.js} +11 -11
  139. package/dist/server/assets/{mindmap-definition-VGOIOE7T-BWCUtjdH.js → mindmap-definition-VGOIOE7T-BZA0jx43.js} +3 -3
  140. package/dist/server/assets/{packet-DYOGHKS2-YNVTDtvn.js → packet-DYOGHKS2-FVoQy92R.js} +6 -6
  141. package/dist/server/assets/{pie-VRWISCQL-CUd-HhbY.js → pie-VRWISCQL-BGUPFoed.js} +6 -6
  142. package/dist/server/assets/{pieDiagram-ADFJNKIX-Cn9i98AK.js → pieDiagram-ADFJNKIX-6xe9bPcx.js} +7 -7
  143. package/dist/server/assets/{quadrantDiagram-AYHSOK5B-BIqkmSwk.js → quadrantDiagram-AYHSOK5B-DrjB4XQc.js} +2 -2
  144. package/dist/server/assets/{radar-ZZBFDIW7-Bp2wUTqp.js → radar-ZZBFDIW7-BioEa_Uy.js} +6 -6
  145. package/dist/server/assets/{requirementDiagram-UZGBJVZJ-DCovbx84.js → requirementDiagram-UZGBJVZJ-BQUraj5G.js} +3 -3
  146. package/dist/server/assets/{router-BJ9AnId-.js → router-Ch9bBOlF.js} +974 -351
  147. package/dist/server/assets/{sankeyDiagram-TZEHDZUN-D235svhJ.js → sankeyDiagram-TZEHDZUN-qdkVPLba.js} +1 -1
  148. package/dist/server/assets/{sequenceDiagram-WL72ISMW-BkT1dO7h.js → sequenceDiagram-WL72ISMW-Bh5Gu2_v.js} +3 -3
  149. package/dist/server/assets/{square-terminal-CmcrJjAr.js → square-terminal-DVnlJfcM.js} +1 -1
  150. package/dist/server/assets/{stateDiagram-FKZM4ZOC-BJ70j0rR.js → stateDiagram-FKZM4ZOC-BUasl40g.js} +8 -8
  151. package/dist/server/assets/{stateDiagram-v2-4FDKWEC3-ju1h0Bq1.js → stateDiagram-v2-4FDKWEC3-BL56MbOT.js} +4 -4
  152. package/dist/server/assets/{timeline-definition-IT6M3QCI-C3FJ_HU6.js → timeline-definition-IT6M3QCI-oGfd7fF8.js} +2 -2
  153. package/dist/server/assets/{treemap-GDKQZRPO-DvhWVE_G.js → treemap-GDKQZRPO-CELUCxyO.js} +6 -6
  154. package/dist/server/assets/{workspace._workspaceId-Dzw4IQZA.js → workspace._workspaceId-DhJMpGAq.js} +10 -4
  155. package/dist/server/assets/{workspace._workspaceId.changes-XtB3brY5.js → workspace._workspaceId.changes-5-0MP0m5.js} +1 -1
  156. package/dist/server/assets/{workspace._workspaceId.code._-Ta-O6sWR.js → workspace._workspaceId.code._-BFbAz_ei.js} +1 -1
  157. package/dist/server/assets/{workspace._workspaceId.code.index-snQLg3f2.js → workspace._workspaceId.code.index-BepZ481b.js} +1 -1
  158. package/dist/server/assets/{workspace._workspaceId.index-BSnuZ0EI.js → workspace._workspaceId.index-Cp3_jFDn.js} +1 -1
  159. package/dist/server/assets/{workspace._workspaceId.terminal-D3jJ3XMV.js → workspace._workspaceId.terminal-B5beQDh_.js} +2 -2
  160. package/dist/server/assets/{xychartDiagram-PRI3JC2R-BRlE_l5B.js → xychartDiagram-PRI3JC2R-qDOKCR8M.js} +2 -2
  161. package/dist/server/server.js +2 -2
  162. package/dist/start-server.mjs +1118 -519
  163. package/package.json +5 -5
  164. package/dist/client/assets/TerminalPanel-DMsYxEdX.js +0 -4
  165. package/dist/client/assets/channel-C4hzzilT.js +0 -1
  166. package/dist/client/assets/classDiagram-2ON5EDUG-D7Wwq-uf.js +0 -1
  167. package/dist/client/assets/classDiagram-v2-WZHVMYZB-D7Wwq-uf.js +0 -1
  168. package/dist/client/assets/clone-CRqkC7J9.js +0 -1
  169. package/dist/client/assets/main-F2T48yRI.css +0 -1
  170. package/dist/client/assets/stateDiagram-v2-4FDKWEC3--e7abZtM.js +0 -1
  171. package/dist/client/assets/workspace._workspaceId-BlPtc664.js +0 -1
  172. package/dist/client/assets/workspace._workspaceId.code-B2x2c1r3.js +0 -1
  173. package/dist/server/assets/TerminalPanel-CDMb43XN.js +0 -442
@@ -0,0 +1,1016 @@
1
+ import { r as reactExports, j as jsxRuntimeExports } from "../server.js";
2
+ import { E as createLucideIcon, bh as ArrowLeft, c3 as ArrowRight, c4 as ArrowUp, c5 as ArrowDown, X, c6 as ClipboardPaste, b as useSettingsQuery, c7 as openExternalUrl, c8 as SearchBar } from "./router-Ch9bBOlF.js";
3
+ import "node:async_hooks";
4
+ import "node:stream";
5
+ import "util";
6
+ import "crypto";
7
+ import "async_hooks";
8
+ import "stream";
9
+ import "node:stream/web";
10
+ import "node:process";
11
+ import "node:path";
12
+ import "node:url";
13
+ const __iconNode$1 = [
14
+ ["rect", { width: "8", height: "4", x: "8", y: "2", rx: "1", ry: "1", key: "tgr4d6" }],
15
+ ["path", { d: "M8 4H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2", key: "4jdomd" }],
16
+ ["path", { d: "M16 4h2a2 2 0 0 1 2 2v4", key: "3hqy98" }],
17
+ ["path", { d: "M21 14H11", key: "1bme5i" }],
18
+ ["path", { d: "m15 10-4 4 4 4", key: "5dvupr" }]
19
+ ];
20
+ const ClipboardCopy = createLucideIcon("clipboard-copy", __iconNode$1);
21
+ const __iconNode = [
22
+ ["path", { d: "M12 20h-1a2 2 0 0 1-2-2 2 2 0 0 1-2 2H6", key: "1528k5" }],
23
+ ["path", { d: "M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7", key: "13ksps" }],
24
+ ["path", { d: "M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1", key: "1n9rhb" }],
25
+ ["path", { d: "M6 4h1a2 2 0 0 1 2 2 2 2 0 0 1 2-2h1", key: "1mj8rg" }],
26
+ ["path", { d: "M9 6v12", key: "velyjx" }]
27
+ ];
28
+ const TextCursorInput = createLucideIcon("text-cursor-input", __iconNode);
29
+ const TERMINAL_TOOLBAR_HEIGHT_PX = 49;
30
+ const TOUCH_QUERY = "(hover: none) and (pointer: coarse)";
31
+ function useVirtualKeyboardToolbar() {
32
+ const [enabled, setEnabled] = reactExports.useState(
33
+ () => typeof window === "undefined" ? false : window.matchMedia(TOUCH_QUERY).matches
34
+ );
35
+ const [bottomOffset, setBottomOffset] = reactExports.useState(0);
36
+ reactExports.useEffect(() => {
37
+ if (typeof window === "undefined") return;
38
+ const mql = window.matchMedia(TOUCH_QUERY);
39
+ const handler = (e) => setEnabled(e.matches);
40
+ setEnabled(mql.matches);
41
+ mql.addEventListener("change", handler);
42
+ return () => mql.removeEventListener("change", handler);
43
+ }, []);
44
+ reactExports.useEffect(() => {
45
+ if (typeof window === "undefined") return;
46
+ if (!enabled) {
47
+ setBottomOffset(0);
48
+ return;
49
+ }
50
+ const vv = window.visualViewport;
51
+ if (!vv) return;
52
+ const update = () => {
53
+ const keyboardHeight = Math.max(0, window.innerHeight - (vv.offsetTop + vv.height));
54
+ setBottomOffset(keyboardHeight);
55
+ };
56
+ update();
57
+ vv.addEventListener("resize", update);
58
+ vv.addEventListener("scroll", update);
59
+ window.addEventListener("resize", update);
60
+ return () => {
61
+ vv.removeEventListener("resize", update);
62
+ vv.removeEventListener("scroll", update);
63
+ window.removeEventListener("resize", update);
64
+ };
65
+ }, [enabled]);
66
+ return {
67
+ enabled,
68
+ bottomOffset,
69
+ contentBottomInset: enabled ? TERMINAL_TOOLBAR_HEIGHT_PX : 0
70
+ };
71
+ }
72
+ const WORD_RE = /[A-Za-z0-9_./:\-+@~]/;
73
+ function pointToCell(clientX, clientY, terminal, screenEl) {
74
+ const rect = screenEl.getBoundingClientRect();
75
+ if (rect.width <= 0 || rect.height <= 0 || terminal.cols <= 0 || terminal.rows <= 0) {
76
+ return { col: 0, row: terminal.buffer.active.viewportY };
77
+ }
78
+ const cellW = rect.width / terminal.cols;
79
+ const cellH = rect.height / terminal.rows;
80
+ const col = clamp(Math.floor((clientX - rect.left) / cellW), 0, terminal.cols - 1);
81
+ const viewportRow = clamp(Math.floor((clientY - rect.top) / cellH), 0, terminal.rows - 1);
82
+ return { col, row: terminal.buffer.active.viewportY + viewportRow };
83
+ }
84
+ function findWordBoundaries(line, col) {
85
+ if (col < 0 || col >= line.length || !WORD_RE.test(line[col])) {
86
+ const safeCol = clamp(col, 0, Math.max(0, line.length));
87
+ return { start: safeCol, end: safeCol + 1 };
88
+ }
89
+ let start = col;
90
+ while (start > 0 && WORD_RE.test(line[start - 1])) start--;
91
+ let end = col + 1;
92
+ while (end < line.length && WORD_RE.test(line[end])) end++;
93
+ return { start, end };
94
+ }
95
+ function getLineText(terminal, row) {
96
+ return terminal.buffer.active.getLine(row)?.translateToString(false) ?? "";
97
+ }
98
+ function moveCell(cell, dir, terminal) {
99
+ const cols = terminal.cols;
100
+ const lastRow = Math.max(0, terminal.buffer.active.length - 1);
101
+ switch (dir) {
102
+ case "left":
103
+ if (cell.col > 0) return { col: cell.col - 1, row: cell.row };
104
+ if (cell.row > 0) return { col: cols - 1, row: cell.row - 1 };
105
+ return cell;
106
+ case "right":
107
+ if (cell.col < cols - 1) return { col: cell.col + 1, row: cell.row };
108
+ if (cell.row < lastRow) return { col: 0, row: cell.row + 1 };
109
+ return cell;
110
+ case "up":
111
+ if (cell.row > 0) return { col: cell.col, row: cell.row - 1 };
112
+ return cell;
113
+ case "down":
114
+ if (cell.row < lastRow) return { col: cell.col, row: cell.row + 1 };
115
+ return cell;
116
+ }
117
+ }
118
+ function applySelection(terminal, anchor, head) {
119
+ const cols = terminal.cols;
120
+ if (cols <= 0) return;
121
+ const anchorLinear = anchor.row * cols + anchor.col;
122
+ const headLinear = head.row * cols + head.col;
123
+ const startLinear = Math.min(anchorLinear, headLinear);
124
+ const endLinear = Math.max(anchorLinear, headLinear);
125
+ const length = endLinear - startLinear + 1;
126
+ const startRow = Math.floor(startLinear / cols);
127
+ const startCol = startLinear - startRow * cols;
128
+ terminal.select(startCol, startRow, length);
129
+ }
130
+ function wordSelectionAt(cell, lineText) {
131
+ const { start, end } = findWordBoundaries(lineText, cell.col);
132
+ return {
133
+ anchor: { col: start, row: cell.row },
134
+ // `head` is the last cell of the selection (inclusive). `end` from
135
+ // findWordBoundaries is exclusive, so subtract one.
136
+ head: { col: Math.max(start, end - 1), row: cell.row }
137
+ };
138
+ }
139
+ function clamp(n, lo, hi) {
140
+ if (n < lo) return lo;
141
+ if (n > hi) return hi;
142
+ return n;
143
+ }
144
+ async function writeClipboardText(text) {
145
+ if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
146
+ try {
147
+ await navigator.clipboard.writeText(text);
148
+ return true;
149
+ } catch {
150
+ }
151
+ }
152
+ return legacyCopy(text);
153
+ }
154
+ function legacyCopy(text) {
155
+ if (typeof document === "undefined") return false;
156
+ const textarea = document.createElement("textarea");
157
+ textarea.value = text;
158
+ textarea.setAttribute("readonly", "");
159
+ textarea.style.position = "fixed";
160
+ textarea.style.top = "0";
161
+ textarea.style.left = "0";
162
+ textarea.style.width = "1px";
163
+ textarea.style.height = "1px";
164
+ textarea.style.padding = "0";
165
+ textarea.style.border = "0";
166
+ textarea.style.opacity = "0";
167
+ textarea.style.pointerEvents = "none";
168
+ document.body.appendChild(textarea);
169
+ const previouslyFocused = document.activeElement;
170
+ try {
171
+ textarea.focus();
172
+ textarea.select();
173
+ textarea.setSelectionRange(0, text.length);
174
+ return document.execCommand("copy");
175
+ } catch {
176
+ return false;
177
+ } finally {
178
+ document.body.removeChild(textarea);
179
+ previouslyFocused?.focus?.();
180
+ }
181
+ }
182
+ async function readClipboardText() {
183
+ if (typeof navigator === "undefined" || !navigator.clipboard?.readText) {
184
+ return "";
185
+ }
186
+ try {
187
+ return await navigator.clipboard.readText();
188
+ } catch {
189
+ return "";
190
+ }
191
+ }
192
+ const SEQ_ESC = "\x1B";
193
+ const SEQ_TAB = " ";
194
+ const SEQ_ARROW_UP = "\x1B[A";
195
+ const SEQ_ARROW_DOWN = "\x1B[B";
196
+ const SEQ_ARROW_RIGHT = "\x1B[C";
197
+ const SEQ_ARROW_LEFT = "\x1B[D";
198
+ const tap = (fn) => (e) => {
199
+ e.preventDefault();
200
+ void fn();
201
+ };
202
+ function TerminalToolbar({
203
+ terminal,
204
+ sendInput,
205
+ pendingCtrl,
206
+ onToggleCtrl,
207
+ selectionMode,
208
+ onExtendSelection,
209
+ onExitSelection,
210
+ onSelectAll
211
+ }) {
212
+ const { enabled, bottomOffset } = useVirtualKeyboardToolbar();
213
+ const handleCopy = reactExports.useCallback(async () => {
214
+ if (!terminal.hasSelection()) return;
215
+ const text = terminal.getSelection();
216
+ if (!text) return;
217
+ const ok = await writeClipboardText(text);
218
+ if (!ok) console.warn("[TerminalToolbar] clipboard write failed");
219
+ }, [terminal]);
220
+ const handleCopyAndExit = reactExports.useCallback(async () => {
221
+ await handleCopy();
222
+ onExitSelection();
223
+ }, [handleCopy, onExitSelection]);
224
+ const handlePaste = reactExports.useCallback(async () => {
225
+ const text = await readClipboardText();
226
+ if (text) sendInput(text);
227
+ }, [sendInput]);
228
+ const idleKeyButtons = reactExports.useMemo(
229
+ () => [
230
+ { label: "Esc", seq: SEQ_ESC, ariaLabel: "Send Escape" },
231
+ { label: "Tab", seq: SEQ_TAB, ariaLabel: "Send Tab" }
232
+ ],
233
+ []
234
+ );
235
+ const idleArrows = reactExports.useMemo(
236
+ () => [
237
+ { Icon: ArrowLeft, seq: SEQ_ARROW_LEFT, ariaLabel: "Arrow Left" },
238
+ { Icon: ArrowRight, seq: SEQ_ARROW_RIGHT, ariaLabel: "Arrow Right" },
239
+ { Icon: ArrowUp, seq: SEQ_ARROW_UP, ariaLabel: "Arrow Up" },
240
+ { Icon: ArrowDown, seq: SEQ_ARROW_DOWN, ariaLabel: "Arrow Down" }
241
+ ],
242
+ []
243
+ );
244
+ const selectionArrows = reactExports.useMemo(
245
+ () => [
246
+ { Icon: ArrowLeft, dir: "left", ariaLabel: "Extend selection left" },
247
+ { Icon: ArrowRight, dir: "right", ariaLabel: "Extend selection right" },
248
+ { Icon: ArrowUp, dir: "up", ariaLabel: "Extend selection up" },
249
+ { Icon: ArrowDown, dir: "down", ariaLabel: "Extend selection down" }
250
+ ],
251
+ []
252
+ );
253
+ if (!enabled) return null;
254
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
255
+ "div",
256
+ {
257
+ "data-testid": "terminal-toolbar",
258
+ "data-mode": selectionMode ? "selection" : "idle",
259
+ role: "toolbar",
260
+ "aria-label": selectionMode ? "Terminal selection controls" : "Terminal accessory keys",
261
+ style: { bottom: bottomOffset },
262
+ className: "fixed inset-x-0 z-50 flex justify-center border-t border-border bg-background/95 shadow-lg backdrop-blur-md",
263
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex w-full max-w-3xl items-center gap-1 overflow-x-auto px-2 py-1.5", children: selectionMode ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
264
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
265
+ ToolbarButton,
266
+ {
267
+ ariaLabel: "Copy selection and exit",
268
+ title: "Copy",
269
+ onPointerDown: tap(handleCopyAndExit),
270
+ variant: "primary",
271
+ children: [
272
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClipboardCopy, { className: "size-4" }),
273
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "Copy" })
274
+ ]
275
+ }
276
+ ),
277
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
278
+ ToolbarButton,
279
+ {
280
+ ariaLabel: "Exit selection mode",
281
+ title: "Done",
282
+ onPointerDown: tap(onExitSelection),
283
+ children: [
284
+ /* @__PURE__ */ jsxRuntimeExports.jsx(X, { className: "size-4" }),
285
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "Done" })
286
+ ]
287
+ }
288
+ ),
289
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-1 h-6 w-px shrink-0 bg-border", "aria-hidden": "true" }),
290
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
291
+ "span",
292
+ {
293
+ className: "mr-1 shrink-0 select-none text-xs font-medium uppercase tracking-wide text-muted-foreground",
294
+ "aria-hidden": "true",
295
+ children: "Extend"
296
+ }
297
+ ),
298
+ selectionArrows.map(({ Icon, dir, ariaLabel }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
299
+ ToolbarButton,
300
+ {
301
+ ariaLabel,
302
+ title: ariaLabel,
303
+ onPointerDown: tap(() => onExtendSelection(dir)),
304
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "size-4" })
305
+ },
306
+ dir
307
+ ))
308
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
309
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
310
+ ToolbarButton,
311
+ {
312
+ ariaLabel: "Paste from clipboard",
313
+ title: "Paste",
314
+ onPointerDown: tap(handlePaste),
315
+ children: [
316
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ClipboardPaste, { className: "size-4" }),
317
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "Paste" })
318
+ ]
319
+ }
320
+ ),
321
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
322
+ ToolbarButton,
323
+ {
324
+ ariaLabel: "Select all",
325
+ title: "Select all",
326
+ onPointerDown: tap(onSelectAll),
327
+ children: [
328
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TextCursorInput, { className: "size-4" }),
329
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs", children: "All" })
330
+ ]
331
+ }
332
+ ),
333
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-1 h-6 w-px shrink-0 bg-border", "aria-hidden": "true" }),
334
+ idleKeyButtons.map(({ label, seq, ariaLabel }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
335
+ ToolbarButton,
336
+ {
337
+ ariaLabel,
338
+ title: label,
339
+ onPointerDown: tap(() => sendInput(seq)),
340
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium", children: label })
341
+ },
342
+ label
343
+ )),
344
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
345
+ ToolbarButton,
346
+ {
347
+ ariaLabel: pendingCtrl ? "Cancel pending Ctrl" : "Arm Ctrl modifier",
348
+ title: "Ctrl (sticky — taps the next key as Ctrl+key)",
349
+ onPointerDown: tap(onToggleCtrl),
350
+ active: pendingCtrl,
351
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "text-xs font-medium", children: "Ctrl" })
352
+ }
353
+ ),
354
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mx-1 h-6 w-px shrink-0 bg-border", "aria-hidden": "true" }),
355
+ idleArrows.map(({ Icon, seq, ariaLabel }) => /* @__PURE__ */ jsxRuntimeExports.jsx(
356
+ ToolbarButton,
357
+ {
358
+ ariaLabel,
359
+ title: ariaLabel,
360
+ onPointerDown: tap(() => sendInput(seq)),
361
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { className: "size-4" })
362
+ },
363
+ ariaLabel
364
+ ))
365
+ ] }) })
366
+ }
367
+ );
368
+ }
369
+ function ToolbarButton({
370
+ ariaLabel,
371
+ title,
372
+ onPointerDown,
373
+ active,
374
+ variant = "default",
375
+ disabled,
376
+ children
377
+ }) {
378
+ const palette = active ? "bg-primary text-primary-foreground" : variant === "primary" ? "bg-primary text-primary-foreground hover:bg-primary/90" : "bg-muted/60 hover:bg-muted active:bg-muted";
379
+ return /* @__PURE__ */ jsxRuntimeExports.jsx(
380
+ "button",
381
+ {
382
+ type: "button",
383
+ "aria-label": ariaLabel,
384
+ "aria-pressed": active,
385
+ title,
386
+ onPointerDown,
387
+ disabled,
388
+ className: [
389
+ "inline-flex h-9 min-w-9 shrink-0 items-center justify-center gap-1 rounded-md px-2",
390
+ "text-foreground transition-colors",
391
+ palette,
392
+ "disabled:opacity-40"
393
+ ].join(" "),
394
+ children
395
+ }
396
+ );
397
+ }
398
+ const LONG_PRESS_MS = 500;
399
+ const LONG_PRESS_SLOP_PX = 10;
400
+ const SEARCH_DECORATIONS = {
401
+ matchBackground: "#515c6a",
402
+ activeMatchBackground: "#a9913680",
403
+ matchOverviewRuler: "#a9913680",
404
+ activeMatchColorOverviewRuler: "#a99136"
405
+ };
406
+ const DEFAULT_SEARCH_OPTIONS = {
407
+ caseSensitive: false,
408
+ wholeWord: false,
409
+ regex: false
410
+ };
411
+ function toXtermSearchOptions(opts) {
412
+ return {
413
+ caseSensitive: opts.caseSensitive,
414
+ wholeWord: opts.wholeWord,
415
+ regex: opts.regex,
416
+ decorations: SEARCH_DECORATIONS
417
+ };
418
+ }
419
+ const DARK_TERMINAL_THEME = {
420
+ background: "#1e1e1e",
421
+ foreground: "#e8e8e8",
422
+ cursor: "#e8e8e8",
423
+ selectionBackground: "rgba(255, 255, 255, 0.2)"
424
+ };
425
+ const LIGHT_TERMINAL_THEME = {
426
+ background: "#ffffff",
427
+ foreground: "#1e1e1e",
428
+ cursor: "#1e1e1e",
429
+ cursorAccent: "#ffffff",
430
+ selectionBackground: "rgba(0, 0, 0, 0.15)",
431
+ // Tweak ANSI colors so they remain readable on a white background. The default
432
+ // bright-yellow / bright-green xterm palette washes out badly in light mode.
433
+ black: "#000000",
434
+ red: "#cd3131",
435
+ green: "#0a8043",
436
+ yellow: "#946800",
437
+ blue: "#0451a5",
438
+ magenta: "#bc05bc",
439
+ cyan: "#0598bc",
440
+ white: "#555555",
441
+ brightBlack: "#666666",
442
+ brightRed: "#cd3131",
443
+ brightGreen: "#0a8043",
444
+ brightYellow: "#946800",
445
+ brightBlue: "#0451a5",
446
+ brightMagenta: "#bc05bc",
447
+ brightCyan: "#0598bc",
448
+ brightWhite: "#1e1e1e"
449
+ };
450
+ function isDarkMode() {
451
+ return document.documentElement.classList.contains("dark");
452
+ }
453
+ function getTerminalTheme() {
454
+ return isDarkMode() ? DARK_TERMINAL_THEME : LIGHT_TERMINAL_THEME;
455
+ }
456
+ function TerminalPanel({
457
+ workspaceId,
458
+ terminalId,
459
+ visible,
460
+ paneMetadata,
461
+ autoFocus,
462
+ onTitleChange
463
+ }) {
464
+ const containerRef = reactExports.useRef(null);
465
+ const terminalRef = reactExports.useRef(null);
466
+ const fitAddonRef = reactExports.useRef(null);
467
+ const searchAddonRef = reactExports.useRef(null);
468
+ const webglAddonRef = reactExports.useRef(null);
469
+ const wsRef = reactExports.useRef(null);
470
+ const onTitleChangeRef = reactExports.useRef(onTitleChange);
471
+ onTitleChangeRef.current = onTitleChange;
472
+ const { settings } = useSettingsQuery();
473
+ const useWebGLRenderer = settings.useWebGLTerminalRenderer ?? true;
474
+ const useWebGLRendererRef = reactExports.useRef(useWebGLRenderer);
475
+ useWebGLRendererRef.current = useWebGLRenderer;
476
+ const [searchOpen, setSearchOpen] = reactExports.useState(false);
477
+ const [searchQuery, setSearchQuery] = reactExports.useState("");
478
+ const [searchOptions, setSearchOptions] = reactExports.useState(DEFAULT_SEARCH_OPTIONS);
479
+ const [matchInfo, setMatchInfo] = reactExports.useState({
480
+ total: 0,
481
+ current: 0
482
+ });
483
+ const searchBarRef = reactExports.useRef(null);
484
+ const openSearchRef = reactExports.useRef(() => {
485
+ });
486
+ const [terminalReady, setTerminalReady] = reactExports.useState(false);
487
+ const pendingCtrlRef = reactExports.useRef(false);
488
+ const [pendingCtrl, setPendingCtrl] = reactExports.useState(false);
489
+ const handleToggleCtrl = reactExports.useCallback(() => {
490
+ const next = !pendingCtrlRef.current;
491
+ pendingCtrlRef.current = next;
492
+ setPendingCtrl(next);
493
+ }, []);
494
+ const selectionAnchorRef = reactExports.useRef(null);
495
+ const selectionHeadRef = reactExports.useRef(null);
496
+ const [selectionMode, setSelectionMode] = reactExports.useState(false);
497
+ const exitSelectionMode = reactExports.useCallback(() => {
498
+ selectionAnchorRef.current = null;
499
+ selectionHeadRef.current = null;
500
+ setSelectionMode(false);
501
+ terminalRef.current?.clearSelection();
502
+ }, []);
503
+ const handleExtendSelection = reactExports.useCallback((direction) => {
504
+ const terminal = terminalRef.current;
505
+ const anchor = selectionAnchorRef.current;
506
+ const head = selectionHeadRef.current;
507
+ if (!terminal || !anchor || !head) return;
508
+ const next = moveCell(head, direction, terminal);
509
+ selectionHeadRef.current = next;
510
+ applySelection(terminal, anchor, next);
511
+ }, []);
512
+ const handleSelectAll = reactExports.useCallback(() => {
513
+ const terminal = terminalRef.current;
514
+ if (!terminal) return;
515
+ const anchor = { col: 0, row: 0 };
516
+ const lastRow = Math.max(0, terminal.buffer.active.length - 1);
517
+ const head = { col: Math.max(0, terminal.cols - 1), row: lastRow };
518
+ applySelection(terminal, anchor, head);
519
+ selectionAnchorRef.current = anchor;
520
+ selectionHeadRef.current = head;
521
+ setSelectionMode(true);
522
+ terminal.blur();
523
+ }, []);
524
+ reactExports.useEffect(() => {
525
+ if (!containerRef.current) return;
526
+ let cancelled = false;
527
+ let cleanup;
528
+ Promise.all([
529
+ import("./xterm-CkV9CBvP.js"),
530
+ import("./addon-fit-D89xfLfG.js"),
531
+ import("./addon-web-links-CzLDtFWc.js"),
532
+ import("./addon-search-BS53_-cp.js"),
533
+ import("./addon-webgl-BeO2q2vc.js")
534
+ ]).then(([xtermMod, fitMod, webLinksMod, searchMod, webglMod]) => {
535
+ const { Terminal: XTerm } = xtermMod;
536
+ const { FitAddon: XFitAddon } = fitMod;
537
+ const { WebLinksAddon: XWebLinksAddon } = webLinksMod;
538
+ const { SearchAddon: XSearchAddon } = searchMod;
539
+ const { WebglAddon: XWebglAddon } = webglMod;
540
+ if (cancelled || !containerRef.current) return;
541
+ const wantsWebGL = useWebGLRendererRef.current;
542
+ Promise.resolve({ });
543
+ const terminal = new XTerm({
544
+ // Opt in to addon-only APIs (decorations, markers, etc.) that
545
+ // xterm.js 6.1-beta gates behind this flag. Without it, the search
546
+ // addon's `findNext` throws "You must set the allowProposedApi
547
+ // option to true to use proposed API" the first time the user
548
+ // types in the find bar. The addons we ship (search, webgl) are
549
+ // first-party xterm.js addons that depend on these APIs.
550
+ allowProposedApi: true,
551
+ cursorBlink: true,
552
+ fontSize: 13,
553
+ fontFamily: "'SF Mono', Menlo, Monaco, 'Courier New', monospace",
554
+ // iTerm-style row spacing — only safe with the WebGL renderer.
555
+ // The WebGL addon redraws box-drawing (U+2500-U+257F), block
556
+ // elements (U+2580-U+259F), powerline separators, and other
557
+ // continuous glyphs at the full cell rect (via its `customGlyphs`
558
+ // option, default true) so a 1.2 lineHeight doesn't slice horizontal
559
+ // gaps through the opencode banner, claude-code's powerline
560
+ // statusline, or other ASCII art. xterm.js's DOM renderer does
561
+ // NOT do this — falling back to it means we have to revert to
562
+ // lineHeight: 1.0 to keep block art continuous.
563
+ // See https://github.com/band-app/band/issues/391 for history.
564
+ lineHeight: wantsWebGL ? 1.2 : 1,
565
+ macOptionIsMeta: true,
566
+ // Alt+Left/Right → word navigation on macOS
567
+ scrollback: 1e4,
568
+ theme: getTerminalTheme()
569
+ });
570
+ const themeObserver = new MutationObserver(() => {
571
+ terminal.options.theme = getTerminalTheme();
572
+ });
573
+ themeObserver.observe(document.documentElement, {
574
+ attributes: true,
575
+ attributeFilter: ["class"]
576
+ });
577
+ const fitAddon = new XFitAddon();
578
+ terminal.loadAddon(fitAddon);
579
+ terminal.loadAddon(new XWebLinksAddon((_event, uri) => openExternalUrl(uri)));
580
+ terminal.open(containerRef.current);
581
+ let webglContextLossDisposable;
582
+ const attachWebGL = () => {
583
+ try {
584
+ const addon = new XWebglAddon({ customGlyphs: true });
585
+ terminal.loadAddon(addon);
586
+ const screenEl = containerRef.current?.querySelector(
587
+ ".xterm-screen"
588
+ );
589
+ const webglCanvas = screenEl?.querySelector(
590
+ ":scope > canvas:last-of-type"
591
+ );
592
+ if (webglCanvas) {
593
+ webglCanvas.style.pointerEvents = "none";
594
+ webglCanvas.style.touchAction = "none";
595
+ }
596
+ webglAddonRef.current = addon;
597
+ webglContextLossDisposable?.dispose();
598
+ webglContextLossDisposable = addon.onContextLoss(() => {
599
+ console.warn("[TerminalPanel] WebGL context lost, reattaching addon");
600
+ addon.dispose();
601
+ webglAddonRef.current = null;
602
+ attachWebGL();
603
+ });
604
+ return true;
605
+ } catch (err) {
606
+ console.warn("[TerminalPanel] WebGL renderer unavailable, falling back to DOM", err);
607
+ return false;
608
+ }
609
+ };
610
+ if (wantsWebGL) attachWebGL();
611
+ const searchAddon = new XSearchAddon();
612
+ terminal.loadAddon(searchAddon);
613
+ const searchResultsDisposable = searchAddon.onDidChangeResults((event) => {
614
+ setMatchInfo({
615
+ total: event.resultCount,
616
+ current: event.resultIndex >= 0 ? event.resultIndex + 1 : 0
617
+ });
618
+ });
619
+ terminal.attachCustomKeyEventHandler((e) => {
620
+ if (e.type === "keydown") {
621
+ if (pendingCtrlRef.current && e.key.length === 1 && !e.metaKey && !e.altKey && !e.ctrlKey) {
622
+ const lower = e.key.toLowerCase();
623
+ const code = lower.charCodeAt(0);
624
+ if (code >= 97 && code <= 122) {
625
+ terminal.input(String.fromCharCode(code - 96));
626
+ pendingCtrlRef.current = false;
627
+ setPendingCtrl(false);
628
+ e.preventDefault();
629
+ return false;
630
+ }
631
+ pendingCtrlRef.current = false;
632
+ setPendingCtrl(false);
633
+ }
634
+ if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey && e.key.toLowerCase() === "f") {
635
+ e.preventDefault();
636
+ openSearchRef.current();
637
+ return false;
638
+ }
639
+ if (e.key === "Enter" && e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey) {
640
+ terminal.input("\x1B[13;2u");
641
+ return false;
642
+ }
643
+ if (e.altKey && !e.metaKey && !e.ctrlKey) {
644
+ if (e.key === "ArrowLeft") {
645
+ terminal.input("\x1Bb");
646
+ return false;
647
+ }
648
+ if (e.key === "ArrowRight") {
649
+ terminal.input("\x1Bf");
650
+ return false;
651
+ }
652
+ }
653
+ }
654
+ return true;
655
+ });
656
+ terminalRef.current = terminal;
657
+ fitAddonRef.current = fitAddon;
658
+ searchAddonRef.current = searchAddon;
659
+ setTerminalReady(true);
660
+ const containerEl = containerRef.current;
661
+ let lastTouchY = null;
662
+ const onTouchStart = (e) => {
663
+ lastTouchY = e.touches.length === 1 ? e.touches[0].clientY : null;
664
+ };
665
+ const onTouchMove = (e) => {
666
+ if (e.touches.length !== 1 || lastTouchY === null) return;
667
+ const currentY = e.touches[0].clientY;
668
+ const deltaY = lastTouchY - currentY;
669
+ const viewport = containerEl.querySelector(".xterm-viewport");
670
+ const cellHeight = viewport && terminal.rows > 0 ? viewport.clientHeight / terminal.rows : 17;
671
+ const lineDelta = Math.trunc(deltaY / cellHeight);
672
+ if (lineDelta !== 0) {
673
+ terminal.scrollLines(lineDelta);
674
+ lastTouchY = currentY + (deltaY - lineDelta * cellHeight);
675
+ e.preventDefault();
676
+ }
677
+ };
678
+ const onTouchEnd = () => {
679
+ lastTouchY = null;
680
+ };
681
+ containerEl.addEventListener("touchstart", onTouchStart, { passive: true });
682
+ containerEl.addEventListener("touchmove", onTouchMove, { passive: false });
683
+ containerEl.addEventListener("touchend", onTouchEnd, { passive: true });
684
+ containerEl.addEventListener("touchcancel", onTouchEnd, { passive: true });
685
+ let longPressTimer = null;
686
+ let longPressStart = null;
687
+ const cancelLongPress = () => {
688
+ if (longPressTimer !== null) {
689
+ window.clearTimeout(longPressTimer);
690
+ longPressTimer = null;
691
+ }
692
+ longPressStart = null;
693
+ };
694
+ const onLongPressStart = (e) => {
695
+ cancelLongPress();
696
+ if (e.touches.length !== 1) return;
697
+ const t = e.touches[0];
698
+ longPressStart = { x: t.clientX, y: t.clientY };
699
+ longPressTimer = window.setTimeout(() => {
700
+ longPressTimer = null;
701
+ const start = longPressStart;
702
+ if (!start) return;
703
+ const screenEl = containerEl.querySelector(".xterm-screen");
704
+ if (!screenEl) return;
705
+ const cell = pointToCell(start.x, start.y, terminal, screenEl);
706
+ const lineText = getLineText(terminal, cell.row);
707
+ const { anchor, head } = wordSelectionAt(cell, lineText);
708
+ applySelection(terminal, anchor, head);
709
+ selectionAnchorRef.current = anchor;
710
+ selectionHeadRef.current = head;
711
+ setSelectionMode(true);
712
+ tapStartX = null;
713
+ tapStartY = null;
714
+ terminal.blur();
715
+ if (typeof navigator.vibrate === "function") {
716
+ try {
717
+ navigator.vibrate(15);
718
+ } catch {
719
+ }
720
+ }
721
+ }, LONG_PRESS_MS);
722
+ };
723
+ const onLongPressMove = (e) => {
724
+ if (!longPressStart || e.touches.length !== 1) return;
725
+ const t = e.touches[0];
726
+ const dx = Math.abs(t.clientX - longPressStart.x);
727
+ const dy = Math.abs(t.clientY - longPressStart.y);
728
+ if (dx > LONG_PRESS_SLOP_PX || dy > LONG_PRESS_SLOP_PX) cancelLongPress();
729
+ };
730
+ containerEl.addEventListener("touchstart", onLongPressStart, { passive: true });
731
+ containerEl.addEventListener("touchmove", onLongPressMove, { passive: true });
732
+ containerEl.addEventListener("touchend", cancelLongPress, { passive: true });
733
+ containerEl.addEventListener("touchcancel", cancelLongPress, { passive: true });
734
+ let tapStartX = null;
735
+ let tapStartY = null;
736
+ const onTapStart = (e) => {
737
+ if (e.touches.length === 1) {
738
+ tapStartX = e.touches[0].clientX;
739
+ tapStartY = e.touches[0].clientY;
740
+ } else {
741
+ tapStartX = null;
742
+ tapStartY = null;
743
+ }
744
+ };
745
+ const onTapEnd = (e) => {
746
+ const startX = tapStartX;
747
+ const startY = tapStartY;
748
+ tapStartX = null;
749
+ tapStartY = null;
750
+ if (startX === null || startY === null || e.changedTouches.length !== 1) return;
751
+ const dx = Math.abs(e.changedTouches[0].clientX - startX);
752
+ const dy = Math.abs(e.changedTouches[0].clientY - startY);
753
+ if (dx < 10 && dy < 10) {
754
+ if (selectionAnchorRef.current !== null) {
755
+ selectionAnchorRef.current = null;
756
+ selectionHeadRef.current = null;
757
+ setSelectionMode(false);
758
+ terminal.clearSelection();
759
+ }
760
+ terminal.focus();
761
+ }
762
+ };
763
+ const onTapCancel = () => {
764
+ tapStartX = null;
765
+ tapStartY = null;
766
+ };
767
+ containerEl.addEventListener("touchstart", onTapStart, { passive: true });
768
+ containerEl.addEventListener("touchend", onTapEnd, { passive: true });
769
+ containerEl.addEventListener("touchcancel", onTapCancel, { passive: true });
770
+ const proto = location.protocol === "https:" ? "wss:" : "ws:";
771
+ const ws = new WebSocket(
772
+ `${proto}//${location.host}/terminal?workspaceId=${encodeURIComponent(workspaceId)}&terminalId=${encodeURIComponent(terminalId)}`
773
+ );
774
+ wsRef.current = ws;
775
+ ws.binaryType = "arraybuffer";
776
+ ws.onopen = () => {
777
+ if (paneMetadata && (paneMetadata.command || paneMetadata.cwd || paneMetadata.env)) {
778
+ const initMsg = { type: "init" };
779
+ if (paneMetadata.command) initMsg.command = paneMetadata.command;
780
+ if (paneMetadata.cwd) initMsg.cwd = paneMetadata.cwd;
781
+ if (paneMetadata.env) initMsg.env = paneMetadata.env;
782
+ ws.send(JSON.stringify(initMsg));
783
+ }
784
+ fitAddon.fit();
785
+ ws.send(
786
+ JSON.stringify({
787
+ type: "resize",
788
+ cols: terminal.cols,
789
+ rows: terminal.rows
790
+ })
791
+ );
792
+ if (autoFocus) {
793
+ terminal.focus();
794
+ }
795
+ };
796
+ ws.onmessage = (event) => {
797
+ if (event.data instanceof ArrayBuffer) {
798
+ terminal.write(new Uint8Array(event.data));
799
+ } else {
800
+ try {
801
+ const msg = JSON.parse(event.data);
802
+ if (msg.type === "title" && typeof msg.title === "string") {
803
+ onTitleChangeRef.current?.(msg.title);
804
+ }
805
+ } catch {
806
+ terminal.write(event.data);
807
+ }
808
+ }
809
+ };
810
+ ws.onclose = () => {
811
+ terminal.write("\r\n\x1B[90m[Terminal disconnected]\x1B[0m\r\n");
812
+ };
813
+ terminal.onData((data) => {
814
+ if (ws.readyState === WebSocket.OPEN) {
815
+ ws.send(data);
816
+ }
817
+ });
818
+ terminal.onTitleChange((title) => {
819
+ onTitleChangeRef.current?.(title);
820
+ });
821
+ let selectionRafId = null;
822
+ const reapplySelectionOnNextFrame = () => {
823
+ if (selectionRafId !== null) return;
824
+ if (!selectionAnchorRef.current || !selectionHeadRef.current) return;
825
+ selectionRafId = requestAnimationFrame(() => {
826
+ selectionRafId = null;
827
+ const anchor = selectionAnchorRef.current;
828
+ const head = selectionHeadRef.current;
829
+ if (anchor && head) applySelection(terminal, anchor, head);
830
+ });
831
+ };
832
+ const selectionResizeDisposable = terminal.onResize(reapplySelectionOnNextFrame);
833
+ let lastDpr = window.devicePixelRatio;
834
+ const handleDprChange = () => {
835
+ const currentDpr = window.devicePixelRatio;
836
+ if (currentDpr === lastDpr) return;
837
+ lastDpr = currentDpr;
838
+ const fs = terminal.options.fontSize;
839
+ if (typeof fs === "number") {
840
+ terminal.options.fontSize = fs + 1;
841
+ terminal.options.fontSize = fs;
842
+ }
843
+ const addon = webglAddonRef.current;
844
+ if (addon) {
845
+ addon.dispose();
846
+ webglAddonRef.current = null;
847
+ attachWebGL();
848
+ }
849
+ fitAddon.fit();
850
+ };
851
+ const resizeObserver = new ResizeObserver((entries) => {
852
+ const entry = entries[0];
853
+ if (!entry || entry.contentRect.width === 0 || entry.contentRect.height === 0) return;
854
+ handleDprChange();
855
+ fitAddon.fit();
856
+ if (ws.readyState === WebSocket.OPEN && terminal.cols > 0 && terminal.rows > 0) {
857
+ ws.send(
858
+ JSON.stringify({
859
+ type: "resize",
860
+ cols: terminal.cols,
861
+ rows: terminal.rows
862
+ })
863
+ );
864
+ }
865
+ });
866
+ resizeObserver.observe(containerRef.current);
867
+ let dprMql;
868
+ const bindDprListener = () => {
869
+ dprMql = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
870
+ dprMql.addEventListener("change", onDprMediaChange);
871
+ };
872
+ const onDprMediaChange = () => {
873
+ handleDprChange();
874
+ dprMql?.removeEventListener("change", onDprMediaChange);
875
+ bindDprListener();
876
+ };
877
+ bindDprListener();
878
+ cleanup = () => {
879
+ themeObserver.disconnect();
880
+ resizeObserver.disconnect();
881
+ searchResultsDisposable.dispose();
882
+ selectionResizeDisposable.dispose();
883
+ if (selectionRafId !== null) cancelAnimationFrame(selectionRafId);
884
+ webglContextLossDisposable?.dispose();
885
+ dprMql?.removeEventListener("change", onDprMediaChange);
886
+ cancelLongPress();
887
+ containerEl.removeEventListener("touchstart", onTouchStart);
888
+ containerEl.removeEventListener("touchmove", onTouchMove);
889
+ containerEl.removeEventListener("touchend", onTouchEnd);
890
+ containerEl.removeEventListener("touchcancel", onTouchEnd);
891
+ containerEl.removeEventListener("touchstart", onLongPressStart);
892
+ containerEl.removeEventListener("touchmove", onLongPressMove);
893
+ containerEl.removeEventListener("touchend", cancelLongPress);
894
+ containerEl.removeEventListener("touchcancel", cancelLongPress);
895
+ containerEl.removeEventListener("touchstart", onTapStart);
896
+ containerEl.removeEventListener("touchend", onTapEnd);
897
+ containerEl.removeEventListener("touchcancel", onTapCancel);
898
+ ws.close();
899
+ terminal.dispose();
900
+ terminalRef.current = null;
901
+ fitAddonRef.current = null;
902
+ searchAddonRef.current = null;
903
+ webglAddonRef.current = null;
904
+ wsRef.current = null;
905
+ selectionAnchorRef.current = null;
906
+ selectionHeadRef.current = null;
907
+ pendingCtrlRef.current = false;
908
+ setSelectionMode(false);
909
+ setPendingCtrl(false);
910
+ setTerminalReady(false);
911
+ };
912
+ });
913
+ return () => {
914
+ cancelled = true;
915
+ cleanup?.();
916
+ };
917
+ }, [terminalId, workspaceId, paneMetadata, autoFocus]);
918
+ reactExports.useEffect(() => {
919
+ if (visible && fitAddonRef.current) {
920
+ requestAnimationFrame(() => {
921
+ fitAddonRef.current?.fit();
922
+ const term = terminalRef.current;
923
+ const ws = wsRef.current;
924
+ if (term && ws?.readyState === WebSocket.OPEN && term.cols > 0 && term.rows > 0) {
925
+ ws.send(JSON.stringify({ type: "resize", cols: term.cols, rows: term.rows }));
926
+ }
927
+ });
928
+ }
929
+ }, [visible]);
930
+ reactExports.useEffect(() => {
931
+ const handler = () => {
932
+ if (!visible) return;
933
+ terminalRef.current?.focus();
934
+ };
935
+ window.addEventListener("band:focus-terminal", handler);
936
+ return () => window.removeEventListener("band:focus-terminal", handler);
937
+ }, [visible]);
938
+ const handleOpenSearch = reactExports.useCallback(() => {
939
+ setSearchOpen(true);
940
+ requestAnimationFrame(() => {
941
+ searchBarRef.current?.focus();
942
+ searchBarRef.current?.select();
943
+ });
944
+ }, []);
945
+ openSearchRef.current = handleOpenSearch;
946
+ const handleCloseSearch = reactExports.useCallback(() => {
947
+ searchAddonRef.current?.clearDecorations();
948
+ setSearchOpen(false);
949
+ setSearchQuery("");
950
+ setMatchInfo({ total: 0, current: 0 });
951
+ terminalRef.current?.focus();
952
+ }, []);
953
+ const handleNext = reactExports.useCallback(() => {
954
+ if (!searchQuery) return;
955
+ searchAddonRef.current?.findNext(searchQuery, toXtermSearchOptions(searchOptions));
956
+ }, [searchQuery, searchOptions]);
957
+ const handlePrevious = reactExports.useCallback(() => {
958
+ if (!searchQuery) return;
959
+ searchAddonRef.current?.findPrevious(searchQuery, toXtermSearchOptions(searchOptions));
960
+ }, [searchQuery, searchOptions]);
961
+ reactExports.useEffect(() => {
962
+ const addon = searchAddonRef.current;
963
+ if (!addon) return;
964
+ if (!searchQuery) {
965
+ addon.clearDecorations();
966
+ setMatchInfo({ total: 0, current: 0 });
967
+ return;
968
+ }
969
+ addon.findNext(searchQuery, toXtermSearchOptions(searchOptions));
970
+ }, [searchQuery, searchOptions]);
971
+ const { contentBottomInset } = useVirtualKeyboardToolbar();
972
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex h-full w-full flex-col", children: [
973
+ searchOpen && /* @__PURE__ */ jsxRuntimeExports.jsx(
974
+ SearchBar,
975
+ {
976
+ ref: searchBarRef,
977
+ query: searchQuery,
978
+ onQueryChange: setSearchQuery,
979
+ options: searchOptions,
980
+ onOptionsChange: setSearchOptions,
981
+ placeholder: "Find in terminal...",
982
+ matchInfo,
983
+ onNext: handleNext,
984
+ onPrevious: handlePrevious,
985
+ onClose: handleCloseSearch
986
+ }
987
+ ),
988
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "relative min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
989
+ "div",
990
+ {
991
+ ref: containerRef,
992
+ className: "absolute inset-x-2 top-2 overflow-hidden",
993
+ style: { bottom: 8 + contentBottomInset }
994
+ }
995
+ ) }),
996
+ terminalReady && terminalRef.current && /* @__PURE__ */ jsxRuntimeExports.jsx(
997
+ TerminalToolbar,
998
+ {
999
+ terminal: terminalRef.current,
1000
+ sendInput: (data) => {
1001
+ const ws = wsRef.current;
1002
+ if (ws?.readyState === WebSocket.OPEN) ws.send(data);
1003
+ },
1004
+ pendingCtrl,
1005
+ onToggleCtrl: handleToggleCtrl,
1006
+ selectionMode,
1007
+ onExtendSelection: handleExtendSelection,
1008
+ onExitSelection: exitSelectionMode,
1009
+ onSelectAll: handleSelectAll
1010
+ }
1011
+ )
1012
+ ] });
1013
+ }
1014
+ export {
1015
+ TerminalPanel
1016
+ };