@zythum02/fello-server 0.1.53 → 0.1.54

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 (380) hide show
  1. package/out/renderer/assets/{_baseUniq-CJr3HkLS.js → _baseUniq-DYINnBRJ.js} +1 -1
  2. package/out/renderer/assets/_baseUniq-DYINnBRJ.js.br +0 -0
  3. package/out/renderer/assets/_baseUniq-DYINnBRJ.js.gz +0 -0
  4. package/out/renderer/assets/{arc-POsBroTF.js → arc-BSUyw88k.js} +1 -1
  5. package/out/renderer/assets/arc-BSUyw88k.js.br +0 -0
  6. package/out/renderer/assets/arc-BSUyw88k.js.gz +0 -0
  7. package/out/renderer/assets/{architectureDiagram-Q4EWVU46-CmToUhDb.js → architectureDiagram-Q4EWVU46-Cxb8DhYZ.js} +6 -6
  8. package/out/renderer/assets/architectureDiagram-Q4EWVU46-Cxb8DhYZ.js.br +0 -0
  9. package/out/renderer/assets/architectureDiagram-Q4EWVU46-Cxb8DhYZ.js.gz +0 -0
  10. package/out/renderer/assets/{arrow-left-CxS1t3f7.js → arrow-left-CQqe9rrj.js} +1 -1
  11. package/out/renderer/assets/arrow-up-1eI4tva4.js +21 -0
  12. package/out/renderer/assets/{automation-Cyz3eLWp.js → automation-CQAOpWYp.js} +7 -7
  13. package/out/renderer/assets/automation-CQAOpWYp.js.br +0 -0
  14. package/out/renderer/assets/automation-CQAOpWYp.js.gz +0 -0
  15. package/out/renderer/assets/{blockDiagram-DXYQGD6D-M2nnTg9f.js → blockDiagram-DXYQGD6D-CFozis-v.js} +7 -7
  16. package/out/renderer/assets/blockDiagram-DXYQGD6D-CFozis-v.js.br +0 -0
  17. package/out/renderer/assets/blockDiagram-DXYQGD6D-CFozis-v.js.gz +0 -0
  18. package/out/renderer/assets/{c4Diagram-AHTNJAMY-CwLtsy_0.js → c4Diagram-AHTNJAMY-CcDDkZUp.js} +3 -3
  19. package/out/renderer/assets/c4Diagram-AHTNJAMY-CcDDkZUp.js.br +0 -0
  20. package/out/renderer/assets/c4Diagram-AHTNJAMY-CcDDkZUp.js.gz +0 -0
  21. package/out/renderer/assets/{channel-BUNDMqpH.js → channel-B-VC_ZcK.js} +1 -1
  22. package/out/renderer/assets/{chunk-4BX2VUAB-B2qXmkDT.js → chunk-4BX2VUAB-ClHmnOTC.js} +1 -1
  23. package/out/renderer/assets/{chunk-4TB4RGXK-DXLZpPY5.js → chunk-4TB4RGXK-mwOvn19G.js} +5 -5
  24. package/out/renderer/assets/chunk-4TB4RGXK-mwOvn19G.js.br +0 -0
  25. package/out/renderer/assets/chunk-4TB4RGXK-mwOvn19G.js.gz +0 -0
  26. package/out/renderer/assets/{chunk-55IACEB6-CJeyefxI.js → chunk-55IACEB6-CE8f6iip.js} +1 -1
  27. package/out/renderer/assets/{chunk-EDXVE4YY-CNjJEQfY.js → chunk-EDXVE4YY-CU7aY96h.js} +1 -1
  28. package/out/renderer/assets/chunk-EDXVE4YY-CU7aY96h.js.br +0 -0
  29. package/out/renderer/assets/chunk-EDXVE4YY-CU7aY96h.js.gz +0 -0
  30. package/out/renderer/assets/{chunk-FMBD7UC4-DOAOsjRu.js → chunk-FMBD7UC4-B38kFkjv.js} +1 -1
  31. package/out/renderer/assets/{chunk-OYMX7WX6-BG4B1VQ7.js → chunk-OYMX7WX6-BriTCtaz.js} +3 -3
  32. package/out/renderer/assets/chunk-OYMX7WX6-BriTCtaz.js.br +0 -0
  33. package/out/renderer/assets/chunk-OYMX7WX6-BriTCtaz.js.gz +0 -0
  34. package/out/renderer/assets/{chunk-QZHKN3VN-B9zfXYIQ.js → chunk-QZHKN3VN-BwJ37p5G.js} +1 -1
  35. package/out/renderer/assets/{chunk-YZCP3GAM-jeoI2tsD.js → chunk-YZCP3GAM-BlHAYoQe.js} +1 -1
  36. package/out/renderer/assets/chunk-YZCP3GAM-BlHAYoQe.js.br +0 -0
  37. package/out/renderer/assets/chunk-YZCP3GAM-BlHAYoQe.js.gz +0 -0
  38. package/out/renderer/assets/{circle-x-B1kBsMlS.js → circle-x-D_gJIgxf.js} +1 -1
  39. package/out/renderer/assets/{classDiagram-v2-HSJHXN6E-DWPFF3Yt.js → classDiagram-6PBFFD2Q-D01ZMeaj.js} +7 -7
  40. package/out/renderer/assets/{classDiagram-6PBFFD2Q-DWPFF3Yt.js → classDiagram-v2-HSJHXN6E-D01ZMeaj.js} +7 -7
  41. package/out/renderer/assets/{clone-Dcvr9oKv.js → clone-qctAbdCx.js} +1 -1
  42. package/out/renderer/assets/{code-editor-CEXlC4aV.js → code-editor-tm0AYOLz.js} +2 -2
  43. package/out/renderer/assets/code-editor-tm0AYOLz.js.br +0 -0
  44. package/out/renderer/assets/code-editor-tm0AYOLz.js.gz +0 -0
  45. package/out/renderer/assets/{collapsible-CMuCJUWG.js → collapsible-DD6NlDid.js} +1 -1
  46. package/out/renderer/assets/collapsible-DD6NlDid.js.br +0 -0
  47. package/out/renderer/assets/collapsible-DD6NlDid.js.gz +0 -0
  48. package/out/renderer/assets/command-BF4jOeoL.js +11 -0
  49. package/out/renderer/assets/{cose-bilkent-S5V4N54A-B3bgImVS.js → cose-bilkent-S5V4N54A-CF4brbsf.js} +2 -2
  50. package/out/renderer/assets/cose-bilkent-S5V4N54A-CF4brbsf.js.br +0 -0
  51. package/out/renderer/assets/cose-bilkent-S5V4N54A-CF4brbsf.js.gz +0 -0
  52. package/out/renderer/assets/{dagre-KV5264BT-DTbumBA_.js → dagre-KV5264BT-C6I5VgRp.js} +7 -7
  53. package/out/renderer/assets/dagre-KV5264BT-C6I5VgRp.js.br +0 -0
  54. package/out/renderer/assets/dagre-KV5264BT-C6I5VgRp.js.gz +0 -0
  55. package/out/renderer/assets/{diagram-5BDNPKRD-B34Y6e8q.js → diagram-5BDNPKRD-BAO72D5R.js} +7 -7
  56. package/out/renderer/assets/diagram-5BDNPKRD-BAO72D5R.js.br +0 -0
  57. package/out/renderer/assets/diagram-5BDNPKRD-BAO72D5R.js.gz +0 -0
  58. package/out/renderer/assets/{diagram-G4DWMVQ6-BBiBmFR4.js → diagram-G4DWMVQ6-BmpkrtJs.js} +7 -7
  59. package/out/renderer/assets/diagram-G4DWMVQ6-BmpkrtJs.js.br +0 -0
  60. package/out/renderer/assets/diagram-G4DWMVQ6-BmpkrtJs.js.gz +0 -0
  61. package/out/renderer/assets/{diagram-MMDJMWI5-P-YslDjG.js → diagram-MMDJMWI5-8keZZjgB.js} +6 -6
  62. package/out/renderer/assets/diagram-MMDJMWI5-8keZZjgB.js.br +0 -0
  63. package/out/renderer/assets/diagram-MMDJMWI5-8keZZjgB.js.gz +0 -0
  64. package/out/renderer/assets/{diagram-TYMM5635-D_cLard_.js → diagram-TYMM5635-Be4uDvHI.js} +6 -6
  65. package/out/renderer/assets/diagram-TYMM5635-Be4uDvHI.js.br +0 -0
  66. package/out/renderer/assets/diagram-TYMM5635-Be4uDvHI.js.gz +0 -0
  67. package/out/renderer/assets/{ellipsis-D1agTYu1.js → ellipsis-92s4sSUO.js} +1 -1
  68. package/out/renderer/assets/{erDiagram-SMLLAGMA-C1MHqKvC.js → erDiagram-SMLLAGMA-C6IgAbhi.js} +5 -5
  69. package/out/renderer/assets/erDiagram-SMLLAGMA-C6IgAbhi.js.br +0 -0
  70. package/out/renderer/assets/erDiagram-SMLLAGMA-C6IgAbhi.js.gz +0 -0
  71. package/out/renderer/assets/{field-DR3J0r9e.js → field-BPsDfe4e.js} +1 -1
  72. package/out/renderer/assets/field-BPsDfe4e.js.br +0 -0
  73. package/out/renderer/assets/field-BPsDfe4e.js.gz +0 -0
  74. package/out/renderer/assets/{file-text-nGCW6zu1.js → file-text-ITbWr8iW.js} +1 -1
  75. package/out/renderer/assets/{flowDiagram-DWJPFMVM-DprlEc3Z.js → flowDiagram-DWJPFMVM-vbYKBn4t.js} +7 -7
  76. package/out/renderer/assets/flowDiagram-DWJPFMVM-vbYKBn4t.js.br +0 -0
  77. package/out/renderer/assets/flowDiagram-DWJPFMVM-vbYKBn4t.js.gz +0 -0
  78. package/out/renderer/assets/{ganttDiagram-T4ZO3ILL-CbTdumBm.js → ganttDiagram-T4ZO3ILL-AxXIe9I4.js} +3 -3
  79. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-AxXIe9I4.js.br +0 -0
  80. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-AxXIe9I4.js.gz +0 -0
  81. package/out/renderer/assets/{gitGraphDiagram-UUTBAWPF-06bme-w8.js → gitGraphDiagram-UUTBAWPF-DSipARMB.js} +7 -7
  82. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-DSipARMB.js.br +0 -0
  83. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-DSipARMB.js.gz +0 -0
  84. package/out/renderer/assets/{graph-BZhxluo9.js → graph-mNaHfg3r.js} +2 -2
  85. package/out/renderer/assets/graph-mNaHfg3r.js.br +0 -0
  86. package/out/renderer/assets/graph-mNaHfg3r.js.gz +0 -0
  87. package/out/renderer/assets/{highlighted-body-OFNGDK62-CvDMJtXf.js → highlighted-body-OFNGDK62-8846XFj-.js} +2 -2
  88. package/out/renderer/assets/{index-LmYTNvdF.js → index-BUwXrbHW.js} +1643 -776
  89. package/out/renderer/assets/index-BUwXrbHW.js.br +0 -0
  90. package/out/renderer/assets/index-BUwXrbHW.js.gz +0 -0
  91. package/out/renderer/assets/index-DOIzYXAl.css +382 -0
  92. package/out/renderer/assets/index-DOIzYXAl.css.br +0 -0
  93. package/out/renderer/assets/index-DOIzYXAl.css.gz +0 -0
  94. package/out/renderer/assets/{infoDiagram-42DDH7IO-DqivEzWL.js → infoDiagram-42DDH7IO-ThYxaM6U.js} +5 -5
  95. package/out/renderer/assets/infoDiagram-42DDH7IO-ThYxaM6U.js.br +0 -0
  96. package/out/renderer/assets/infoDiagram-42DDH7IO-ThYxaM6U.js.gz +0 -0
  97. package/out/renderer/assets/{ishikawaDiagram-UXIWVN3A-BKcg_z4w.js → ishikawaDiagram-UXIWVN3A-EcWEDDQ3.js} +2 -2
  98. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-EcWEDDQ3.js.br +0 -0
  99. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-EcWEDDQ3.js.gz +0 -0
  100. package/out/renderer/assets/{item-BHEUMM9H.js → item-Dph2aCdz.js} +20 -2
  101. package/out/renderer/assets/item-Dph2aCdz.js.br +0 -0
  102. package/out/renderer/assets/item-Dph2aCdz.js.gz +0 -0
  103. package/out/renderer/assets/{journeyDiagram-VCZTEJTY-Bvv8xuxQ.js → journeyDiagram-VCZTEJTY-Ct6VLkXK.js} +5 -5
  104. package/out/renderer/assets/journeyDiagram-VCZTEJTY-Ct6VLkXK.js.br +0 -0
  105. package/out/renderer/assets/journeyDiagram-VCZTEJTY-Ct6VLkXK.js.gz +0 -0
  106. package/out/renderer/assets/{kanban-definition-6JOO6SKY-C-gRMpeM.js → kanban-definition-6JOO6SKY-DHWulQen.js} +3 -3
  107. package/out/renderer/assets/kanban-definition-6JOO6SKY-DHWulQen.js.br +0 -0
  108. package/out/renderer/assets/kanban-definition-6JOO6SKY-DHWulQen.js.gz +0 -0
  109. package/out/renderer/assets/{layout-B4dSyItA.js → layout-pfquJ3N_.js} +4 -4
  110. package/out/renderer/assets/layout-pfquJ3N_.js.br +0 -0
  111. package/out/renderer/assets/layout-pfquJ3N_.js.gz +0 -0
  112. package/out/renderer/assets/{linear-CoVhuer7.js → linear-CdfVBcAB.js} +1 -1
  113. package/out/renderer/assets/linear-CdfVBcAB.js.br +0 -0
  114. package/out/renderer/assets/linear-CdfVBcAB.js.gz +0 -0
  115. package/out/renderer/assets/{link-2-DHUPzNSt.js → link-2-DpdZfD3m.js} +1 -1
  116. package/out/renderer/assets/{mermaid-GHXKKRXX-CZqkhGx7.js → mermaid-GHXKKRXX-CqMNodCp.js} +36 -36
  117. package/out/renderer/assets/mermaid-GHXKKRXX-CqMNodCp.js.br +0 -0
  118. package/out/renderer/assets/mermaid-GHXKKRXX-CqMNodCp.js.gz +0 -0
  119. package/out/renderer/assets/{mic-BgSvicCB.js → mic-CT1bYBEV.js} +1 -1
  120. package/out/renderer/assets/{min-emzuJjmk.js → min-CiK16GFr.js} +2 -2
  121. package/out/renderer/assets/min-CiK16GFr.js.br +0 -0
  122. package/out/renderer/assets/min-CiK16GFr.js.gz +0 -0
  123. package/out/renderer/assets/{mindmap-definition-QFDTVHPH-DQ4JNECm.js → mindmap-definition-QFDTVHPH-BvmM-Xdx.js} +4 -4
  124. package/out/renderer/assets/mindmap-definition-QFDTVHPH-BvmM-Xdx.js.br +0 -0
  125. package/out/renderer/assets/mindmap-definition-QFDTVHPH-BvmM-Xdx.js.gz +0 -0
  126. package/out/renderer/assets/{open-guide-CfLO-Sdk.js → open-guide-BqiUQfrM.js} +1 -1
  127. package/out/renderer/assets/{package-search-CrF2Iegl.js → package-search-BxIuIl9F.js} +1 -1
  128. package/out/renderer/assets/{pieDiagram-DEJITSTG-0H6CGQQt.js → pieDiagram-DEJITSTG-CQY4NZ_4.js} +7 -7
  129. package/out/renderer/assets/pieDiagram-DEJITSTG-CQY4NZ_4.js.br +0 -0
  130. package/out/renderer/assets/pieDiagram-DEJITSTG-CQY4NZ_4.js.gz +0 -0
  131. package/out/renderer/assets/{plus-YNCXW-GD.js → plus-C5XdFVFm.js} +1 -1
  132. package/out/renderer/assets/{quadrantDiagram-34T5L4WZ-D0aPKp5z.js → quadrantDiagram-34T5L4WZ-BiDWKNht.js} +3 -3
  133. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-BiDWKNht.js.br +0 -0
  134. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-BiDWKNht.js.gz +0 -0
  135. package/out/renderer/assets/{requirementDiagram-MS252O5E-BkzwapW_.js → requirementDiagram-MS252O5E-D-KxL9Tf.js} +4 -4
  136. package/out/renderer/assets/requirementDiagram-MS252O5E-D-KxL9Tf.js.br +0 -0
  137. package/out/renderer/assets/requirementDiagram-MS252O5E-D-KxL9Tf.js.gz +0 -0
  138. package/out/renderer/assets/{resizable-cStzNJ8V.js → resizable-ObbINbIB.js} +1 -1
  139. package/out/renderer/assets/resizable-ObbINbIB.js.br +0 -0
  140. package/out/renderer/assets/resizable-ObbINbIB.js.gz +0 -0
  141. package/out/renderer/assets/{sankeyDiagram-XADWPNL6-Dbde7usj.js → sankeyDiagram-XADWPNL6-BIFbqkzs.js} +2 -2
  142. package/out/renderer/assets/sankeyDiagram-XADWPNL6-BIFbqkzs.js.br +0 -0
  143. package/out/renderer/assets/sankeyDiagram-XADWPNL6-BIFbqkzs.js.gz +0 -0
  144. package/out/renderer/assets/{schedule-DNMCsk-G.js → schedule-BtuArq_x.js} +9 -9
  145. package/out/renderer/assets/schedule-BtuArq_x.js.br +0 -0
  146. package/out/renderer/assets/schedule-BtuArq_x.js.gz +0 -0
  147. package/out/renderer/assets/{search-BEY9yGF_.js → search-TCnuQyCi.js} +1 -1
  148. package/out/renderer/assets/{sequenceDiagram-FGHM5R23-DI8l1pSL.js → sequenceDiagram-FGHM5R23-DQX-_zuj.js} +4 -4
  149. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DQX-_zuj.js.br +0 -0
  150. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DQX-_zuj.js.gz +0 -0
  151. package/out/renderer/assets/{session-Bn5k9ScR.js → session-C_1BpGhU.js} +956 -269
  152. package/out/renderer/assets/session-C_1BpGhU.js.br +0 -0
  153. package/out/renderer/assets/session-C_1BpGhU.js.gz +0 -0
  154. package/out/renderer/assets/{setting-dialog-sqfPfGsy.js → setting-dialog-D1_-4H95.js} +3 -3
  155. package/out/renderer/assets/setting-dialog-D1_-4H95.js.br +0 -0
  156. package/out/renderer/assets/setting-dialog-D1_-4H95.js.gz +0 -0
  157. package/out/renderer/assets/{settings-2-DRhoXOO8.js → settings-2-BwfZrIw6.js} +1 -1
  158. package/out/renderer/assets/{settings-agents-Bntc31Nn.js → settings-agents-BtuYXQ1V.js} +26 -14
  159. package/out/renderer/assets/settings-agents-BtuYXQ1V.js.br +0 -0
  160. package/out/renderer/assets/settings-agents-BtuYXQ1V.js.gz +0 -0
  161. package/out/renderer/assets/{settings-general-DhbLb9cP.js → settings-general-cHqsKFFa.js} +36 -3
  162. package/out/renderer/assets/settings-general-cHqsKFFa.js.br +0 -0
  163. package/out/renderer/assets/settings-general-cHqsKFFa.js.gz +0 -0
  164. package/out/renderer/assets/{settings-ilink-C7nGGjwT.js → settings-ilink-BR1Vd9t9.js} +3 -3
  165. package/out/renderer/assets/settings-ilink-BR1Vd9t9.js.br +0 -0
  166. package/out/renderer/assets/settings-ilink-BR1Vd9t9.js.gz +0 -0
  167. package/out/renderer/assets/{settings-image-generation-H2dgqG7Y.js → settings-image-generation-MUHYnpbm.js} +6 -6
  168. package/out/renderer/assets/settings-image-generation-MUHYnpbm.js.br +0 -0
  169. package/out/renderer/assets/settings-image-generation-MUHYnpbm.js.gz +0 -0
  170. package/out/renderer/assets/{settings-layout-ATto1xpJ.js → settings-layout-SBihzFfb.js} +10 -3
  171. package/out/renderer/assets/settings-layout-SBihzFfb.js.br +0 -0
  172. package/out/renderer/assets/settings-layout-SBihzFfb.js.gz +0 -0
  173. package/out/renderer/assets/{settings-mcp-DUdMuoJ-.js → settings-mcp-Co88s-0y.js} +8 -8
  174. package/out/renderer/assets/settings-mcp-Co88s-0y.js.br +0 -0
  175. package/out/renderer/assets/settings-mcp-Co88s-0y.js.gz +0 -0
  176. package/out/renderer/assets/{settings-memory-CJLG4aHW.js → settings-memory-CNH9gHYC.js} +2 -3
  177. package/out/renderer/assets/settings-memory-CNH9gHYC.js.br +0 -0
  178. package/out/renderer/assets/settings-memory-CNH9gHYC.js.gz +0 -0
  179. package/out/renderer/assets/settings-shortcuts-C1s7YIMj.js +267 -0
  180. package/out/renderer/assets/settings-shortcuts-C1s7YIMj.js.br +0 -0
  181. package/out/renderer/assets/settings-shortcuts-C1s7YIMj.js.gz +0 -0
  182. package/out/renderer/assets/{settings-snippets-B4VcnD5Z.js → settings-snippets-DGgI6mxm.js} +7 -7
  183. package/out/renderer/assets/settings-snippets-DGgI6mxm.js.br +0 -0
  184. package/out/renderer/assets/settings-snippets-DGgI6mxm.js.gz +0 -0
  185. package/out/renderer/assets/{settings-speech-to-text-DQ7lfkTu.js → settings-speech-to-text-CV0xM7yz.js} +5 -5
  186. package/out/renderer/assets/settings-speech-to-text-CV0xM7yz.js.br +0 -0
  187. package/out/renderer/assets/settings-speech-to-text-CV0xM7yz.js.gz +0 -0
  188. package/out/renderer/assets/{settings-webui-DZf9O-6j.js → settings-webui-Bj9dJDcm.js} +2 -2
  189. package/out/renderer/assets/settings-webui-Bj9dJDcm.js.br +0 -0
  190. package/out/renderer/assets/settings-webui-Bj9dJDcm.js.gz +0 -0
  191. package/out/renderer/assets/{skills-installed-Dp0r_4I-.js → skills-installed-Bhd5a33I.js} +4 -4
  192. package/out/renderer/assets/skills-installed-Bhd5a33I.js.br +0 -0
  193. package/out/renderer/assets/skills-installed-Bhd5a33I.js.gz +0 -0
  194. package/out/renderer/assets/{skills-layout-D-5rlY38.js → skills-layout-DZFDa1cw.js} +2 -2
  195. package/out/renderer/assets/skills-layout-DZFDa1cw.js.br +0 -0
  196. package/out/renderer/assets/skills-layout-DZFDa1cw.js.gz +0 -0
  197. package/out/renderer/assets/{skills-skills-sh-CcLoIrSw.js → skills-skills-sh-DF59nekm.js} +4 -4
  198. package/out/renderer/assets/skills-skills-sh-DF59nekm.js.br +0 -0
  199. package/out/renderer/assets/skills-skills-sh-DF59nekm.js.gz +0 -0
  200. package/out/renderer/assets/{sortable.esm-knFxDx0Y.js → sortable.esm-BlhN8Kkg.js} +1 -1
  201. package/out/renderer/assets/sortable.esm-BlhN8Kkg.js.br +0 -0
  202. package/out/renderer/assets/sortable.esm-BlhN8Kkg.js.gz +0 -0
  203. package/out/renderer/assets/{standard-schema-dKXoCekr.js → standard-schema-CGAs4bGi.js} +1 -1
  204. package/out/renderer/assets/standard-schema-CGAs4bGi.js.br +0 -0
  205. package/out/renderer/assets/standard-schema-CGAs4bGi.js.gz +0 -0
  206. package/out/renderer/assets/{stateDiagram-FHFEXIEX-DWWz4PMv.js → stateDiagram-FHFEXIEX-DappRrGm.js} +9 -9
  207. package/out/renderer/assets/stateDiagram-FHFEXIEX-DappRrGm.js.br +0 -0
  208. package/out/renderer/assets/stateDiagram-FHFEXIEX-DappRrGm.js.gz +0 -0
  209. package/out/renderer/assets/{stateDiagram-v2-QKLJ7IA2-Dm2qD5bg.js → stateDiagram-v2-QKLJ7IA2-mbgJN2Ya.js} +5 -5
  210. package/out/renderer/assets/{task-C5dyYbfn.js → task-C7tCZ6e3.js} +11 -11
  211. package/out/renderer/assets/task-C7tCZ6e3.js.br +0 -0
  212. package/out/renderer/assets/task-C7tCZ6e3.js.gz +0 -0
  213. package/out/renderer/assets/{textarea-DTqKlQbL.js → textarea-DNSPhqFr.js} +2 -2
  214. package/out/renderer/assets/{timeline-definition-GMOUNBTQ-A1tEoL9d.js → timeline-definition-GMOUNBTQ-o8XIUDyn.js} +3 -3
  215. package/out/renderer/assets/timeline-definition-GMOUNBTQ-o8XIUDyn.js.br +0 -0
  216. package/out/renderer/assets/timeline-definition-GMOUNBTQ-o8XIUDyn.js.gz +0 -0
  217. package/out/renderer/assets/{vennDiagram-DHZGUBPP-tNdYrJi_.js → vennDiagram-DHZGUBPP-mnc6bpmR.js} +2 -2
  218. package/out/renderer/assets/vennDiagram-DHZGUBPP-mnc6bpmR.js.br +0 -0
  219. package/out/renderer/assets/vennDiagram-DHZGUBPP-mnc6bpmR.js.gz +0 -0
  220. package/out/renderer/assets/{wardley-RL74JXVD-BxN5_Sp6.js → wardley-RL74JXVD-wdJYeEiD.js} +4 -4
  221. package/out/renderer/assets/wardley-RL74JXVD-wdJYeEiD.js.br +0 -0
  222. package/out/renderer/assets/wardley-RL74JXVD-wdJYeEiD.js.gz +0 -0
  223. package/out/renderer/assets/{wardleyDiagram-NUSXRM2D-B_3jA8zU.js → wardleyDiagram-NUSXRM2D-Ddx6k7tJ.js} +6 -6
  224. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-Ddx6k7tJ.js.br +0 -0
  225. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-Ddx6k7tJ.js.gz +0 -0
  226. package/out/renderer/assets/{wrench-7r-g9MUq.js → wrench-BsjH8RPm.js} +1 -1
  227. package/out/renderer/assets/wrench-BsjH8RPm.js.br +0 -0
  228. package/out/renderer/assets/wrench-BsjH8RPm.js.gz +0 -0
  229. package/out/renderer/assets/{xlsx-view-Bv0YhA5m.js → xlsx-view-CQd4jbk-.js} +21 -13
  230. package/out/renderer/assets/xlsx-view-CQd4jbk-.js.br +0 -0
  231. package/out/renderer/assets/xlsx-view-CQd4jbk-.js.gz +0 -0
  232. package/out/renderer/assets/{xychartDiagram-5P7HB3ND-NNVuzC4j.js → xychartDiagram-5P7HB3ND-VIQ9wuz0.js} +3 -3
  233. package/out/renderer/assets/xychartDiagram-5P7HB3ND-VIQ9wuz0.js.br +0 -0
  234. package/out/renderer/assets/xychartDiagram-5P7HB3ND-VIQ9wuz0.js.gz +0 -0
  235. package/out/renderer/index.html +2 -2
  236. package/out/renderer/index.html.br +0 -0
  237. package/out/renderer/index.html.gz +0 -0
  238. package/out/scripts/mcp-skills/server.mjs +1 -1
  239. package/out/server/main.js +44 -1
  240. package/package.json +1 -1
  241. package/out/renderer/assets/_baseUniq-CJr3HkLS.js.br +0 -0
  242. package/out/renderer/assets/_baseUniq-CJr3HkLS.js.gz +0 -0
  243. package/out/renderer/assets/arc-POsBroTF.js.br +0 -0
  244. package/out/renderer/assets/arc-POsBroTF.js.gz +0 -0
  245. package/out/renderer/assets/architectureDiagram-Q4EWVU46-CmToUhDb.js.br +0 -0
  246. package/out/renderer/assets/architectureDiagram-Q4EWVU46-CmToUhDb.js.gz +0 -0
  247. package/out/renderer/assets/automation-Cyz3eLWp.js.br +0 -0
  248. package/out/renderer/assets/automation-Cyz3eLWp.js.gz +0 -0
  249. package/out/renderer/assets/blockDiagram-DXYQGD6D-M2nnTg9f.js.br +0 -0
  250. package/out/renderer/assets/blockDiagram-DXYQGD6D-M2nnTg9f.js.gz +0 -0
  251. package/out/renderer/assets/c4Diagram-AHTNJAMY-CwLtsy_0.js.br +0 -0
  252. package/out/renderer/assets/c4Diagram-AHTNJAMY-CwLtsy_0.js.gz +0 -0
  253. package/out/renderer/assets/chunk-4TB4RGXK-DXLZpPY5.js.br +0 -0
  254. package/out/renderer/assets/chunk-4TB4RGXK-DXLZpPY5.js.gz +0 -0
  255. package/out/renderer/assets/chunk-EDXVE4YY-CNjJEQfY.js.br +0 -0
  256. package/out/renderer/assets/chunk-EDXVE4YY-CNjJEQfY.js.gz +0 -0
  257. package/out/renderer/assets/chunk-OYMX7WX6-BG4B1VQ7.js.br +0 -0
  258. package/out/renderer/assets/chunk-OYMX7WX6-BG4B1VQ7.js.gz +0 -0
  259. package/out/renderer/assets/chunk-YZCP3GAM-jeoI2tsD.js.br +0 -0
  260. package/out/renderer/assets/chunk-YZCP3GAM-jeoI2tsD.js.gz +0 -0
  261. package/out/renderer/assets/code-editor-CEXlC4aV.js.br +0 -0
  262. package/out/renderer/assets/code-editor-CEXlC4aV.js.gz +0 -0
  263. package/out/renderer/assets/collapsible-CMuCJUWG.js.br +0 -0
  264. package/out/renderer/assets/collapsible-CMuCJUWG.js.gz +0 -0
  265. package/out/renderer/assets/cose-bilkent-S5V4N54A-B3bgImVS.js.br +0 -0
  266. package/out/renderer/assets/cose-bilkent-S5V4N54A-B3bgImVS.js.gz +0 -0
  267. package/out/renderer/assets/dagre-KV5264BT-DTbumBA_.js.br +0 -0
  268. package/out/renderer/assets/dagre-KV5264BT-DTbumBA_.js.gz +0 -0
  269. package/out/renderer/assets/diagram-5BDNPKRD-B34Y6e8q.js.br +0 -0
  270. package/out/renderer/assets/diagram-5BDNPKRD-B34Y6e8q.js.gz +0 -0
  271. package/out/renderer/assets/diagram-G4DWMVQ6-BBiBmFR4.js.br +0 -0
  272. package/out/renderer/assets/diagram-G4DWMVQ6-BBiBmFR4.js.gz +0 -0
  273. package/out/renderer/assets/diagram-MMDJMWI5-P-YslDjG.js.br +0 -0
  274. package/out/renderer/assets/diagram-MMDJMWI5-P-YslDjG.js.gz +0 -0
  275. package/out/renderer/assets/diagram-TYMM5635-D_cLard_.js.br +0 -0
  276. package/out/renderer/assets/diagram-TYMM5635-D_cLard_.js.gz +0 -0
  277. package/out/renderer/assets/erDiagram-SMLLAGMA-C1MHqKvC.js.br +0 -0
  278. package/out/renderer/assets/erDiagram-SMLLAGMA-C1MHqKvC.js.gz +0 -0
  279. package/out/renderer/assets/field-DR3J0r9e.js.br +0 -0
  280. package/out/renderer/assets/field-DR3J0r9e.js.gz +0 -0
  281. package/out/renderer/assets/flowDiagram-DWJPFMVM-DprlEc3Z.js.br +0 -0
  282. package/out/renderer/assets/flowDiagram-DWJPFMVM-DprlEc3Z.js.gz +0 -0
  283. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-CbTdumBm.js.br +0 -0
  284. package/out/renderer/assets/ganttDiagram-T4ZO3ILL-CbTdumBm.js.gz +0 -0
  285. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-06bme-w8.js.br +0 -0
  286. package/out/renderer/assets/gitGraphDiagram-UUTBAWPF-06bme-w8.js.gz +0 -0
  287. package/out/renderer/assets/graph-BZhxluo9.js.br +0 -0
  288. package/out/renderer/assets/graph-BZhxluo9.js.gz +0 -0
  289. package/out/renderer/assets/index-LmYTNvdF.js.br +0 -0
  290. package/out/renderer/assets/index-LmYTNvdF.js.gz +0 -0
  291. package/out/renderer/assets/index-aGJ_yZib.css +0 -382
  292. package/out/renderer/assets/index-aGJ_yZib.css.br +0 -0
  293. package/out/renderer/assets/index-aGJ_yZib.css.gz +0 -0
  294. package/out/renderer/assets/infoDiagram-42DDH7IO-DqivEzWL.js.br +0 -0
  295. package/out/renderer/assets/infoDiagram-42DDH7IO-DqivEzWL.js.gz +0 -0
  296. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-BKcg_z4w.js.br +0 -0
  297. package/out/renderer/assets/ishikawaDiagram-UXIWVN3A-BKcg_z4w.js.gz +0 -0
  298. package/out/renderer/assets/item-BHEUMM9H.js.br +0 -0
  299. package/out/renderer/assets/item-BHEUMM9H.js.gz +0 -0
  300. package/out/renderer/assets/journeyDiagram-VCZTEJTY-Bvv8xuxQ.js.br +0 -0
  301. package/out/renderer/assets/journeyDiagram-VCZTEJTY-Bvv8xuxQ.js.gz +0 -0
  302. package/out/renderer/assets/kanban-definition-6JOO6SKY-C-gRMpeM.js.br +0 -0
  303. package/out/renderer/assets/kanban-definition-6JOO6SKY-C-gRMpeM.js.gz +0 -0
  304. package/out/renderer/assets/layout-B4dSyItA.js.br +0 -0
  305. package/out/renderer/assets/layout-B4dSyItA.js.gz +0 -0
  306. package/out/renderer/assets/linear-CoVhuer7.js.br +0 -0
  307. package/out/renderer/assets/linear-CoVhuer7.js.gz +0 -0
  308. package/out/renderer/assets/mermaid-GHXKKRXX-CZqkhGx7.js.br +0 -0
  309. package/out/renderer/assets/mermaid-GHXKKRXX-CZqkhGx7.js.gz +0 -0
  310. package/out/renderer/assets/min-emzuJjmk.js.br +0 -0
  311. package/out/renderer/assets/min-emzuJjmk.js.gz +0 -0
  312. package/out/renderer/assets/mindmap-definition-QFDTVHPH-DQ4JNECm.js.br +0 -0
  313. package/out/renderer/assets/mindmap-definition-QFDTVHPH-DQ4JNECm.js.gz +0 -0
  314. package/out/renderer/assets/pieDiagram-DEJITSTG-0H6CGQQt.js.br +0 -0
  315. package/out/renderer/assets/pieDiagram-DEJITSTG-0H6CGQQt.js.gz +0 -0
  316. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-D0aPKp5z.js.br +0 -0
  317. package/out/renderer/assets/quadrantDiagram-34T5L4WZ-D0aPKp5z.js.gz +0 -0
  318. package/out/renderer/assets/refresh-cw-Bvm578nW.js +0 -11
  319. package/out/renderer/assets/requirementDiagram-MS252O5E-BkzwapW_.js.br +0 -0
  320. package/out/renderer/assets/requirementDiagram-MS252O5E-BkzwapW_.js.gz +0 -0
  321. package/out/renderer/assets/resizable-cStzNJ8V.js.br +0 -0
  322. package/out/renderer/assets/resizable-cStzNJ8V.js.gz +0 -0
  323. package/out/renderer/assets/sankeyDiagram-XADWPNL6-Dbde7usj.js.br +0 -0
  324. package/out/renderer/assets/sankeyDiagram-XADWPNL6-Dbde7usj.js.gz +0 -0
  325. package/out/renderer/assets/schedule-DNMCsk-G.js.br +0 -0
  326. package/out/renderer/assets/schedule-DNMCsk-G.js.gz +0 -0
  327. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DI8l1pSL.js.br +0 -0
  328. package/out/renderer/assets/sequenceDiagram-FGHM5R23-DI8l1pSL.js.gz +0 -0
  329. package/out/renderer/assets/session-Bn5k9ScR.js.br +0 -0
  330. package/out/renderer/assets/session-Bn5k9ScR.js.gz +0 -0
  331. package/out/renderer/assets/setting-dialog-sqfPfGsy.js.br +0 -0
  332. package/out/renderer/assets/setting-dialog-sqfPfGsy.js.gz +0 -0
  333. package/out/renderer/assets/settings-agents-Bntc31Nn.js.br +0 -0
  334. package/out/renderer/assets/settings-agents-Bntc31Nn.js.gz +0 -0
  335. package/out/renderer/assets/settings-general-DhbLb9cP.js.br +0 -0
  336. package/out/renderer/assets/settings-general-DhbLb9cP.js.gz +0 -0
  337. package/out/renderer/assets/settings-ilink-C7nGGjwT.js.br +0 -0
  338. package/out/renderer/assets/settings-ilink-C7nGGjwT.js.gz +0 -0
  339. package/out/renderer/assets/settings-image-generation-H2dgqG7Y.js.br +0 -0
  340. package/out/renderer/assets/settings-image-generation-H2dgqG7Y.js.gz +0 -0
  341. package/out/renderer/assets/settings-layout-ATto1xpJ.js.br +0 -0
  342. package/out/renderer/assets/settings-layout-ATto1xpJ.js.gz +0 -0
  343. package/out/renderer/assets/settings-mcp-DUdMuoJ-.js.br +0 -0
  344. package/out/renderer/assets/settings-mcp-DUdMuoJ-.js.gz +0 -0
  345. package/out/renderer/assets/settings-memory-CJLG4aHW.js.br +0 -0
  346. package/out/renderer/assets/settings-memory-CJLG4aHW.js.gz +0 -0
  347. package/out/renderer/assets/settings-snippets-B4VcnD5Z.js.br +0 -0
  348. package/out/renderer/assets/settings-snippets-B4VcnD5Z.js.gz +0 -0
  349. package/out/renderer/assets/settings-speech-to-text-DQ7lfkTu.js.br +0 -0
  350. package/out/renderer/assets/settings-speech-to-text-DQ7lfkTu.js.gz +0 -0
  351. package/out/renderer/assets/settings-webui-DZf9O-6j.js.br +0 -0
  352. package/out/renderer/assets/settings-webui-DZf9O-6j.js.gz +0 -0
  353. package/out/renderer/assets/skills-installed-Dp0r_4I-.js.br +0 -0
  354. package/out/renderer/assets/skills-installed-Dp0r_4I-.js.gz +0 -0
  355. package/out/renderer/assets/skills-layout-D-5rlY38.js.br +0 -0
  356. package/out/renderer/assets/skills-layout-D-5rlY38.js.gz +0 -0
  357. package/out/renderer/assets/skills-skills-sh-CcLoIrSw.js.br +0 -0
  358. package/out/renderer/assets/skills-skills-sh-CcLoIrSw.js.gz +0 -0
  359. package/out/renderer/assets/sortable.esm-knFxDx0Y.js.br +0 -0
  360. package/out/renderer/assets/sortable.esm-knFxDx0Y.js.gz +0 -0
  361. package/out/renderer/assets/standard-schema-dKXoCekr.js.br +0 -0
  362. package/out/renderer/assets/standard-schema-dKXoCekr.js.gz +0 -0
  363. package/out/renderer/assets/stateDiagram-FHFEXIEX-DWWz4PMv.js.br +0 -0
  364. package/out/renderer/assets/stateDiagram-FHFEXIEX-DWWz4PMv.js.gz +0 -0
  365. package/out/renderer/assets/task-C5dyYbfn.js.br +0 -0
  366. package/out/renderer/assets/task-C5dyYbfn.js.gz +0 -0
  367. package/out/renderer/assets/timeline-definition-GMOUNBTQ-A1tEoL9d.js.br +0 -0
  368. package/out/renderer/assets/timeline-definition-GMOUNBTQ-A1tEoL9d.js.gz +0 -0
  369. package/out/renderer/assets/vennDiagram-DHZGUBPP-tNdYrJi_.js.br +0 -0
  370. package/out/renderer/assets/vennDiagram-DHZGUBPP-tNdYrJi_.js.gz +0 -0
  371. package/out/renderer/assets/wardley-RL74JXVD-BxN5_Sp6.js.br +0 -0
  372. package/out/renderer/assets/wardley-RL74JXVD-BxN5_Sp6.js.gz +0 -0
  373. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-B_3jA8zU.js.br +0 -0
  374. package/out/renderer/assets/wardleyDiagram-NUSXRM2D-B_3jA8zU.js.gz +0 -0
  375. package/out/renderer/assets/wrench-7r-g9MUq.js.br +0 -0
  376. package/out/renderer/assets/wrench-7r-g9MUq.js.gz +0 -0
  377. package/out/renderer/assets/xlsx-view-Bv0YhA5m.js.br +0 -0
  378. package/out/renderer/assets/xlsx-view-Bv0YhA5m.js.gz +0 -0
  379. package/out/renderer/assets/xychartDiagram-5P7HB3ND-NNVuzC4j.js.br +0 -0
  380. package/out/renderer/assets/xychartDiagram-5P7HB3ND-NNVuzC4j.js.gz +0 -0
@@ -1,36 +1,21 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./code-editor-CEXlC4aV.js","./index-LmYTNvdF.js","./index-aGJ_yZib.css","./mermaid-GHXKKRXX-CZqkhGx7.js","./code-editor-BwxubRqT.css"])))=>i.map(i=>d[i]);
2
- import { h as createLucideIcon, r as reactExports, am as formatErrorMessage, bq as ReactStore, br as popupStoreSelectors, bs as triggerHover, al as triggerPress, bt as escapeKey, bu as attachPreventUnmountOnClose, bv as closePress, bw as PATIENT_CLICK_THRESHOLD, ae as reactDomExports, bx as focusOut, by as setPopupOpenState, bz as createInitialPopupStoreState, bA as createPopupFloatingRootContext, bB as Timeout, bC as PopupTriggerMap, j as jsxRuntimeExports, bD as FloatingTree, bE as usePopupRootSync, bF as useImplicitActiveTrigger, bG as useOpenStateTransitions, ak as createChangeEventDetails, bH as imperativeAction, bI as PopupHandleAttachment, bJ as usePopupRootStore, bK as useDismiss, bL as usePopupInteractionProps, bM as usePopupHandleStore, ai as useBaseUiId, bN as useTriggerDataForwarding, bO as useHoverReferenceInteraction, bP as safePolygon, bQ as useClick, bR as useOpenMethodTriggerProps, aq as useButton, bS as useTriggerFocusGuards, ap as useRenderElement, bT as CLICK_TRIGGER_IDENTIFIER, bU as FocusGuard, bV as pressableTriggerOpenStateMapping, bW as triggerOpenStateMapping, bX as FloatingPortal, bY as POPUP_COLLISION_AVOIDANCE, bZ as useFloatingNodeId, at as useAnimationsFinished, b_ as useAnchorPositioning, au as useIsoLayoutEffect, b$ as useAnchoredPopupScrollLock, c0 as usePositioner, c1 as InternalBackdrop, c2 as inertValue, c3 as FloatingNode, aj as useStableCallback, c4 as useToolbarRootContext, av as useOpenChangeComplete, c5 as useHoverFloatingInteraction, c6 as createDefaultInitialFocus, c7 as FOCUSABLE_POPUP_PROPS, ba as COMPOSITE_KEYS, c8 as getDisabledMountTransitionStyles, c9 as FloatingFocusManager, ca as isHTMLElement, cb as popupTransitionStateMapping, u as useTranslation, b as useMessage, X as useNavigate, a as useAppStore, _ as Badge, cc as formatUpdatedTime, e as request, V as electron, ab as ALL_FEATURES, ac as FEATURE_I18N_KEYS, M as cn$1, c as Switch, B as Button, R as LoaderCircle, cd as buttonVariants, i as isWebUI, U as FolderOpen, C as Check, d as Copy, f as extractErrorMessage, aG as reduceFlushStreaming, aF as reduceSessionNotification, g as copyText, ad as React, ce as Tooltip, cf as TooltipTrigger, cg as TooltipContent, S as ScrollArea, a5 as Bot, ch as formatDuration, af as getDefaultExportFromCjs, ci as ReactDOM, Y as subscribe, cj as clientId, A as DropdownMenu, E as DropdownMenuTrigger, ck as ChevronDown, F as DropdownMenuContent, G as DropdownMenuItem, cl as v$2, J as generateUUID, cm as HoverCard, cn as HoverCardTrigger, co as HoverCardContent, cp as X$1, aI as Folder, L as Library, cq as DropdownMenuSub, cr as DropdownMenuSubTrigger, cs as DropdownMenuSubContent, ct as CircleQuestionMark, cu as ChevronUp, aH as Clock, aB as Tabs, aC as TabsList, aD as TabsTrigger, cv as z$1, a0 as CircleCheck, cw as __vitePreload, I as Input, m as ContextMenuContent, n as ContextMenuItem, o as ContextMenuSeparator, cx as Code, bk as EDITOR_LABELS, k as ContextMenu, l as ContextMenuTrigger, aE as webUIBaseUrl, aa as ChevronRight, cy as MessageSquare, cz as FolderPlus, P as Pencil, T as Trash2, cA as useProjectState, cB as TabsContent } from "./index-LmYTNvdF.js";
3
- import { S as Settings2 } from "./settings-2-DRhoXOO8.js";
4
- import { i as isValidMessageToDisplay, M as MessageBubble, A as ArrowUpToLine, S as Square, j as jsonToPrettyYamlExports, p as parseFileReference, c as CodeCompareView, r as resolveFileUrl, I as ImageView, P as PdfView, D as DocxView, a as PptxView, X as XlsxView, R as RotateCcw, F as Folders } from "./xlsx-view-Bv0YhA5m.js";
5
- import { M as Mic, C as Clipboard } from "./mic-BgSvicCB.js";
6
- import { I as Image, W as Wrench } from "./wrench-7r-g9MUq.js";
7
- import { F as FileText } from "./file-text-nGCW6zu1.js";
8
- import { A as ArrowLeft } from "./arrow-left-CxS1t3f7.js";
9
- import { aQ as CodeView, S as StreamMarkdown, aR as FileIcon } from "./mermaid-GHXKKRXX-CZqkhGx7.js";
10
- import { S as Search } from "./search-BEY9yGF_.js";
11
- import { E as ExternalLink } from "./link-2-DHUPzNSt.js";
12
- import { R as RefreshCw } from "./refresh-cw-Bvm578nW.js";
13
- import { P as Plus } from "./plus-YNCXW-GD.js";
14
- import { R as ResizablePanelGroup, a as ResizablePanel, b as ResizableHandle } from "./resizable-cStzNJ8V.js";
15
- import "./collapsible-CMuCJUWG.js";
16
- import "./item-BHEUMM9H.js";
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./code-editor-tm0AYOLz.js","./index-BUwXrbHW.js","./index-DOIzYXAl.css","./mermaid-GHXKKRXX-CqMNodCp.js","./code-editor-BwxubRqT.css"])))=>i.map(i=>d[i]);
2
+ import { c as createLucideIcon, r as reactExports, av as formatErrorMessage, bz as ReactStore, bA as popupStoreSelectors, bB as triggerHover, au as triggerPress, bC as escapeKey, bD as attachPreventUnmountOnClose, bE as closePress, bF as PATIENT_CLICK_THRESHOLD, an as reactDomExports, bG as focusOut, bH as setPopupOpenState, bI as createInitialPopupStoreState, bJ as createPopupFloatingRootContext, bK as Timeout, bL as PopupTriggerMap, j as jsxRuntimeExports, bM as FloatingTree, bN as usePopupRootSync, bO as useImplicitActiveTrigger, bP as useOpenStateTransitions, at as createChangeEventDetails, bQ as imperativeAction, bR as PopupHandleAttachment, bS as usePopupRootStore, bT as useDismiss, bU as usePopupInteractionProps, bV as usePopupHandleStore, ar as useBaseUiId, bW as useTriggerDataForwarding, bX as useHoverReferenceInteraction, bY as safePolygon, bZ as useClick, b_ as useOpenMethodTriggerProps, az as useButton, b$ as useTriggerFocusGuards, ay as useRenderElement, c0 as CLICK_TRIGGER_IDENTIFIER, c1 as FocusGuard, c2 as pressableTriggerOpenStateMapping, c3 as triggerOpenStateMapping, c4 as FloatingPortal, c5 as POPUP_COLLISION_AVOIDANCE, c6 as useFloatingNodeId, aC as useAnimationsFinished, c7 as useAnchorPositioning, aD as useIsoLayoutEffect, c8 as useAnchoredPopupScrollLock, c9 as usePositioner, ca as InternalBackdrop, cb as inertValue, cc as FloatingNode, as as useStableCallback, cd as useToolbarRootContext, aE as useOpenChangeComplete, ce as useHoverFloatingInteraction, cf as createDefaultInitialFocus, cg as FOCUSABLE_POPUP_PROPS, bj as COMPOSITE_KEYS, ch as getDisabledMountTransitionStyles, ci as FloatingFocusManager, cj as isHTMLElement, ck as popupTransitionStateMapping, u as useTranslation, b as useMessage, X as useNavigate, a as useAppStore, f as request, g as extractErrorMessage, _ as Badge, cl as formatUpdatedTime, V as electron, aK as Tabs, aL as TabsList, aM as TabsTrigger, af as ALL_FEATURES, ag as FEATURE_I18N_KEYS, M as cn$1, d as Switch, B as Button, R as LoaderCircle, cm as buttonVariants, C as Check, e as Copy, i as isWebUI, U as FolderOpen, cn as restartSession, co as SessionLifecycleBusyError, cp as closeSession, h as copyText, cq as RestartSessionError, am as React, cr as Tooltip, cs as TooltipTrigger, ct as TooltipContent, cu as useFocusTarget, S as ScrollArea, a1 as Bot, cv as formatDuration, ao as getDefaultExportFromCjs, cw as ReactDOM, Y as subscribe, cx as clientId, A as DropdownMenu, E as DropdownMenuTrigger, cy as ChevronDown, F as DropdownMenuContent, G as DropdownMenuItem, cz as v$2, J as generateUUID, aP as reduceFlushStreaming, cA as HoverCard, cB as HoverCardTrigger, cC as HoverCardContent, cD as X$1, aR as Folder, L as Library, cE as DropdownMenuSub, cF as DropdownMenuSubTrigger, cG as DropdownMenuSubContent, cH as CircleQuestionMark, cI as ChevronUp, aQ as Clock, cJ as z$1, a0 as CircleCheck, cK as __vitePreload, I as Input, m as ContextMenuContent, n as ContextMenuItem, o as ContextMenuSeparator, cL as Code, bt as EDITOR_LABELS, k as ContextMenu, l as ContextMenuTrigger, aN as webUIBaseUrl, a6 as RefreshCw, a7 as ChevronRight, cM as MessageSquare, cN as FolderPlus, cO as Eye, P as Pencil, T as Trash2, cP as useProjectState, cQ as useFocusTargetRegistry, cR as TabsContent, cS as loadSession } from "./index-BUwXrbHW.js";
3
+ import { S as Settings2 } from "./settings-2-BwfZrIw6.js";
4
+ import { i as isValidMessageToDisplay, M as MessageBubble, A as ArrowUpToLine, S as Square, j as jsonToPrettyYamlExports, p as parseFileReference, c as CodeCompareView, r as resolveFileUrl, I as ImageView, P as PdfView, D as DocxView, a as PptxView, X as XlsxView, R as RotateCcw, F as Folders } from "./xlsx-view-CQd4jbk-.js";
5
+ import { a as ArrowDown, A as ArrowUp, b as ArrowRight } from "./arrow-up-1eI4tva4.js";
6
+ import { M as Mic, C as Clipboard } from "./mic-CT1bYBEV.js";
7
+ import { I as Image, W as Wrench } from "./wrench-BsjH8RPm.js";
8
+ import { F as FileText } from "./file-text-ITbWr8iW.js";
9
+ import { A as ArrowLeft } from "./arrow-left-CQqe9rrj.js";
10
+ import { aQ as CodeView, S as StreamMarkdown, aR as FileIcon } from "./mermaid-GHXKKRXX-CqMNodCp.js";
11
+ import { S as Search } from "./search-TCnuQyCi.js";
12
+ import { E as ExternalLink } from "./link-2-DpdZfD3m.js";
13
+ import { P as Plus } from "./plus-C5XdFVFm.js";
14
+ import { R as ResizablePanelGroup, a as ResizablePanel, b as ResizableHandle } from "./resizable-ObbINbIB.js";
15
+ import "./collapsible-DD6NlDid.js";
16
+ import "./item-Dph2aCdz.js";
17
17
  import "./schemas-c0X-G5_P.js";
18
- import "./ellipsis-D1agTYu1.js";
19
- const __iconNode$k = [
20
- ["path", { d: "M12 5v14", key: "s699le" }],
21
- ["path", { d: "m19 12-7 7-7-7", key: "1idqje" }]
22
- ];
23
- const ArrowDown = createLucideIcon("arrow-down", __iconNode$k);
24
- const __iconNode$j = [
25
- ["path", { d: "M5 12h14", key: "1ays0h" }],
26
- ["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
27
- ];
28
- const ArrowRight = createLucideIcon("arrow-right", __iconNode$j);
29
- const __iconNode$i = [
30
- ["path", { d: "m5 12 7-7 7 7", key: "hav0vg" }],
31
- ["path", { d: "M12 19V5", key: "x0mq9r" }]
32
- ];
33
- const ArrowUp = createLucideIcon("arrow-up", __iconNode$i);
18
+ import "./ellipsis-92s4sSUO.js";
34
19
  const __iconNode$h = [
35
20
  [
36
21
  "path",
@@ -815,76 +800,71 @@ function ChatHeader({ session }) {
815
800
  const currentProjectInfo = projects.find((project) => project.id === currentProjectId);
816
801
  const [localMcpServers, setLocalMcpServers] = reactExports.useState([]);
817
802
  const [localFeatures, setLocalFeatures] = reactExports.useState([]);
803
+ const [isRestarting, setIsRestarting] = reactExports.useState(false);
818
804
  const [isClosing, setIsClosing] = reactExports.useState(false);
819
805
  const handleToggle = reactExports.useCallback((mcpId) => {
820
806
  setLocalMcpServers(
821
807
  (prev) => prev.includes(mcpId) ? prev.filter((id) => id !== mcpId) : [...prev, mcpId]
822
808
  );
823
809
  }, []);
810
+ const handlePermissionChange = reactExports.useCallback(
811
+ async (permissionMode) => {
812
+ try {
813
+ await request.updateSession({ sessionId: session.id, permissionMode });
814
+ } catch (err) {
815
+ console.error("Failed to update session permission:", err);
816
+ toast.error(
817
+ extractErrorMessage(err) || t("chatHeader.failedToUpdatePermission", "Failed to update permission.")
818
+ );
819
+ }
820
+ },
821
+ [session.id, t, toast]
822
+ );
824
823
  const handleSyncAndRefresh = async () => {
825
- if (!session) return;
824
+ if (!session || isClosing || isRestarting) return;
825
+ setIsRestarting(true);
826
826
  try {
827
- await request.updateSession({
828
- sessionId: session.id,
827
+ await restartSession({
828
+ session,
829
829
  mcpServers: localMcpServers,
830
830
  features: localFeatures
831
831
  });
832
832
  } catch (err) {
833
- console.error("Failed to update MCP servers:", err);
834
- toast.error(
835
- extractErrorMessage(err) || t("chat.failedToUpdateMcpServers", "Failed to update MCP servers")
836
- );
837
- return;
838
- }
839
- const { resetSessionState, updateSessionState, updateSession } = useAppStore.getState();
840
- try {
841
- updateSession({ ...session, isStreaming: false });
842
- updateSessionState(session.id, (prev) => reduceFlushStreaming(prev));
843
- resetSessionState(session.id);
844
- updateSessionState(session.id, () => ({ isLoading: true }));
845
- const result = await request.getSessionHistory({ sessionId: session.id });
846
- if (!result) return;
847
- let state = useAppStore.getState().getSessionState(session.id);
848
- state = { ...state, messages: [], activeToolCalls: /* @__PURE__ */ new Map(), activeSubagents: /* @__PURE__ */ new Map() };
849
- for (const notification of result.messages) {
850
- state = reduceSessionNotification(session.id, state, notification);
851
- }
852
- const displayIds = new Set(
853
- result.messages.map((m) => m?.update?._meta?.fello?.displayId).filter(Boolean)
854
- );
855
- for (const notification of state.pendingNotifications) {
856
- const did = notification.update._meta?.fello?.displayId;
857
- if (did && displayIds.has(did)) continue;
858
- state = reduceSessionNotification(session.id, state, notification);
859
- }
860
- state = {
861
- ...state,
862
- pendingNotifications: [],
863
- isLoading: false
864
- };
865
- updateSessionState(session.id, () => state);
866
- request.loadSession({ sessionId: session.id, force: true }).catch((err) => {
867
- console.error("Failed to load session:", err);
833
+ console.error("Failed to restart session:", err);
834
+ if (err instanceof SessionLifecycleBusyError) {
868
835
  toast.error(
869
- extractErrorMessage(err) || t("chat.failedToLoadSession", "Failed to load session.")
836
+ t(
837
+ "chatHeader.sessionOperationInProgress",
838
+ "Another session operation is already in progress."
839
+ )
870
840
  );
871
- });
872
- } catch (err) {
873
- console.error("Failed to load session:", err);
874
- const message = extractErrorMessage(err) || t("chat.failedToLoadSession", "Failed to load session.");
875
- toast.error(message);
841
+ return;
842
+ }
843
+ const lifecycleError = err instanceof RestartSessionError ? err : null;
844
+ const cause = lifecycleError?.cause ?? err;
845
+ const fallback = lifecycleError?.stage === "update" ? t("chat.failedToUpdateMcpServers", "Failed to update MCP servers") : t("chat.failedToLoadSession", "Failed to load session.");
846
+ toast.error(extractErrorMessage(cause) || fallback);
876
847
  } finally {
877
- useAppStore.getState().updateSessionState(session.id, () => ({ isLoading: false }));
848
+ setIsRestarting(false);
878
849
  }
879
850
  };
880
851
  const handleCloseSession = async () => {
881
- if (isClosing) return;
852
+ if (isClosing || isRestarting) return;
882
853
  setIsClosing(true);
883
854
  try {
884
- await request.closeSession({ sessionId: session.id });
855
+ await closeSession(session.id);
885
856
  navigate("/");
886
857
  } catch (err) {
887
858
  console.error("Failed to close session:", err);
859
+ if (err instanceof SessionLifecycleBusyError) {
860
+ toast.error(
861
+ t(
862
+ "chatHeader.sessionOperationInProgress",
863
+ "Another session operation is already in progress."
864
+ )
865
+ );
866
+ return;
867
+ }
888
868
  toast.error(
889
869
  extractErrorMessage(err) || t("chatHeader.failedToCloseSession", "Failed to close session.")
890
870
  );
@@ -903,7 +883,7 @@ function ChatHeader({ session }) {
903
883
  children: [
904
884
  /* @__PURE__ */ jsxRuntimeExports.jsx(Badge, { variant: "outline", className: "px-1 text-[10px] uppercase select-none", children: session.agentId }),
905
885
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 min-w-0 items-baseline gap-2", children: [
906
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-[13px] font-normal text-sidebar-foreground/85", children: session.title || t("sidebar.newChat", "New Chat") }),
886
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate text-[13px] font-normal text-sidebar-foreground/85", children: session.title || t("sidebar.newSession", "New Session") }),
907
887
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 text-[10px] text-muted-foreground truncate", children: currentProjectInfo?.cwd }),
908
888
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-xs text-sidebar-foreground/70 whitespace-nowrap", children: formatUpdatedTime(session.updatedAt) })
909
889
  ] }),
@@ -920,8 +900,8 @@ function ChatHeader({ session }) {
920
900
  },
921
901
  children: [
922
902
  /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverTrigger, { className: "flex size-7 items-center justify-center rounded-md text-sidebar-foreground/45 hover:bg-sidebar-accent/30 hover:text-sidebar-foreground/70 outline-none transition-colors data-pressed:bg-sidebar-accent/40", children: /* @__PURE__ */ jsxRuntimeExports.jsx(Settings2, { className: "size-4" }) }),
923
- /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPositioner, { side: "bottom", align: "end", sideOffset: 4, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(PopoverPopup, { className: "z-10 min-w-96 rounded-lg border border-border bg-popover text-popover-foreground shadow-lg outline-none p-1.5 origin-(--transform-origin) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 transition-[transform,opacity] duration-100", children: [
924
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-1 py-1", children: [
903
+ /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPortal, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(PopoverPositioner, { side: "bottom", align: "end", sideOffset: 4, children: /* @__PURE__ */ jsxRuntimeExports.jsxs(PopoverPopup, { className: "z-10 w-110 rounded-lg border border-border bg-popover text-popover-foreground shadow-lg outline-none p-1.5 origin-(--transform-origin) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 transition-[transform,opacity] duration-100", children: [
904
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-px py-1", children: [
925
905
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
926
906
  CopyableRow,
927
907
  {
@@ -950,6 +930,24 @@ function ChatHeader({ session }) {
950
930
  ) })
951
931
  ] }),
952
932
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-border/50 my-1" }),
933
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-2 py-1 text-xs font-semibold text-foreground/80", children: t("sidebar.newSessionDialog.permission", "Permission") }),
934
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
935
+ Tabs,
936
+ {
937
+ value: session.permissionMode,
938
+ onValueChange: (value) => {
939
+ if (value === "ask" || value === "allow-all") {
940
+ void handlePermissionChange(value);
941
+ }
942
+ },
943
+ className: "w-full px-2 my-2",
944
+ children: /* @__PURE__ */ jsxRuntimeExports.jsxs(TabsList, { className: "w-full", children: [
945
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "ask", className: "text-xs", children: t("sidebar.newSessionDialog.permissionAsk", "Ask") }),
946
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsTrigger, { value: "allow-all", className: "text-xs", children: t("sidebar.newSessionDialog.permissionAllowAll", "Allow all") })
947
+ ] })
948
+ }
949
+ ),
950
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-border/50 my-1" }),
953
951
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-2 py-1 text-xs font-semibold text-foreground/80", children: t("constant.feature.title", "Features") }),
954
952
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: ALL_FEATURES.length >= 2 ? "grid grid-cols-2 gap-0.5" : "", children: ALL_FEATURES.map((feature) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
955
953
  "div",
@@ -1024,14 +1022,17 @@ function ChatHeader({ session }) {
1024
1022
  )
1025
1023
  ] }),
1026
1024
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-1 flex gap-1", children: [
1027
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1025
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
1028
1026
  Button,
1029
1027
  {
1030
1028
  size: "xs",
1031
1029
  className: "flex flex-3 items-center gap-2 h-7 text-xs font-normal",
1032
1030
  onClick: handleSyncAndRefresh,
1033
- disabled: isClosing,
1034
- children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("chatHeader.refresh", "Restart Session") })
1031
+ disabled: isClosing || isRestarting,
1032
+ children: [
1033
+ isRestarting && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
1034
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("chatHeader.refresh", "Restart Session") })
1035
+ ]
1035
1036
  }
1036
1037
  ),
1037
1038
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -1041,7 +1042,7 @@ function ChatHeader({ session }) {
1041
1042
  variant: "destructive",
1042
1043
  className: "flex flex-1 items-center gap-1.5 h-7 text-xs font-normal",
1043
1044
  onClick: handleCloseSession,
1044
- disabled: isClosing,
1045
+ disabled: isClosing || isRestarting,
1045
1046
  children: [
1046
1047
  isClosing && /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3 animate-spin" }),
1047
1048
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: isClosing ? t("chatHeader.closingSession", "Closing…") : t("chatHeader.closeSession", "Close Session") })
@@ -1175,23 +1176,23 @@ function CopyableRow({
1175
1176
  ":"
1176
1177
  ] }),
1177
1178
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 min-w-0 truncate font-mono text-muted-foreground/70 select-all", children: value }),
1178
- !isWebUI && onOpenFolder && /* @__PURE__ */ jsxRuntimeExports.jsx(
1179
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
1179
1180
  "button",
1180
1181
  {
1181
1182
  type: "button",
1182
1183
  className: "shrink-0 flex items-center justify-center size-5 rounded hover:bg-accent/50 text-muted-foreground/50 hover:text-muted-foreground transition-colors -mr-1",
1183
- onClick: onOpenFolder,
1184
- title: openFolderTitle,
1185
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3" })
1184
+ onClick: handleCopy,
1185
+ children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
1186
1186
  }
1187
1187
  ),
1188
- /* @__PURE__ */ jsxRuntimeExports.jsx(
1188
+ !isWebUI && onOpenFolder && /* @__PURE__ */ jsxRuntimeExports.jsx(
1189
1189
  "button",
1190
1190
  {
1191
1191
  type: "button",
1192
1192
  className: "shrink-0 flex items-center justify-center size-5 rounded hover:bg-accent/50 text-muted-foreground/50 hover:text-muted-foreground transition-colors -mr-1",
1193
- onClick: handleCopy,
1194
- children: copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "size-3" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "size-3" })
1193
+ onClick: onOpenFolder,
1194
+ title: openFolderTitle,
1195
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3" })
1195
1196
  }
1196
1197
  )
1197
1198
  ] });
@@ -1372,14 +1373,14 @@ function ChatTimeline({ items, activeDisplayId, onSelect: onSelect2 }) {
1372
1373
  {
1373
1374
  type: "button",
1374
1375
  onClick: () => handleSelect(item.displayId),
1375
- className: "p-1 group pointer-events-auto",
1376
+ className: "p-1 group/timeline pointer-events-auto outline-0",
1376
1377
  "aria-label": ariaLabel,
1377
1378
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1378
1379
  "div",
1379
1380
  {
1380
1381
  className: cn$1(
1381
- "size-2 rounded-full transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50",
1382
- isActive ? "bg-foreground/40" : "bg-muted-foreground/15 group-hover:bg-muted-foreground/40"
1382
+ "size-2 rounded-full transition-colors outline-none group-focus-visible/timeline:ring-1 group-focus-visible/timeline:ring-ring",
1383
+ isActive ? "bg-foreground/40" : "bg-muted-foreground/15 group-hover/timeline:bg-muted-foreground/40"
1383
1384
  )
1384
1385
  }
1385
1386
  )
@@ -1438,6 +1439,12 @@ function ChatArea({ session }) {
1438
1439
  const getViewport = reactExports.useCallback(() => {
1439
1440
  return scrollAreaRef.current?.querySelector('[data-slot="scroll-area-viewport"]');
1440
1441
  }, []);
1442
+ const focusChatArea = reactExports.useCallback(() => {
1443
+ const viewport = getViewport();
1444
+ if (!viewport) return;
1445
+ viewport.focus({ preventScroll: true });
1446
+ }, [getViewport]);
1447
+ useFocusTarget("chat-area", focusChatArea);
1441
1448
  const scrollToBottom = reactExports.useCallback((behavior) => {
1442
1449
  if (scrollTimeoutRef.current) {
1443
1450
  clearTimeout(scrollTimeoutRef.current);
@@ -1708,7 +1715,7 @@ function ChatArea({ session }) {
1708
1715
  const copyText$1 = reactExports.useCallback(async (text) => {
1709
1716
  return copyText(text);
1710
1717
  }, []);
1711
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full relative min-h-0 flex flex-1 overflow-hidden", children: [
1718
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "w-full relative min-h-0 flex flex-1 group/chat-area", children: [
1712
1719
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0 w-6 -mr-6 relative z-1 pointer-events-none", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
1713
1720
  ChatTimeline,
1714
1721
  {
@@ -1722,7 +1729,7 @@ function ChatArea({ session }) {
1722
1729
  {
1723
1730
  ref: scrollAreaRef,
1724
1731
  className: "flex-1 w-full transform-gpu",
1725
- viewportClassName: "animate-in fade-in",
1732
+ viewportClassName: "animate-in fade-in chat-area",
1726
1733
  children: [
1727
1734
  hasMore && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 px-10 py-3 max-w-5xl mx-auto", children: [
1728
1735
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex-1 border-b border-dashed border-muted-foreground/30" }),
@@ -1892,7 +1899,8 @@ function ChatArea({ session }) {
1892
1899
  "aria-label": t("chatArea.scrollToBottom", "Scroll to bottom"),
1893
1900
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowDown, { className: "size-4" })
1894
1901
  }
1895
- )
1902
+ ),
1903
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "pointer-events-none absolute -top-px left-0 right-0 h-px bg-linear-to-r from-ring/30 from-10% via-ring/80 via-30% to-ring/30 animate-out fill-mode-both fade-out ease-out duration-1500 hidden group-has-[.chat-area:focus-visible]/chat-area:block" })
1896
1904
  ] });
1897
1905
  }
1898
1906
  function _arrayWithoutHoles$1(arr) {
@@ -4586,7 +4594,10 @@ function useRealtimeAsr(options) {
4586
4594
  }
4587
4595
  const ASR_WAVEFORM_BARS = [0.35, 0.65, 0.95, 0.55, 0.8, 0.45, 0.9, 0.6, 0.38];
4588
4596
  const DEFAULT_MAX_DURATION = 5 * 60 * 1e3;
4597
+ const ALT_DOUBLE_PRESS_WINDOW = 350;
4589
4598
  const VOICE_INPUT_DEVICE_STORAGE_KEY = "fello.voice-input.device-id";
4599
+ let activeVoiceRecording = null;
4600
+ let voiceRecordingStartChain = Promise.resolve();
4590
4601
  function getInputCursor(input) {
4591
4602
  return input.selectionStart ?? input.value.length;
4592
4603
  }
@@ -4599,11 +4610,16 @@ function VoiceInputButton({
4599
4610
  }) {
4600
4611
  const { t } = useTranslation();
4601
4612
  const { toast } = useMessage();
4613
+ const altDoublePressEnabled = useAppStore((state) => state.voiceInput.altDoublePress);
4614
+ const [instanceId] = reactExports.useState(() => /* @__PURE__ */ Symbol("VoiceInputButton"));
4615
+ const stopAsrRef = reactExports.useRef(() => Promise.resolve());
4602
4616
  const asrApplyingRef = reactExports.useRef(false);
4603
4617
  const asrSegmentsRef = reactExports.useRef(/* @__PURE__ */ new Map());
4604
4618
  const asrTailRef = reactExports.useRef(0);
4605
4619
  const asrCurrentKeyRef = reactExports.useRef(null);
4606
4620
  const asrSequenceRef = reactExports.useRef(0);
4621
+ const lastAltTapAtRef = reactExports.useRef(null);
4622
+ const suppressAltUntilRef = reactExports.useRef(0);
4607
4623
  const freezeAsrSegments = reactExports.useCallback(() => {
4608
4624
  asrSegmentsRef.current.clear();
4609
4625
  asrCurrentKeyRef.current = null;
@@ -4639,17 +4655,32 @@ function VoiceInputButton({
4639
4655
  },
4640
4656
  [inputRef]
4641
4657
  );
4658
+ const handleRecordingChange = reactExports.useCallback(
4659
+ (recording) => {
4660
+ if (recording) {
4661
+ activeVoiceRecording = {
4662
+ owner: instanceId,
4663
+ stop: () => stopAsrRef.current()
4664
+ };
4665
+ } else {
4666
+ freezeAsrSegments();
4667
+ if (activeVoiceRecording?.owner === instanceId) {
4668
+ activeVoiceRecording = null;
4669
+ }
4670
+ }
4671
+ },
4672
+ [freezeAsrSegments, instanceId]
4673
+ );
4642
4674
  const asr = useRealtimeAsr({
4643
4675
  onTranscript: applyAsrTranscript,
4644
4676
  onError: (message) => toast.error(message),
4645
- onRecordingChange: (recording) => {
4646
- if (!recording) freezeAsrSegments();
4647
- }
4677
+ onRecordingChange: handleRecordingChange
4648
4678
  });
4649
4679
  const { start: startAsr, stop: stopAsr, refreshInputDevices } = asr;
4650
4680
  const handleStop = reactExports.useCallback(async () => {
4651
4681
  await stopAsr();
4652
4682
  }, [stopAsr]);
4683
+ stopAsrRef.current = handleStop;
4653
4684
  reactExports.useImperativeHandle(
4654
4685
  ref,
4655
4686
  () => ({
@@ -4659,23 +4690,28 @@ function VoiceInputButton({
4659
4690
  );
4660
4691
  const handleStart = reactExports.useCallback(
4661
4692
  async (deviceId) => {
4662
- const textarea = inputRef.current;
4663
- if (!textarea) return;
4664
- textarea.focus();
4665
- const cursorPosition = getInputCursor(textarea);
4666
- const before = textarea.value.slice(0, cursorPosition);
4667
- if (before.length > 0 && !/\s$/.test(before)) {
4668
- asrApplyingRef.current = true;
4669
- try {
4670
- document.execCommand("insertText", false, " ");
4671
- } finally {
4672
- asrApplyingRef.current = false;
4693
+ const startOperation = voiceRecordingStartChain.then(async () => {
4694
+ await activeVoiceRecording?.stop();
4695
+ const textarea = inputRef.current;
4696
+ if (!textarea) return;
4697
+ textarea.focus();
4698
+ const cursorPosition = getInputCursor(textarea);
4699
+ const before = textarea.value.slice(0, cursorPosition);
4700
+ if (before.length > 0 && !/\s$/.test(before)) {
4701
+ asrApplyingRef.current = true;
4702
+ try {
4703
+ document.execCommand("insertText", false, " ");
4704
+ } finally {
4705
+ asrApplyingRef.current = false;
4706
+ }
4673
4707
  }
4674
- }
4675
- asrSegmentsRef.current.clear();
4676
- asrCurrentKeyRef.current = null;
4677
- asrTailRef.current = getInputCursor(textarea);
4678
- await startAsr(deviceId);
4708
+ asrSegmentsRef.current.clear();
4709
+ asrCurrentKeyRef.current = null;
4710
+ asrTailRef.current = getInputCursor(textarea);
4711
+ await startAsr(deviceId);
4712
+ });
4713
+ voiceRecordingStartChain = startOperation.catch(() => void 0);
4714
+ await startOperation;
4679
4715
  },
4680
4716
  [startAsr, inputRef]
4681
4717
  );
@@ -4687,6 +4723,7 @@ function VoiceInputButton({
4687
4723
  }
4688
4724
  });
4689
4725
  const [deviceMenuOpen, setDeviceMenuOpen] = reactExports.useState(false);
4726
+ const [starting, setStarting] = reactExports.useState(false);
4690
4727
  const rememberDevice = reactExports.useCallback((deviceId) => {
4691
4728
  setSavedDeviceId(deviceId);
4692
4729
  try {
@@ -4702,14 +4739,44 @@ function VoiceInputButton({
4702
4739
  [rememberDevice]
4703
4740
  );
4704
4741
  const handleMicClick = reactExports.useCallback(async () => {
4705
- const devices = await refreshInputDevices();
4706
- const hasSavedDevice = savedDeviceId != null && devices.some((device) => device.deviceId === savedDeviceId);
4707
- if (hasSavedDevice) {
4708
- await handleStart(savedDeviceId);
4709
- } else {
4710
- setDeviceMenuOpen(true);
4742
+ if (disabled || !asr.configured || starting) return;
4743
+ setStarting(true);
4744
+ try {
4745
+ const devices = await refreshInputDevices();
4746
+ const hasSavedDevice = savedDeviceId != null && devices.some((device) => device.deviceId === savedDeviceId);
4747
+ if (hasSavedDevice) {
4748
+ await handleStart(savedDeviceId);
4749
+ } else {
4750
+ setDeviceMenuOpen(true);
4751
+ }
4752
+ } finally {
4753
+ setStarting(false);
4754
+ }
4755
+ }, [asr.configured, disabled, handleStart, refreshInputDevices, savedDeviceId, starting]);
4756
+ const handleShortcutToggle = reactExports.useCallback(async () => {
4757
+ if (disabled || !asr.configured || starting) return;
4758
+ if (asr.recording) {
4759
+ await handleStop();
4760
+ return;
4761
+ }
4762
+ setStarting(true);
4763
+ try {
4764
+ const devices = await refreshInputDevices();
4765
+ const hasSavedDevice = savedDeviceId != null && devices.some((device) => device.deviceId === savedDeviceId);
4766
+ await handleStart(hasSavedDevice ? savedDeviceId : void 0);
4767
+ } finally {
4768
+ setStarting(false);
4711
4769
  }
4712
- }, [refreshInputDevices, handleStart, savedDeviceId]);
4770
+ }, [
4771
+ asr.configured,
4772
+ asr.recording,
4773
+ disabled,
4774
+ handleStart,
4775
+ handleStop,
4776
+ refreshInputDevices,
4777
+ savedDeviceId,
4778
+ starting
4779
+ ]);
4713
4780
  const handleDeviceMenuChange = reactExports.useCallback(
4714
4781
  (open) => {
4715
4782
  setDeviceMenuOpen(open);
@@ -4717,6 +4784,76 @@ function VoiceInputButton({
4717
4784
  },
4718
4785
  [refreshInputDevices]
4719
4786
  );
4787
+ reactExports.useEffect(() => {
4788
+ lastAltTapAtRef.current = null;
4789
+ const handleKeyDown = (event) => {
4790
+ const input = inputRef.current;
4791
+ if (!input || document.activeElement !== input) {
4792
+ lastAltTapAtRef.current = null;
4793
+ return;
4794
+ }
4795
+ if (event.key === "Escape") {
4796
+ lastAltTapAtRef.current = null;
4797
+ suppressAltUntilRef.current = 0;
4798
+ if (!event.repeat && !event.ctrlKey && !event.metaKey && !event.shiftKey && asr.recording) {
4799
+ event.preventDefault();
4800
+ void handleStop();
4801
+ }
4802
+ return;
4803
+ }
4804
+ if (event.key !== "Alt") {
4805
+ lastAltTapAtRef.current = null;
4806
+ return;
4807
+ }
4808
+ if (!altDoublePressEnabled || event.repeat || event.ctrlKey || event.metaKey || event.shiftKey) {
4809
+ lastAltTapAtRef.current = null;
4810
+ return;
4811
+ }
4812
+ const now = Date.now();
4813
+ if (now < suppressAltUntilRef.current) {
4814
+ lastAltTapAtRef.current = null;
4815
+ return;
4816
+ }
4817
+ if (asr.recording) {
4818
+ lastAltTapAtRef.current = null;
4819
+ suppressAltUntilRef.current = now + ALT_DOUBLE_PRESS_WINDOW;
4820
+ event.preventDefault();
4821
+ void handleStop();
4822
+ return;
4823
+ }
4824
+ const lastTapAt = lastAltTapAtRef.current;
4825
+ if (lastTapAt !== null && now - lastTapAt <= ALT_DOUBLE_PRESS_WINDOW) {
4826
+ lastAltTapAtRef.current = null;
4827
+ event.preventDefault();
4828
+ void handleShortcutToggle();
4829
+ }
4830
+ };
4831
+ const handleKeyUp = (event) => {
4832
+ if (event.key !== "Alt") return;
4833
+ const input = inputRef.current;
4834
+ if (!input || document.activeElement !== input) {
4835
+ lastAltTapAtRef.current = null;
4836
+ return;
4837
+ }
4838
+ if (Date.now() < suppressAltUntilRef.current) {
4839
+ lastAltTapAtRef.current = null;
4840
+ return;
4841
+ }
4842
+ lastAltTapAtRef.current = Date.now();
4843
+ };
4844
+ const resetAltTap = () => {
4845
+ lastAltTapAtRef.current = null;
4846
+ suppressAltUntilRef.current = 0;
4847
+ };
4848
+ window.addEventListener("keydown", handleKeyDown);
4849
+ window.addEventListener("keyup", handleKeyUp);
4850
+ window.addEventListener("blur", resetAltTap);
4851
+ return () => {
4852
+ window.removeEventListener("keydown", handleKeyDown);
4853
+ window.removeEventListener("keyup", handleKeyUp);
4854
+ window.removeEventListener("blur", resetAltTap);
4855
+ };
4856
+ }, [altDoublePressEnabled, asr.recording, handleShortcutToggle, handleStop, inputRef]);
4720
4857
  reactExports.useEffect(() => {
4721
4858
  const textarea = inputRef.current;
4722
4859
  if (!textarea) return;
@@ -4739,7 +4876,7 @@ function VoiceInputButton({
4739
4876
  "div",
4740
4877
  {
4741
4878
  className: cn$1(
4742
- "relative inline-flex h-7 transition-[width] duration-300 ease-out",
4879
+ "relative inline-flex h-7 transition-[width] duration-300 ease-out flex-none",
4743
4880
  asr.recording ? "w-18" : "w-12.5",
4744
4881
  className
4745
4882
  ),
@@ -4802,10 +4939,11 @@ function VoiceInputButton({
4802
4939
  size: "sm",
4803
4940
  className: "h-full w-8 rounded-r-none border-r-0 bg-muted hover:bg-input border border-input text-amber-300/50 hover:text-amber-200",
4804
4941
  onClick: () => void handleMicClick(),
4805
- disabled: disabled || !asr.configured,
4806
- "aria-label": t("chatInput.voiceInput", "Voice input"),
4807
- title: asr.configured ? t("chatInput.voiceInput", "Voice input") : t("chatInput.voiceInputNotConfigured", "Configure voice input in Settings"),
4808
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(Mic, { className: "size-3.5" })
4942
+ disabled: disabled || !asr.configured || starting,
4943
+ "aria-busy": starting,
4944
+ "aria-label": starting ? t("chatInput.startingVoiceInput", "Starting voice input") : t("chatInput.voiceInput", "Voice input"),
4945
+ title: starting ? t("chatInput.startingVoiceInput", "Starting voice input") : asr.configured ? t("chatInput.voiceInput", "Voice input") : t("chatInput.voiceInputNotConfigured", "Configure voice input in Settings"),
4946
+ children: starting ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "size-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Mic, { className: "size-3.5" })
4809
4947
  }
4810
4948
  ),
4811
4949
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -4816,7 +4954,7 @@ function VoiceInputButton({
4816
4954
  {
4817
4955
  size: "icon",
4818
4956
  className: "h-full w-4.5 rounded-l-none bg-muted hover:bg-input border border-input border-l-0 px-0 text-amber-300/50 hover:text-amber-200",
4819
- disabled: disabled || !asr.configured,
4957
+ disabled: disabled || !asr.configured || starting,
4820
4958
  "aria-label": t("chatInput.selectVoiceInputDevice", "Select microphone"),
4821
4959
  title: t("chatInput.selectVoiceInputDevice", "Select microphone")
4822
4960
  }
@@ -4996,6 +5134,13 @@ function ChatInput({ session }) {
4996
5134
  const textareaRef = reactExports.useRef(null);
4997
5135
  const voiceInputRef = reactExports.useRef(null);
4998
5136
  const getTextarea = reactExports.useCallback(() => textareaRef.current, []);
5137
+ const focusInput = reactExports.useCallback(() => {
5138
+ const textarea = getTextarea();
5139
+ if (!textarea || textarea.disabled) return false;
5140
+ textarea.focus({ preventScroll: true });
5141
+ return document.activeElement === textarea;
5142
+ }, [getTextarea]);
5143
+ useFocusTarget("chat-input", focusInput);
4999
5144
  const insertTriggerChar = reactExports.useCallback(
5000
5145
  (char) => {
5001
5146
  const textarea = getTextarea();
@@ -5554,14 +5699,14 @@ function ChatInput({ session }) {
5554
5699
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
5555
5700
  "div",
5556
5701
  {
5557
- className: "flex cursor-text items-center justify-between gap-2 px-2 pb-2 overflow-hidden",
5702
+ className: "flex cursor-text items-center justify-between gap-2 -mt-3 overflow-hidden",
5558
5703
  onClick: (e) => {
5559
5704
  const target = e.target;
5560
5705
  if (target.closest("button, select, [role='combobox']")) return;
5561
5706
  getTextarea()?.focus();
5562
5707
  },
5563
5708
  children: [
5564
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 overflow-hidden", children: [
5709
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 p-2 overflow-hidden -mr-4", children: [
5565
5710
  availableModes.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenu, { children: [
5566
5711
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
5567
5712
  DropdownMenuTrigger,
@@ -5571,7 +5716,7 @@ function ChatInput({ session }) {
5571
5716
  {
5572
5717
  variant: "outline",
5573
5718
  size: "sm",
5574
- className: "h-7 text-xs text-muted-foreground hover:text-foreground gap-2 max-w-48 shrink overflow-hidden"
5719
+ className: "h-7 min-w-16 text-xs text-muted-foreground hover:text-foreground gap-2 max-w-48 shrink overflow-hidden"
5575
5720
  }
5576
5721
  ),
5577
5722
  children: [
@@ -5693,7 +5838,7 @@ function ChatInput({ session }) {
5693
5838
  ] })
5694
5839
  ] })
5695
5840
  ] }),
5696
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 overflow-hidden", children: [
5841
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 p-2 overflow-hidden", children: [
5697
5842
  availableModels.length > 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs(DropdownMenu, { children: [
5698
5843
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
5699
5844
  DropdownMenuTrigger,
@@ -5703,7 +5848,7 @@ function ChatInput({ session }) {
5703
5848
  {
5704
5849
  variant: "outline",
5705
5850
  size: "sm",
5706
- className: "h-7 text-xs text-muted-foreground hover:text-foreground gap-2 max-w-48 shrink overflow-hidden"
5851
+ className: "h-7 min-w-16 text-xs text-muted-foreground hover:text-foreground gap-2 max-w-48 shrink overflow-hidden"
5707
5852
  }
5708
5853
  ),
5709
5854
  children: [
@@ -5839,14 +5984,7 @@ function ChatInput({ session }) {
5839
5984
  }
5840
5985
  )
5841
5986
  ] }),
5842
- /* @__PURE__ */ jsxRuntimeExports.jsx(
5843
- VoiceInputButton,
5844
- {
5845
- ref: voiceInputRef,
5846
- inputRef: textareaRef,
5847
- disabled
5848
- }
5849
- ),
5987
+ /* @__PURE__ */ jsxRuntimeExports.jsx(VoiceInputButton, { ref: voiceInputRef, inputRef: textareaRef, disabled }),
5850
5988
  isStreaming ? /* @__PURE__ */ jsxRuntimeExports.jsx(
5851
5989
  Button,
5852
5990
  {
@@ -5890,14 +6028,14 @@ const mentionsInputStyle = {
5890
6028
  highlighter: {
5891
6029
  padding: "12px 16px 8px",
5892
6030
  border: "none",
5893
- maxHeight: 200
6031
+ maxHeight: "80vh"
5894
6032
  },
5895
6033
  input: {
5896
6034
  padding: "12px 16px 8px",
5897
6035
  border: "none",
5898
6036
  outline: "none",
5899
6037
  overflow: "auto",
5900
- maxHeight: 200,
6038
+ maxHeight: "80vh",
5901
6039
  color: "var(--foreground)",
5902
6040
  fontSize: 13,
5903
6041
  lineHeight: "1.5",
@@ -5990,12 +6128,15 @@ function AskUserDialog({ sessionId }) {
5990
6128
  "div",
5991
6129
  {
5992
6130
  ref: cardRef,
6131
+ role: "dialog",
6132
+ "aria-labelledby": "ask-user-dialog-title",
6133
+ "aria-describedby": currentRequest.description ? "ask-user-dialog-description" : void 0,
5993
6134
  onClick: () => setCollapsed(false),
5994
6135
  className: "grid grid-rows-[auto_1fr_auto] rounded-xl border border-border bg-card p-4 shadow-lg shadow-primary/5 max-h-[90vh]",
5995
6136
  children: [
5996
6137
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-3 min-h-0", children: [
5997
6138
  /* @__PURE__ */ jsxRuntimeExports.jsx(CircleQuestionMark, { className: "size-4.5 shrink-0 text-sky-500" }),
5998
- /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-medium leading-snug truncate", children: currentRequest.title || t("askUser.title", "Request") }),
6139
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { id: "ask-user-dialog-title", className: "text-sm font-medium leading-snug truncate", children: currentRequest.title || t("askUser.title", "Request") }),
5999
6140
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center ml-auto gap-1", children: [
6000
6141
  currentRequest.timeoutAt != null && /* @__PURE__ */ jsxRuntimeExports.jsx(AskUserCountdown, { timeoutAt: currentRequest.timeoutAt }),
6001
6142
  /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -6009,13 +6150,14 @@ function AskUserDialog({ sessionId }) {
6009
6150
  setCollapsed((c) => !c);
6010
6151
  },
6011
6152
  "aria-label": collapsed ? t("askUser.expand", "Expand") : t("askUser.collapse", "Collapse"),
6153
+ "aria-expanded": !collapsed,
6012
6154
  title: collapsed ? t("askUser.expand", "Expand") : t("askUser.collapse", "Collapse"),
6013
6155
  children: collapsed ? /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronUp, { className: "size-4" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ChevronDown, { className: "size-4" })
6014
6156
  }
6015
6157
  )
6016
6158
  ] })
6017
6159
  ] }),
6018
- currentRequest.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "h-full rounded-md bg-muted/40", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-3 px-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs text-muted-foreground leading-relaxed whitespace-pre-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: formatDescription(currentRequest.description) }) }) }) }) }),
6160
+ currentRequest.description && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { id: "ask-user-dialog-description", className: "min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "h-full rounded-md bg-muted/40", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "py-3 px-2", children: /* @__PURE__ */ jsxRuntimeExports.jsx("pre", { className: "text-xs text-muted-foreground leading-relaxed whitespace-pre-wrap", children: /* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: formatDescription(currentRequest.description) }) }) }) }) }),
6019
6161
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: cn$1("pt-3 min-h-0", collapsed ? "pointer-events-none" : ""), children: /* @__PURE__ */ jsxRuntimeExports.jsx(
6020
6162
  AskUserOptions,
6021
6163
  {
@@ -6079,12 +6221,21 @@ function AskUserOptions({
6079
6221
  const [highlightedIndex, setHighlightedIndex] = reactExports.useState(null);
6080
6222
  const [isDragOver, setIsDragOver] = reactExports.useState(false);
6081
6223
  const inputContainerRef = reactExports.useRef(null);
6224
+ const optionRefs = reactExports.useRef([]);
6225
+ const otherButtonRef = reactExports.useRef(null);
6082
6226
  const textareaRef = reactExports.useRef(null);
6083
6227
  const voiceInputRef = reactExports.useRef(null);
6084
6228
  const navigate = useNavigate();
6085
6229
  const snippets = useAppStore((s15) => s15.snippets);
6086
6230
  const fileInputRef = reactExports.useRef(null);
6087
6231
  const getTextarea = reactExports.useCallback(() => textareaRef.current, []);
6232
+ const focusAskUser = reactExports.useCallback(() => {
6233
+ const target = mode === "input" ? textareaRef.current : optionRefs.current[0];
6234
+ if (!target || target.disabled) return false;
6235
+ target.focus({ preventScroll: true });
6236
+ return document.activeElement === target;
6237
+ }, [mode]);
6238
+ useFocusTarget("ask-user-dialog", focusAskUser);
6088
6239
  const insertTriggerChar = reactExports.useCallback(
6089
6240
  (char) => {
6090
6241
  const textarea = getTextarea();
@@ -6254,31 +6405,53 @@ function AskUserOptions({
6254
6405
  }
6255
6406
  };
6256
6407
  reactExports.useEffect(() => {
6257
- if (mode === "input") {
6258
- textareaRef.current?.focus();
6259
- }
6408
+ if (mode !== "input") return;
6409
+ textareaRef.current?.focus();
6260
6410
  }, [mode]);
6411
+ reactExports.useEffect(() => {
6412
+ if (mode !== "options" || !hasOptions) return;
6413
+ const frame = window.requestAnimationFrame(() => optionRefs.current[0]?.focus());
6414
+ return () => window.cancelAnimationFrame(frame);
6415
+ }, [hasOptions, mode]);
6416
+ const handleOptionKeyDown = (event, index) => {
6417
+ const { key } = event;
6418
+ if (key === "ArrowDown" || key === "ArrowUp" || key === "Home" || key === "End") {
6419
+ event.preventDefault();
6420
+ event.stopPropagation();
6421
+ if (key === "Home") {
6422
+ optionRefs.current[0]?.focus();
6423
+ } else if (key === "End") {
6424
+ if (showOther) otherButtonRef.current?.focus();
6425
+ else optionRefs.current[request$1.options.length - 1]?.focus();
6426
+ } else if (key === "ArrowDown") {
6427
+ if (index < request$1.options.length - 1) {
6428
+ optionRefs.current[index + 1]?.focus();
6429
+ } else if (showOther) {
6430
+ otherButtonRef.current?.focus();
6431
+ }
6432
+ } else if (index > 0) {
6433
+ optionRefs.current[index - 1]?.focus();
6434
+ }
6435
+ }
6436
+ };
6261
6437
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
6262
6438
  mode === "options" && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2", children: [
6263
6439
  request$1.options.map((option, index) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
6264
- "div",
6440
+ "button",
6265
6441
  {
6266
- role: "button",
6267
- tabIndex: 0,
6268
- className: `relative flex w-full min-h-8 py-2 px-2 text-xs text-left rounded-lg border transition-all select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:translate-y-px ${highlightedIndex === index ? "ring-1 ring-sky-500 bg-sky-500/10 border-sky-500/30" : option.danger ? "bg-destructive/10 text-destructive hover:bg-destructive/20 border-destructive/20" : "bg-secondary/50 hover:bg-secondary hover:text-foreground"}`,
6269
- onClick: () => handleSelectOption(option.value),
6270
- onKeyDown: (e) => {
6271
- if (e.key === "Enter" || e.key === " ") {
6272
- e.preventDefault();
6273
- handleSelectOption(option.value);
6274
- }
6442
+ ref: (element) => {
6443
+ optionRefs.current[index] = element;
6275
6444
  },
6445
+ type: "button",
6446
+ className: `relative flex w-full min-h-8 py-2 px-2 text-xs text-left rounded-lg border transition-all select-none focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 active:translate-y-px ${highlightedIndex === index ? "ring-1 ring-sky-500 bg-sky-500/10 border-sky-500/30" : option.danger ? "bg-destructive/10 text-destructive hover:bg-destructive/20 border-destructive/20" : "bg-secondary/50 hover:bg-secondary hover:text-foreground"}`,
6447
+ onClick: () => handleSelectOption(option.value),
6448
+ onKeyDown: (event) => handleOptionKeyDown(event, index),
6276
6449
  children: [
6277
6450
  /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "inline-flex items-start gap-1.5 w-full", children: [
6278
6451
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "inline-flex size-5 items-center justify-center rounded bg-muted-foreground/10 text-[10px] font-mono shrink-0 self-start mt-0.5", children: index + 1 }),
6279
6452
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "min-w-0 flex-1 whitespace-normal self-start py-1", children: option.label })
6280
6453
  ] }),
6281
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute top-0.5 right-1 text-[9px] leading-none text-muted-foreground/30 shrink-0 self-start font-mono", children: option.priority })
6454
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "absolute top-0.5 right-1 text-[9px] leading-none text-muted-foreground/30 shrink-0 self-start font-mono", children: option.priority })
6282
6455
  ]
6283
6456
  },
6284
6457
  option.value
@@ -6286,10 +6459,22 @@ function AskUserOptions({
6286
6459
  showOther && /* @__PURE__ */ jsxRuntimeExports.jsxs(
6287
6460
  Button,
6288
6461
  {
6462
+ ref: otherButtonRef,
6289
6463
  variant: "ghost",
6290
6464
  size: "sm",
6291
6465
  className: "justify-start h-8 px-2 text-xs text-muted-foreground",
6292
6466
  onClick: () => setMode("input"),
6467
+ onKeyDown: (event) => {
6468
+ if (event.key === "ArrowUp") {
6469
+ event.preventDefault();
6470
+ event.stopPropagation();
6471
+ optionRefs.current[request$1.options.length - 1]?.focus();
6472
+ } else if (event.key === "Home") {
6473
+ event.preventDefault();
6474
+ event.stopPropagation();
6475
+ optionRefs.current[0]?.focus();
6476
+ }
6477
+ },
6293
6478
  children: [
6294
6479
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("askUser.other", "Custom reply") }),
6295
6480
  /* @__PURE__ */ jsxRuntimeExports.jsx(ArrowRight, { className: "size-3" })
@@ -6689,7 +6874,7 @@ function useFile(projectId, file, options = {}) {
6689
6874
  };
6690
6875
  }
6691
6876
  const CodeEditor = reactExports.lazy(
6692
- () => __vitePreload(() => import("./code-editor-CEXlC4aV.js"), true ? __vite__mapDeps([0,1,2,3,4]) : void 0, import.meta.url).then((m) => ({ default: m.CodeEditor }))
6877
+ () => __vitePreload(() => import("./code-editor-tm0AYOLz.js"), true ? __vite__mapDeps([0,1,2,3,4]) : void 0, import.meta.url).then((m) => ({ default: m.CodeEditor }))
6693
6878
  );
6694
6879
  const MAX_EDIT_SIZE = 1024 * 1024;
6695
6880
  const EditPanel = reactExports.forwardRef(function EditPanel2({ projectId, filePath, content, loading = false, onCancel, onSaved }, ref) {
@@ -17260,6 +17445,9 @@ const GIT_SUMMARY_BADGES = [
17260
17445
  { key: "C", color: "text-yellow-500" },
17261
17446
  { key: "D", color: "text-red-500" }
17262
17447
  ];
17448
+ function fileNavigationItemKey(item) {
17449
+ return item.type === "action" ? `action:${item.action}` : `tree:${item.id}`;
17450
+ }
17263
17451
  function TreeItem({
17264
17452
  node,
17265
17453
  depth,
@@ -17273,7 +17461,10 @@ function TreeItem({
17273
17461
  onEditChange,
17274
17462
  onEditSubmit,
17275
17463
  onEditCancel,
17276
- actions
17464
+ actions,
17465
+ onKeyDown: onKeyDown2,
17466
+ registerRef,
17467
+ onFocus
17277
17468
  }) {
17278
17469
  const { t } = useTranslation();
17279
17470
  const isOpen = openFolders.has(node.id);
@@ -17284,6 +17475,15 @@ function TreeItem({
17284
17475
  reactExports.useEffect(() => {
17285
17476
  if (isEditing) setTimeout(() => inputRef.current?.focus(), 0);
17286
17477
  }, [isEditing]);
17478
+ const handleView = (e) => {
17479
+ if (node.isFolder) {
17480
+ actions.toggle(node);
17481
+ actions.select(node.id, e);
17482
+ } else {
17483
+ actions.previewFile(node.id);
17484
+ actions.select(node.id, e);
17485
+ }
17486
+ };
17287
17487
  const childProps = {
17288
17488
  selectedIds,
17289
17489
  openFolders,
@@ -17294,7 +17494,10 @@ function TreeItem({
17294
17494
  onEditChange,
17295
17495
  onEditSubmit,
17296
17496
  onEditCancel,
17297
- actions
17497
+ actions,
17498
+ onKeyDown: onKeyDown2,
17499
+ registerRef,
17500
+ onFocus
17298
17501
  };
17299
17502
  const status = gitStatusMap.get(node.id);
17300
17503
  let statusText = "";
@@ -17331,7 +17534,22 @@ function TreeItem({
17331
17534
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
17332
17535
  ContextMenuTrigger,
17333
17536
  {
17334
- render: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
17537
+ render: /* @__PURE__ */ jsxRuntimeExports.jsx(
17538
+ "div",
17539
+ {
17540
+ ref: (element) => registerRef(node.id, element),
17541
+ tabIndex: -1,
17542
+ role: "treeitem",
17543
+ "aria-level": depth + 1,
17544
+ "aria-expanded": node.isFolder ? isOpen : void 0,
17545
+ "aria-selected": isSelected,
17546
+ className: "outline-0 focus-visible:inset-ring-1 focus-visible:inset-ring-ring/80 rounded-md",
17547
+ onKeyDown: (e) => {
17548
+ if (e.target === e.currentTarget) onKeyDown2(e, node);
17549
+ },
17550
+ onFocus: () => onFocus(node.id)
17551
+ }
17552
+ ),
17335
17553
  draggable: !isEditing,
17336
17554
  onDragStart: (e) => {
17337
17555
  e.stopPropagation();
@@ -17349,7 +17567,6 @@ function TreeItem({
17349
17567
  },
17350
17568
  className: cn$1(
17351
17569
  "flex h-6 cursor-default select-none items-center gap-1.5 px-1.5 text-sx leading-none text-foreground/60",
17352
- node.ignored && "opacity-50",
17353
17570
  node.id === previewId ? "bg-primary/8 hover:bg-primary/10" : "hover:bg-primary/5 hover:text-foreground",
17354
17571
  isSelected ? "text-foreground bg-primary/6" : "",
17355
17572
  isDragOver && "relative ring-1 ring-primary bg-primary/5"
@@ -17361,13 +17578,7 @@ function TreeItem({
17361
17578
  actions.select(node.id, e);
17362
17579
  return;
17363
17580
  }
17364
- if (node.isFolder) {
17365
- actions.toggle(node);
17366
- actions.select(node.id, e);
17367
- } else {
17368
- actions.previewFile(node.id);
17369
- actions.select(node.id, e);
17370
- }
17581
+ handleView(e);
17371
17582
  },
17372
17583
  children: [
17373
17584
  node.isFolder ? /* @__PURE__ */ jsxRuntimeExports.jsx(
@@ -17375,10 +17586,11 @@ function TreeItem({
17375
17586
  {
17376
17587
  className: cn$1(
17377
17588
  "size-3.5 shrink-0 text-muted-foreground scale-110 transition-transform",
17378
- isOpen && "rotate-90"
17589
+ isOpen && "rotate-90",
17590
+ node.ignored && "opacity-50"
17379
17591
  )
17380
17592
  }
17381
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(FileIcon, { name: node.name, className: "size-3.5 shrink-0 text-muted-foreground/90" }),
17593
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(FileIcon, { name: node.name, className: cn$1("size-3.5 shrink-0 text-muted-foreground/90", node.ignored && "opacity-50") }),
17382
17594
  isEditing ? /* @__PURE__ */ jsxRuntimeExports.jsx(
17383
17595
  "input",
17384
17596
  {
@@ -17399,7 +17611,8 @@ function TreeItem({
17399
17611
  {
17400
17612
  className: cn$1(
17401
17613
  "flex-1 truncate leading-normal",
17402
- statusText && !node.isFolder && statusColor
17614
+ statusText && !node.isFolder && statusColor,
17615
+ node.ignored && "opacity-50"
17403
17616
  ),
17404
17617
  children: node.name
17405
17618
  }
@@ -17419,6 +17632,11 @@ function TreeItem({
17419
17632
  }
17420
17633
  ),
17421
17634
  /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuContent, { children: [
17635
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: handleView, children: [
17636
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, {}),
17637
+ t("filePanel.view")
17638
+ ] }),
17639
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
17422
17640
  node.isFolder ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
17423
17641
  /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: () => actions.createIn(node.id, false), children: [
17424
17642
  /* @__PURE__ */ jsxRuntimeExports.jsx(FilePlus, {}),
@@ -17558,7 +17776,13 @@ const FilePanel = reactExports.memo(function FilePanel2({
17558
17776
  onPreviewFile
17559
17777
  }) {
17560
17778
  const { t } = useTranslation();
17561
- const containerRef = reactExports.useRef(null);
17779
+ const treeRef = reactExports.useRef(null);
17780
+ const treeItemRefs = reactExports.useRef(/* @__PURE__ */ new Map());
17781
+ const navigationActionRefs = reactExports.useRef(/* @__PURE__ */ new Map());
17782
+ const lastFocusedActionRef = reactExports.useRef(null);
17783
+ const focusedTreeItemIdRef = reactExports.useRef(null);
17784
+ const pendingFocusIdRef = reactExports.useRef(null);
17785
+ const pendingFocusRestoreRef = reactExports.useRef(false);
17562
17786
  const [data, setData] = reactExports.useState([]);
17563
17787
  const [loading, setLoading] = reactExports.useState(false);
17564
17788
  const [showLoading, setShowLoading] = reactExports.useState(false);
@@ -17769,6 +17993,144 @@ const FilePanel = reactExports.memo(function FilePanel2({
17769
17993
  },
17770
17994
  [openFolders]
17771
17995
  );
17996
+ const registerTreeItemRef = reactExports.useCallback((id, element) => {
17997
+ if (element) {
17998
+ treeItemRefs.current.set(id, element);
17999
+ } else {
18000
+ treeItemRefs.current.delete(id);
18001
+ }
18002
+ }, []);
18003
+ const registerNavigationActionRef = reactExports.useCallback(
18004
+ (action, element) => {
18005
+ if (element) {
18006
+ navigationActionRefs.current.set(action, element);
18007
+ } else {
18008
+ navigationActionRefs.current.delete(action);
18009
+ }
18010
+ },
18011
+ []
18012
+ );
18013
+ const handleTreeItemFocus = reactExports.useCallback((id) => {
18014
+ focusedTreeItemIdRef.current = id;
18015
+ }, []);
18016
+ const focusTreeItem = reactExports.useCallback(
18017
+ (id) => {
18018
+ let element = treeItemRefs.current.get(id);
18019
+ if (!element) {
18020
+ const visibleIds = flattenTree(data);
18021
+ const itemIndex = visibleIds.indexOf(id);
18022
+ if (itemIndex !== -1) {
18023
+ element = treeRef.current?.querySelectorAll('[role="treeitem"]')[itemIndex];
18024
+ }
18025
+ }
18026
+ if (!element) return;
18027
+ element.focus({ preventScroll: true });
18028
+ element.scrollIntoView({ block: "nearest" });
18029
+ },
18030
+ [data, flattenTree]
18031
+ );
18032
+ const fileNavigationItems = reactExports.useMemo(() => {
18033
+ const items = [];
18034
+ if (!isWebUI && cwd) {
18035
+ items.push({ type: "action", action: "reveal" });
18036
+ items.push({ type: "action", action: "editor" });
18037
+ }
18038
+ if (!loading) {
18039
+ items.push(
18040
+ { type: "action", action: "new-file" },
18041
+ { type: "action", action: "new-folder" },
18042
+ { type: "action", action: "refresh" },
18043
+ { type: "action", action: "collapse" }
18044
+ );
18045
+ }
18046
+ items.push(...flattenTree(data).map((id) => ({ type: "tree", id })));
18047
+ return items;
18048
+ }, [cwd, data, flattenTree, loading]);
18049
+ const fileActionItems = reactExports.useMemo(
18050
+ () => fileNavigationItems.filter(
18051
+ (item) => item.type === "action"
18052
+ ),
18053
+ [fileNavigationItems]
18054
+ );
18055
+ const treeNavigationItems = reactExports.useMemo(
18056
+ () => fileNavigationItems.filter(
18057
+ (item) => item.type === "tree"
18058
+ ),
18059
+ [fileNavigationItems]
18060
+ );
18061
+ const focusFileNavigationItem = reactExports.useCallback(
18062
+ (item) => {
18063
+ if (item.type === "action") {
18064
+ const element = navigationActionRefs.current.get(item.action);
18065
+ if (!element) return;
18066
+ element.focus({ preventScroll: true });
18067
+ return;
18068
+ }
18069
+ focusTreeItem(item.id);
18070
+ },
18071
+ [focusTreeItem]
18072
+ );
18073
+ const handleFileNavigationKeyDown = reactExports.useCallback(
18074
+ (event, items, item) => {
18075
+ event.preventDefault();
18076
+ event.stopPropagation();
18077
+ if (items.length === 0) return;
18078
+ const currentIndex = items.findIndex(
18079
+ (navigationItem) => fileNavigationItemKey(navigationItem) === fileNavigationItemKey(item)
18080
+ );
18081
+ const nextIndex = event.key === "Home" ? 0 : event.key === "End" ? items.length - 1 : Math.max(
18082
+ 0,
18083
+ Math.min(
18084
+ items.length - 1,
18085
+ currentIndex + (event.key === "ArrowRight" || event.key === "ArrowDown" ? 1 : -1)
18086
+ )
18087
+ );
18088
+ const nextItem = items[nextIndex];
18089
+ if (nextItem) focusFileNavigationItem(nextItem);
18090
+ },
18091
+ [focusFileNavigationItem]
18092
+ );
18093
+ const focusFileTree = reactExports.useCallback(() => {
18094
+ const visibleIds = flattenTree(data);
18095
+ const targetId = lastSelectedId && visibleIds.includes(lastSelectedId) && lastSelectedId || visibleIds.find((id) => selectedIds.has(id)) || visibleIds[0];
18096
+ if (targetId) {
18097
+ focusTreeItem(targetId);
18098
+ } else if (fileActionItems[0]) {
18099
+ focusFileNavigationItem(fileActionItems[0]);
18100
+ }
18101
+ }, [
18102
+ data,
18103
+ fileActionItems,
18104
+ flattenTree,
18105
+ focusFileNavigationItem,
18106
+ focusTreeItem,
18107
+ lastSelectedId,
18108
+ selectedIds
18109
+ ]);
18110
+ useFocusTarget("file-tree-content", focusFileTree);
18111
+ reactExports.useEffect(() => {
18112
+ if (!pendingFocusRestoreRef.current || loading) return;
18113
+ const visibleIds = flattenTree(data);
18114
+ const pendingId = pendingFocusIdRef.current;
18115
+ const targetId = pendingId && visibleIds.includes(pendingId) ? pendingId : visibleIds[0];
18116
+ const fallbackAction = fileActionItems[0];
18117
+ pendingFocusRestoreRef.current = false;
18118
+ pendingFocusIdRef.current = null;
18119
+ window.requestAnimationFrame(() => {
18120
+ if (targetId) {
18121
+ focusTreeItem(targetId);
18122
+ } else if (fallbackAction) {
18123
+ focusFileNavigationItem(fallbackAction);
18124
+ }
18125
+ });
18126
+ }, [
18127
+ data,
18128
+ fileActionItems,
18129
+ flattenTree,
18130
+ focusFileNavigationItem,
18131
+ focusTreeItem,
18132
+ loading
18133
+ ]);
17772
18134
  reactExports.useEffect(() => {
17773
18135
  useAppStore.getState().updateProjectState(projectId, () => ({
17774
18136
  openFolders: Array.from(openFolders)
@@ -17820,6 +18182,86 @@ const FilePanel = reactExports.memo(function FilePanel2({
17820
18182
  },
17821
18183
  [activeProjectId]
17822
18184
  );
18185
+ const handleTreeKeyDown = reactExports.useCallback(
18186
+ (event, node) => {
18187
+ const { key } = event;
18188
+ const isVerticalNavigationKey = key === "ArrowUp" || key === "ArrowDown" || key === "Home" || key === "End";
18189
+ if (isVerticalNavigationKey) {
18190
+ const treeItem = { type: "tree", id: node.id };
18191
+ const currentIndex = treeNavigationItems.findIndex((item) => item.id === node.id);
18192
+ if (key === "ArrowUp" && currentIndex === 0) {
18193
+ const actionItem = fileActionItems.find((item) => item.action === lastFocusedActionRef.current) ?? fileActionItems[0];
18194
+ if (actionItem) {
18195
+ event.preventDefault();
18196
+ event.stopPropagation();
18197
+ focusFileNavigationItem(actionItem);
18198
+ return;
18199
+ }
18200
+ }
18201
+ handleFileNavigationKeyDown(event, treeNavigationItems, treeItem);
18202
+ return;
18203
+ }
18204
+ if (key === "/") {
18205
+ event.preventDefault();
18206
+ event.stopPropagation();
18207
+ const target = event.currentTarget;
18208
+ const rect = target.getBoundingClientRect();
18209
+ target.dispatchEvent(
18210
+ new MouseEvent("contextmenu", {
18211
+ bubbles: true,
18212
+ cancelable: true,
18213
+ view: window,
18214
+ button: 2,
18215
+ buttons: 2,
18216
+ clientX: rect.left + rect.width / 2,
18217
+ clientY: rect.top + rect.height / 2
18218
+ })
18219
+ );
18220
+ return;
18221
+ }
18222
+ if (key === "ArrowLeft" || key === "ArrowRight") {
18223
+ event.preventDefault();
18224
+ event.stopPropagation();
18225
+ if (key === "ArrowRight" && node.isFolder) {
18226
+ if (!openFolders.has(node.id)) {
18227
+ toggle(node);
18228
+ } else {
18229
+ const firstChild = node.children?.[0];
18230
+ if (firstChild) focusTreeItem(firstChild.id);
18231
+ }
18232
+ } else if (key === "ArrowLeft") {
18233
+ if (node.isFolder && openFolders.has(node.id)) {
18234
+ toggle(node);
18235
+ } else {
18236
+ const parentId = node.id.slice(0, node.id.lastIndexOf("/"));
18237
+ if (parentId) focusTreeItem(parentId);
18238
+ }
18239
+ }
18240
+ return;
18241
+ }
18242
+ if (key === "Enter" || key === " " || key === "Spacebar") {
18243
+ event.preventDefault();
18244
+ event.stopPropagation();
18245
+ setSelectedIds(/* @__PURE__ */ new Set([node.id]));
18246
+ setLastSelectedId(node.id);
18247
+ if (node.isFolder) {
18248
+ toggle(node);
18249
+ } else {
18250
+ onPreviewFile(node.id);
18251
+ }
18252
+ }
18253
+ },
18254
+ [
18255
+ fileActionItems,
18256
+ focusFileNavigationItem,
18257
+ focusTreeItem,
18258
+ handleFileNavigationKeyDown,
18259
+ onPreviewFile,
18260
+ openFolders,
18261
+ toggle,
18262
+ treeNavigationItems
18263
+ ]
18264
+ );
17823
18265
  const collapseAll = reactExports.useCallback(() => {
17824
18266
  setOpenFolders(/* @__PURE__ */ new Set());
17825
18267
  openFoldersRef.current = /* @__PURE__ */ new Set();
@@ -17958,6 +18400,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
17958
18400
  request.getPlatform().then((p) => setOsPlatform(p));
17959
18401
  }, []);
17960
18402
  const trashLabel = osPlatform === "darwin" ? t("filePanel.moveToTrash") : osPlatform === "win32" ? t("filePanel.moveToRecycleBin") : t("filePanel.moveToTrash");
18403
+ const prepareFocusAfterDelete = (ids) => {
18404
+ const isDeletedId = (id) => ids.some((deletedId) => id === deletedId || id.startsWith(`${deletedId}/`));
18405
+ const referenceId = (focusedTreeItemIdRef.current && isDeletedId(focusedTreeItemIdRef.current) ? focusedTreeItemIdRef.current : null) ?? (lastSelectedId && isDeletedId(lastSelectedId) ? lastSelectedId : null) ?? ids.find(isDeletedId);
18406
+ if (!referenceId) return;
18407
+ const visibleIds = flattenTree(data);
18408
+ const referenceIndex = visibleIds.indexOf(referenceId);
18409
+ const targetId = (referenceIndex !== -1 ? visibleIds.slice(referenceIndex + 1).find((id) => !isDeletedId(id)) : void 0) ?? (referenceIndex !== -1 ? [...visibleIds.slice(0, referenceIndex)].reverse().find((id) => !isDeletedId(id)) : void 0) ?? visibleIds.find((id) => !isDeletedId(id));
18410
+ pendingFocusIdRef.current = targetId ?? null;
18411
+ pendingFocusRestoreRef.current = true;
18412
+ };
17961
18413
  const deleteNode = async (ids) => {
17962
18414
  if (ids.length === 0 || !activeProjectId) return;
17963
18415
  await confirm2({
@@ -17986,7 +18438,9 @@ const FilePanel = reactExports.memo(function FilePanel2({
17986
18438
  } catch (err) {
17987
18439
  console.error("Delete failed:", extractErrorMessage(err));
17988
18440
  }
18441
+ prepareFocusAfterDelete(ids);
17989
18442
  setSelectedIds(/* @__PURE__ */ new Set());
18443
+ setLastSelectedId(null);
17990
18444
  refresh();
17991
18445
  return "trashed";
17992
18446
  }
@@ -18004,7 +18458,9 @@ const FilePanel = reactExports.memo(function FilePanel2({
18004
18458
  } catch (err) {
18005
18459
  console.error("Delete failed:", extractErrorMessage(err));
18006
18460
  }
18461
+ prepareFocusAfterDelete(ids);
18007
18462
  setSelectedIds(/* @__PURE__ */ new Set());
18463
+ setLastSelectedId(null);
18008
18464
  refresh();
18009
18465
  return "deleted";
18010
18466
  }
@@ -18445,6 +18901,47 @@ const FilePanel = reactExports.memo(function FilePanel2({
18445
18901
  }
18446
18902
  return null;
18447
18903
  };
18904
+ const handleFileActionKeyDown = (event, action) => {
18905
+ if (event.key === "ArrowLeft" || event.key === "ArrowRight" || event.key === "Home" || event.key === "End") {
18906
+ handleFileNavigationKeyDown(event, fileActionItems, { type: "action", action });
18907
+ return;
18908
+ }
18909
+ if (event.key === "ArrowDown") {
18910
+ event.preventDefault();
18911
+ event.stopPropagation();
18912
+ const firstTreeItem = treeNavigationItems[0];
18913
+ if (firstTreeItem) focusFileNavigationItem(firstTreeItem);
18914
+ return;
18915
+ }
18916
+ if (event.key !== "Enter" && event.key !== " " && event.key !== "Spacebar") return;
18917
+ event.preventDefault();
18918
+ event.stopPropagation();
18919
+ switch (action) {
18920
+ case "reveal":
18921
+ if (cwd) void revealInFinder(cwd);
18922
+ break;
18923
+ case "editor":
18924
+ if (cwd) {
18925
+ const editorName = useAppStore.getState().editor.name;
18926
+ void electron.openInEditor(cwd, editorName).catch((err) => {
18927
+ console.error("openInEditor failed:", extractErrorMessage(err));
18928
+ });
18929
+ }
18930
+ break;
18931
+ case "new-file":
18932
+ createIn(getSelectedFolder(), false);
18933
+ break;
18934
+ case "new-folder":
18935
+ createIn(getSelectedFolder(), true);
18936
+ break;
18937
+ case "refresh":
18938
+ refresh();
18939
+ break;
18940
+ case "collapse":
18941
+ collapseAll();
18942
+ break;
18943
+ }
18944
+ };
18448
18945
  if (!projectId) {
18449
18946
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-full items-center justify-center text-xs text-muted-foreground", children: t("filePanel.noProject", "No project selected") });
18450
18947
  }
@@ -18464,9 +18961,12 @@ const FilePanel = reactExports.memo(function FilePanel2({
18464
18961
  onEditChange: setEditingValue,
18465
18962
  onEditSubmit: submitEdit,
18466
18963
  onEditCancel: () => setEditingId(null),
18467
- actions
18964
+ actions,
18965
+ onKeyDown: handleTreeKeyDown,
18966
+ registerRef: registerTreeItemRef,
18967
+ onFocus: handleTreeItemFocus
18468
18968
  };
18469
- return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "flex h-full min-h-0 flex-col text-xs w-full", children: [
18969
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full min-h-0 flex-col text-xs w-full", children: [
18470
18970
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-10 items-center gap-0.5 border-b border-border", children: [
18471
18971
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex text-muted-foreground items-center gap-1 px-3", children: [
18472
18972
  /* @__PURE__ */ jsxRuntimeExports.jsx(Folders, { className: "size-3.5" }),
@@ -18477,10 +18977,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18477
18977
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18478
18978
  Button,
18479
18979
  {
18980
+ ref: (element) => registerNavigationActionRef("reveal", element),
18480
18981
  variant: "ghost",
18481
18982
  size: "icon",
18983
+ tabIndex: -1,
18482
18984
  className: "size-6 text-muted-foreground hover:text-foreground",
18483
18985
  disabled: !cwd,
18986
+ onKeyDown: (event) => handleFileActionKeyDown(event, "reveal"),
18987
+ onFocus: () => {
18988
+ lastFocusedActionRef.current = "reveal";
18989
+ },
18484
18990
  onClick: () => revealInFinder(cwd),
18485
18991
  title: t("filePanel.revealInFinder"),
18486
18992
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "size-3.5" })
@@ -18489,10 +18995,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18489
18995
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18490
18996
  Button,
18491
18997
  {
18998
+ ref: (element) => registerNavigationActionRef("editor", element),
18492
18999
  variant: "ghost",
18493
19000
  size: "icon",
19001
+ tabIndex: -1,
18494
19002
  className: "size-6 text-muted-foreground hover:text-foreground",
18495
19003
  disabled: !cwd,
19004
+ onKeyDown: (event) => handleFileActionKeyDown(event, "editor"),
19005
+ onFocus: () => {
19006
+ lastFocusedActionRef.current = "editor";
19007
+ },
18496
19008
  onClick: () => {
18497
19009
  if (!cwd) return;
18498
19010
  const editorName = useAppStore.getState().editor.name;
@@ -18510,10 +19022,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18510
19022
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18511
19023
  Button,
18512
19024
  {
19025
+ ref: (element) => registerNavigationActionRef("new-file", element),
18513
19026
  variant: "ghost",
18514
19027
  size: "icon",
19028
+ tabIndex: -1,
18515
19029
  className: "size-6 text-muted-foreground hover:text-foreground",
18516
19030
  disabled: loading,
19031
+ onKeyDown: (event) => handleFileActionKeyDown(event, "new-file"),
19032
+ onFocus: () => {
19033
+ lastFocusedActionRef.current = "new-file";
19034
+ },
18517
19035
  onClick: () => createIn(getSelectedFolder(), false),
18518
19036
  title: t("filePanel.newFile"),
18519
19037
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(FilePlus, { className: "size-3.5" })
@@ -18522,10 +19040,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18522
19040
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18523
19041
  Button,
18524
19042
  {
19043
+ ref: (element) => registerNavigationActionRef("new-folder", element),
18525
19044
  variant: "ghost",
18526
19045
  size: "icon",
19046
+ tabIndex: -1,
18527
19047
  className: "size-6 text-muted-foreground hover:text-foreground",
18528
19048
  disabled: loading,
19049
+ onKeyDown: (event) => handleFileActionKeyDown(event, "new-folder"),
19050
+ onFocus: () => {
19051
+ lastFocusedActionRef.current = "new-folder";
19052
+ },
18529
19053
  onClick: () => createIn(getSelectedFolder(), true),
18530
19054
  title: t("filePanel.newFolder"),
18531
19055
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(FolderPlus, { className: "size-3.5" })
@@ -18534,10 +19058,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18534
19058
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18535
19059
  Button,
18536
19060
  {
19061
+ ref: (element) => registerNavigationActionRef("refresh", element),
18537
19062
  variant: "ghost",
18538
19063
  size: "icon",
19064
+ tabIndex: -1,
18539
19065
  className: "size-6 text-muted-foreground hover:text-foreground",
18540
19066
  disabled: loading,
19067
+ onKeyDown: (event) => handleFileActionKeyDown(event, "refresh"),
19068
+ onFocus: () => {
19069
+ lastFocusedActionRef.current = "refresh";
19070
+ },
18541
19071
  onClick: refresh,
18542
19072
  title: t("filePanel.refresh", "Refresh"),
18543
19073
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(RefreshCw, { className: "size-3.5" })
@@ -18546,10 +19076,16 @@ const FilePanel = reactExports.memo(function FilePanel2({
18546
19076
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18547
19077
  Button,
18548
19078
  {
19079
+ ref: (element) => registerNavigationActionRef("collapse", element),
18549
19080
  variant: "ghost",
18550
19081
  size: "icon",
19082
+ tabIndex: -1,
18551
19083
  className: "size-6 text-muted-foreground hover:text-foreground",
18552
19084
  disabled: loading,
19085
+ onKeyDown: (event) => handleFileActionKeyDown(event, "collapse"),
19086
+ onFocus: () => {
19087
+ lastFocusedActionRef.current = "collapse";
19088
+ },
18553
19089
  onClick: collapseAll,
18554
19090
  title: t("filePanel.collapseFolders"),
18555
19091
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(ListChevronsDownUp, { className: "size-3.5" })
@@ -18571,11 +19107,18 @@ const FilePanel = reactExports.memo(function FilePanel2({
18571
19107
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground/70", children: t("filePanel.emptyDirectory") })
18572
19108
  ]
18573
19109
  }
18574
- ) : /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1 pl-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenu, { children: [
19110
+ ) : /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1 px-1", children: /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenu, { children: [
18575
19111
  /* @__PURE__ */ jsxRuntimeExports.jsx(
18576
19112
  ContextMenuTrigger,
18577
19113
  {
18578
- render: /* @__PURE__ */ jsxRuntimeExports.jsx("div", {}),
19114
+ render: /* @__PURE__ */ jsxRuntimeExports.jsx(
19115
+ "div",
19116
+ {
19117
+ ref: treeRef,
19118
+ role: "tree",
19119
+ "aria-label": t("filePanel.title", "Files")
19120
+ }
19121
+ ),
18579
19122
  className: "min-h-full py-1",
18580
19123
  onClick: (e) => {
18581
19124
  if (e.target === e.currentTarget) clearSelection();
@@ -18703,6 +19246,10 @@ function findNode(node, id) {
18703
19246
  }
18704
19247
  return null;
18705
19248
  }
19249
+ const ADD_TERMINAL_NAVIGATION_ID = "__add_terminal__";
19250
+ function terminalNavigationItemKey(item) {
19251
+ return item.type === "add" ? ADD_TERMINAL_NAVIGATION_ID : item.id;
19252
+ }
18706
19253
  function TerminalPanel({
18707
19254
  projectId,
18708
19255
  activeTerminalId,
@@ -18712,7 +19259,51 @@ function TerminalPanel({
18712
19259
  const projectState = useProjectState(projectId);
18713
19260
  const terminals = projectState.terminals;
18714
19261
  const updateProjectState = useAppStore((s15) => s15.updateProjectState);
18715
- async function createTerminal() {
19262
+ const navigationItemRefs = reactExports.useRef(/* @__PURE__ */ new Map());
19263
+ const focusedNavigationItemIdRef = reactExports.useRef(null);
19264
+ const navigationItems = reactExports.useMemo(() => {
19265
+ const items = [{ type: "add" }];
19266
+ items.push(
19267
+ ...terminals.map(
19268
+ (terminal) => ({ type: "terminal", id: terminal.id })
19269
+ )
19270
+ );
19271
+ return items;
19272
+ }, [terminals]);
19273
+ const terminalItems = reactExports.useMemo(
19274
+ () => navigationItems.filter(
19275
+ (item) => item.type === "terminal"
19276
+ ),
19277
+ [navigationItems]
19278
+ );
19279
+ const registerNavigationItemRef = reactExports.useCallback((id, element) => {
19280
+ if (element) {
19281
+ navigationItemRefs.current.set(id, element);
19282
+ } else {
19283
+ navigationItemRefs.current.delete(id);
19284
+ }
19285
+ }, []);
19286
+ const focusNavigationItem = reactExports.useCallback((item) => {
19287
+ const element = navigationItemRefs.current.get(terminalNavigationItemKey(item));
19288
+ if (!element) return;
19289
+ element.focus({ preventScroll: true });
19290
+ element.scrollIntoView({ block: "nearest" });
19291
+ }, []);
19292
+ const focusTerminalList = reactExports.useCallback(() => {
19293
+ const activeItem = activeTerminalId ? navigationItems.find(
19294
+ (item) => item.type === "terminal" && item.id === activeTerminalId
19295
+ ) : void 0;
19296
+ focusNavigationItem(activeItem ?? navigationItems[0]);
19297
+ }, [activeTerminalId, focusNavigationItem, navigationItems]);
19298
+ useFocusTarget("terminal-list-content", focusTerminalList);
19299
+ const selectTerminal = reactExports.useCallback(
19300
+ (terminalId) => {
19301
+ updateProjectState(projectId, () => ({ activeTerminalId: terminalId }));
19302
+ onSelectTerminal(terminalId);
19303
+ },
19304
+ [onSelectTerminal, projectId, updateProjectState]
19305
+ );
19306
+ const createTerminal = reactExports.useCallback(async () => {
18716
19307
  if (!projectId) return;
18717
19308
  const { terminalId } = await request.createTerminal({ projectId, cwd: "", clientId });
18718
19309
  updateProjectState(projectId, (prev) => ({
@@ -18720,9 +19311,14 @@ function TerminalPanel({
18720
19311
  activeTerminalId: terminalId
18721
19312
  }));
18722
19313
  onSelectTerminal(terminalId);
18723
- }
19314
+ }, [onSelectTerminal, projectId, updateProjectState]);
18724
19315
  async function deleteTerminal(terminalId, e) {
18725
- e.stopPropagation();
19316
+ e?.stopPropagation();
19317
+ const shouldRestoreFocus = focusedNavigationItemIdRef.current === terminalId;
19318
+ const deletedIndex = navigationItems.findIndex(
19319
+ (item) => item.type === "terminal" && item.id === terminalId
19320
+ );
19321
+ const focusTarget = deletedIndex === -1 ? void 0 : navigationItems[deletedIndex + 1] ?? navigationItems[deletedIndex - 1] ?? navigationItems[0];
18726
19322
  destroyTerminalInstance(terminalId);
18727
19323
  await request.killTerminal({ terminalId });
18728
19324
  updateProjectState(projectId, (prev) => {
@@ -18732,7 +19328,81 @@ function TerminalPanel({
18732
19328
  activeTerminalId: prev.activeTerminalId === terminalId ? nextList[nextList.length - 1]?.id ?? null : prev.activeTerminalId
18733
19329
  };
18734
19330
  });
19331
+ if (shouldRestoreFocus && focusTarget) {
19332
+ window.requestAnimationFrame(() => focusNavigationItem(focusTarget));
19333
+ }
18735
19334
  }
19335
+ const handleNavigationKeyDown = reactExports.useCallback(
19336
+ (event, item) => {
19337
+ const { key } = event;
19338
+ if (item.type === "add") {
19339
+ if (key === "ArrowLeft" || key === "ArrowRight" || key === "Home" || key === "End") {
19340
+ event.preventDefault();
19341
+ event.stopPropagation();
19342
+ focusNavigationItem(item);
19343
+ return;
19344
+ }
19345
+ if (key === "ArrowDown") {
19346
+ event.preventDefault();
19347
+ event.stopPropagation();
19348
+ const firstTerminal = terminalItems[0];
19349
+ if (firstTerminal) focusNavigationItem(firstTerminal);
19350
+ return;
19351
+ }
19352
+ if (key === "Enter" || key === " " || key === "Spacebar") {
19353
+ event.preventDefault();
19354
+ event.stopPropagation();
19355
+ void createTerminal();
19356
+ }
19357
+ return;
19358
+ }
19359
+ const isVerticalNavigationKey = key === "ArrowUp" || key === "ArrowDown" || key === "Home" || key === "End";
19360
+ if (isVerticalNavigationKey) {
19361
+ event.preventDefault();
19362
+ event.stopPropagation();
19363
+ const currentIndex = terminalItems.findIndex((terminal) => terminal.id === item.id);
19364
+ if (key === "ArrowUp" && currentIndex === 0) {
19365
+ focusNavigationItem({ type: "add" });
19366
+ return;
19367
+ }
19368
+ if (terminalItems.length === 0) return;
19369
+ const nextIndex = key === "Home" ? 0 : key === "End" ? terminalItems.length - 1 : Math.max(
19370
+ 0,
19371
+ Math.min(
19372
+ terminalItems.length - 1,
19373
+ currentIndex + (key === "ArrowDown" ? 1 : -1)
19374
+ )
19375
+ );
19376
+ const nextTerminal = terminalItems[nextIndex];
19377
+ if (nextTerminal) focusNavigationItem(nextTerminal);
19378
+ return;
19379
+ }
19380
+ if (key === "/") {
19381
+ event.preventDefault();
19382
+ event.stopPropagation();
19383
+ const target = event.currentTarget;
19384
+ const rect = target.getBoundingClientRect();
19385
+ target.dispatchEvent(
19386
+ new MouseEvent("contextmenu", {
19387
+ bubbles: true,
19388
+ cancelable: true,
19389
+ view: window,
19390
+ button: 2,
19391
+ buttons: 2,
19392
+ clientX: rect.left + rect.width / 2,
19393
+ clientY: rect.top + rect.height / 2
19394
+ })
19395
+ );
19396
+ return;
19397
+ }
19398
+ if (key === "Enter" || key === " " || key === "Spacebar") {
19399
+ event.preventDefault();
19400
+ event.stopPropagation();
19401
+ selectTerminal(item.id);
19402
+ }
19403
+ },
19404
+ [createTerminal, focusNavigationItem, selectTerminal, terminalItems]
19405
+ );
18736
19406
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-full flex-col", children: [
18737
19407
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex h-10 items-center gap-0.5 border-b border-border", children: [
18738
19408
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex text-muted-foreground items-center gap-1 px-3", children: [
@@ -18742,10 +19412,16 @@ function TerminalPanel({
18742
19412
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "ml-auto mr-2 flex items-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
18743
19413
  Button,
18744
19414
  {
19415
+ ref: (element) => registerNavigationItemRef(ADD_TERMINAL_NAVIGATION_ID, element),
18745
19416
  variant: "ghost",
18746
19417
  size: "icon",
19418
+ tabIndex: -1,
18747
19419
  className: "size-6 text-muted-foreground hover:text-foreground",
18748
19420
  onClick: () => void createTerminal(),
19421
+ onKeyDown: (event) => handleNavigationKeyDown(event, { type: "add" }),
19422
+ onFocus: () => {
19423
+ focusedNavigationItemIdRef.current = ADD_TERMINAL_NAVIGATION_ID;
19424
+ },
18749
19425
  "aria-label": t("terminalPanel.addTerminal", "Add terminal"),
18750
19426
  children: /* @__PURE__ */ jsxRuntimeExports.jsx(Plus, { className: "size-3.5" })
18751
19427
  }
@@ -18754,41 +19430,70 @@ function TerminalPanel({
18754
19430
  terminals.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center text-muted-foreground", children: [
18755
19431
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "size-10 rounded-full bg-muted flex items-center justify-center mb-3 -mt-10", children: /* @__PURE__ */ jsxRuntimeExports.jsx(SquareTerminal, { className: "size-5 text-muted-foreground/60" }) }),
18756
19432
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-xs text-muted-foreground/70", children: t("terminalPanel.noTerminalSelected", "No terminals") })
18757
- ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-0.5 py-1 px-1", children: terminals.map((terminal) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
18758
- "button",
18759
- {
18760
- type: "button",
18761
- onClick: () => {
18762
- updateProjectState(projectId, () => ({ activeTerminalId: terminal.id }));
18763
- onSelectTerminal(terminal.id);
18764
- },
18765
- className: cn$1(
18766
- "flex h-8 items-center gap-2 rounded-md pl-2 pr-1.5 text-xs w-full transition-colors",
18767
- terminal.id === activeTerminalId ? "bg-accent text-accent-foreground" : "text-foreground/70 hover:bg-accent/50 hover:text-foreground"
18768
- ),
18769
- children: [
18770
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18771
- Circle,
19433
+ ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex flex-col gap-0.5 py-1 px-1", children: terminals.map((terminal) => /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenu, { children: [
19434
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
19435
+ ContextMenuTrigger,
19436
+ {
19437
+ render: /* @__PURE__ */ jsxRuntimeExports.jsx(
19438
+ "button",
18772
19439
  {
18773
- className: cn$1(
18774
- "size-2 shrink-0",
18775
- terminal.running ? "fill-emerald-400 text-emerald-400" : "text-muted-foreground"
18776
- )
19440
+ ref: (element) => registerNavigationItemRef(terminal.id, element),
19441
+ type: "button",
19442
+ tabIndex: -1,
19443
+ className: "outline-0 focus-visible:inset-ring-1 focus-visible:inset-ring-ring/80 rounded-md",
19444
+ "aria-current": terminal.id === activeTerminalId ? "true" : void 0,
19445
+ onKeyDown: (event) => handleNavigationKeyDown(event, { type: "terminal", id: terminal.id }),
19446
+ onFocus: () => {
19447
+ focusedNavigationItemIdRef.current = terminal.id;
19448
+ }
18777
19449
  }
18778
19450
  ),
18779
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-left", children: terminal.id.slice(0, 8) }),
18780
- /* @__PURE__ */ jsxRuntimeExports.jsx(
18781
- "span",
18782
- {
18783
- className: "flex size-5 shrink-0 items-center justify-center rounded hover:bg-background/70",
18784
- onClick: (e) => void deleteTerminal(terminal.id, e),
18785
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "size-3 text-muted-foreground" })
18786
- }
18787
- )
18788
- ]
18789
- },
18790
- terminal.id
18791
- )) }) })
19451
+ onClick: () => selectTerminal(terminal.id),
19452
+ className: cn$1(
19453
+ "flex h-8 items-center gap-2 rounded-md pl-2 pr-1.5 text-xs w-full transition-colors",
19454
+ terminal.id === activeTerminalId ? "bg-accent text-accent-foreground" : "text-foreground/70 hover:bg-accent/50 hover:text-foreground"
19455
+ ),
19456
+ children: [
19457
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
19458
+ Circle,
19459
+ {
19460
+ className: cn$1(
19461
+ "size-2 shrink-0",
19462
+ terminal.running ? "fill-emerald-400 text-emerald-400" : "text-muted-foreground"
19463
+ )
19464
+ }
19465
+ ),
19466
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate text-left", children: terminal.id.slice(0, 8) }),
19467
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
19468
+ "span",
19469
+ {
19470
+ className: "flex size-5 shrink-0 items-center justify-center rounded hover:bg-background/70",
19471
+ onClick: (e) => void deleteTerminal(terminal.id, e),
19472
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$1, { className: "size-3 text-muted-foreground" })
19473
+ }
19474
+ )
19475
+ ]
19476
+ }
19477
+ ),
19478
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuContent, { children: [
19479
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(ContextMenuItem, { onClick: () => selectTerminal(terminal.id), children: [
19480
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Eye, {}),
19481
+ t("terminalPanel.view", "View")
19482
+ ] }),
19483
+ /* @__PURE__ */ jsxRuntimeExports.jsx(ContextMenuSeparator, {}),
19484
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
19485
+ ContextMenuItem,
19486
+ {
19487
+ variant: "destructive",
19488
+ onClick: () => void deleteTerminal(terminal.id),
19489
+ children: [
19490
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, {}),
19491
+ t("terminalPanel.delete", "Delete")
19492
+ ]
19493
+ }
19494
+ )
19495
+ ] })
19496
+ ] }, terminal.id)) }) })
18792
19497
  ] });
18793
19498
  }
18794
19499
  function Panel({
@@ -18801,6 +19506,27 @@ function Panel({
18801
19506
  onSelectTerminal
18802
19507
  }) {
18803
19508
  const { t } = useTranslation();
19509
+ const { focus } = useFocusTargetRegistry();
19510
+ const focusFileTree = reactExports.useCallback(() => {
19511
+ const focusFileTreeContent = () => focus("file-tree-content");
19512
+ if (tab === "files") {
19513
+ focusFileTreeContent();
19514
+ return;
19515
+ }
19516
+ onTabChange("files");
19517
+ window.requestAnimationFrame(focusFileTreeContent);
19518
+ }, [focus, onTabChange, tab]);
19519
+ useFocusTarget("file-tree", focusFileTree, Boolean(projectId));
19520
+ const focusTerminalList = reactExports.useCallback(() => {
19521
+ const focusTerminalListContent = () => focus("terminal-list-content");
19522
+ if (tab === "terminal") {
19523
+ focusTerminalListContent();
19524
+ return;
19525
+ }
19526
+ onTabChange("terminal");
19527
+ window.requestAnimationFrame(focusTerminalListContent);
19528
+ }, [focus, onTabChange, tab]);
19529
+ useFocusTarget("terminal-list", focusTerminalList, Boolean(projectId));
18804
19530
  if (!projectId) {
18805
19531
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-full items-center justify-center text-xs text-muted-foreground border-l border-border bg-background", children: /* @__PURE__ */ jsxRuntimeExports.jsx("span", { children: t("panel.noProjectSelected", "No project selected") }) });
18806
19532
  }
@@ -18821,7 +19547,7 @@ function Panel({
18821
19547
  t("panel.terminal", "Terminal")
18822
19548
  ] })
18823
19549
  ] }) }),
18824
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "files", className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
19550
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "files", keepMounted: true, className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
18825
19551
  FilePanel,
18826
19552
  {
18827
19553
  projectId,
@@ -18829,7 +19555,7 @@ function Panel({
18829
19555
  onPreviewFile
18830
19556
  }
18831
19557
  ) }),
18832
- /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "terminal", className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
19558
+ /* @__PURE__ */ jsxRuntimeExports.jsx(TabsContent, { value: "terminal", keepMounted: true, className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntimeExports.jsx(
18833
19559
  TerminalPanel,
18834
19560
  {
18835
19561
  projectId,
@@ -18911,61 +19637,21 @@ function Session({ session }) {
18911
19637
  const [connectionError, setConnectionError] = reactExports.useState(false);
18912
19638
  reactExports.useEffect(() => {
18913
19639
  setConnectionError(false);
18914
- request.loadSession({ sessionId }).catch((err) => {
19640
+ const sessionState = useAppStore.getState().getSessionState(sessionId);
19641
+ const shouldLoadHistory = sessionState.messages.length === 0 && !isCreatingSession && sessionState.loadedAt === null;
19642
+ if (shouldLoadHistory && fetchingRef.current === sessionId) return;
19643
+ if (shouldLoadHistory) fetchingRef.current = sessionId;
19644
+ void loadSession(sessionId, { loadHistory: shouldLoadHistory }).catch((err) => {
19645
+ if (err instanceof SessionLifecycleBusyError) return;
18915
19646
  setConnectionError(true);
18916
19647
  toast.error(err instanceof Error ? err.message : String(err));
19648
+ }).finally(() => {
19649
+ if (fetchingRef.current === sessionId) fetchingRef.current = null;
18917
19650
  });
18918
- const sessionState = useAppStore.getState().getSessionState(sessionId);
18919
- if (sessionState.messages.length > 0 || isCreatingSession || sessionState.loadedAt !== null) {
18920
- return;
18921
- }
18922
- if (fetchingRef.current === sessionId) return;
18923
- fetchingRef.current = sessionId;
18924
- async function fetchHistory() {
18925
- useAppStore.getState().updateSessionState(sessionId, (prev) => ({
18926
- ...reduceFlushStreaming(prev),
18927
- isLoading: true
18928
- }));
18929
- try {
18930
- const result = await request.getSessionHistory({ sessionId });
18931
- let state = useAppStore.getState().getSessionState(sessionId);
18932
- state = { ...state, messages: [], activeToolCalls: /* @__PURE__ */ new Map(), activeSubagents: /* @__PURE__ */ new Map() };
18933
- const displayIds = /* @__PURE__ */ new Set();
18934
- for (const notification of result.messages) {
18935
- const displayId = notification?.update?._meta?.fello?.displayId;
18936
- if (displayId) {
18937
- displayIds.add(displayId);
18938
- }
18939
- if (!notification?.update) continue;
18940
- state = reduceSessionNotification(sessionId, state, notification);
18941
- }
18942
- for (const notification of state.pendingNotifications) {
18943
- const did = notification.update._meta?.fello?.displayId;
18944
- if (did && displayIds.has(did)) {
18945
- continue;
18946
- }
18947
- state = reduceSessionNotification(sessionId, state, notification);
18948
- }
18949
- state = reduceFlushStreaming(state);
18950
- state = {
18951
- ...state,
18952
- isLoading: false,
18953
- pendingNotifications: [],
18954
- loadedAt: Date.now()
18955
- };
18956
- useAppStore.getState().updateSessionState(sessionId, () => state);
18957
- } catch (err) {
18958
- console.error("Failed to fetch session history", err);
18959
- useAppStore.getState().updateSessionState(sessionId, (prev) => ({ ...prev, isLoading: false }));
18960
- } finally {
18961
- fetchingRef.current = null;
18962
- }
18963
- }
18964
- void fetchHistory();
18965
19651
  }, [sessionId, isCreatingSession, toast]);
18966
19652
  return /* @__PURE__ */ jsxRuntimeExports.jsx("main", { ref: setMainEl, className: "flex min-w-0 flex-1 flex-col relative overflow-hidden", children: isLoading || sessionConnected !== "connected" || isCreatingSession ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex flex-1 flex-col items-center justify-center gap-4 relative", children: [
18967
19653
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "absolute left-0 top-0 right-0 h-12", style: { WebkitAppRegion: "drag" } }),
18968
- connectionError && sessionConnected !== "connected" && !isCreatingSession ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
19654
+ connectionError && !isCreatingSession ? /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
18969
19655
  /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm font-normal text-muted-foreground", children: t("session.connectionFailed") }),
18970
19656
  /* @__PURE__ */ jsxRuntimeExports.jsxs(
18971
19657
  Button,
@@ -18974,7 +19660,8 @@ function Session({ session }) {
18974
19660
  size: "sm",
18975
19661
  onClick: () => {
18976
19662
  setConnectionError(false);
18977
- request.loadSession({ sessionId, force: true }).catch((err) => {
19663
+ void loadSession(sessionId, { force: true, loadHistory: true }).catch((err) => {
19664
+ if (err instanceof SessionLifecycleBusyError) return;
18978
19665
  setConnectionError(true);
18979
19666
  toast.error(err instanceof Error ? err.message : String(err));
18980
19667
  });