@nextclaw/ui 0.25.4 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (457) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/.vite/manifest.json +1146 -1390
  3. package/dist/assets/{abnfDiagram-VRR7QNED-DX_u5BBX.js → abnfDiagram-VRR7QNED-Bjrmb5-o.js} +1 -1
  4. package/dist/assets/account-panel-C1S3xtUB.js +1 -0
  5. package/dist/assets/{aiden0z-pptx-renderer.es-C-E9e5yB.js → aiden0z-pptx-renderer.es-DO4DCX3e.js} +1 -1
  6. package/dist/assets/api-D9e9cHtW.js +20 -0
  7. package/dist/assets/app-presenter-provider-J9IgTbc9.js +124 -0
  8. package/dist/assets/appearance-settings-page-BljTr6nB.js +1 -0
  9. package/dist/assets/{arc-Cxwa624o.js → arc-g4XaP3S4.js} +1 -1
  10. package/dist/assets/architecture-TIHT7OUA-BWywYH_m.js +1 -0
  11. package/dist/assets/{architectureDiagram-ZJ3FMSHR-D8mCj0H1.js → architectureDiagram-ZJ3FMSHR-CAP7YDux.js} +1 -1
  12. package/dist/assets/{blockDiagram-677ZJIJ3-CbGC1IHl.js → blockDiagram-677ZJIJ3-DhaP0zUG.js} +1 -1
  13. package/dist/assets/{book-open-xqEj1OLE.js → book-open-vxpV2eSM.js} +1 -1
  14. package/dist/assets/{c4Diagram-LMCZKHZV-BQhGC1Vc.js → c4Diagram-LMCZKHZV-DHCQJJkD.js} +1 -1
  15. package/dist/assets/card-D9NYhSdf.js +1 -0
  16. package/dist/assets/channel-1nKIAEXr.js +1 -0
  17. package/dist/assets/channels-list-page-BiHA1zZd.js +8 -0
  18. package/dist/assets/chunk-2Q5K7J3B-CAwv72v4.js +1 -0
  19. package/dist/assets/{chunk-32BRIVSS-B74ZZwYG.js → chunk-32BRIVSS-BcQlxl4v.js} +1 -1
  20. package/dist/assets/{chunk-52WLFC77-BvmxW_f_.js → chunk-52WLFC77-ClPpG-2S.js} +1 -1
  21. package/dist/assets/{chunk-5FCAYU7R-DQvBRnwL.js → chunk-5FCAYU7R-B_qmYOdX.js} +1 -1
  22. package/dist/assets/{chunk-5HE753X5-CDIH0_y3.js → chunk-5HE753X5-DTO-V56q.js} +1 -1
  23. package/dist/assets/{chunk-5JV3BV7I-CcevlKd-.js → chunk-5JV3BV7I-CU1SOaaG.js} +1 -1
  24. package/dist/assets/{chunk-5TONJI2A-_3dxVdnY.js → chunk-5TONJI2A-CzSDkWNa.js} +1 -1
  25. package/dist/assets/{chunk-5VM5RSS4-pGO5vvo-.js → chunk-5VM5RSS4-ChkfqIRE.js} +1 -1
  26. package/dist/assets/{chunk-7BUUIJ7U-DEKF5uAN.js → chunk-7BUUIJ7U-Du3Ozi62.js} +1 -1
  27. package/dist/assets/{chunk-BIQX33UG-CjBFgq2r.js → chunk-BIQX33UG-C-HVafHB.js} +1 -1
  28. package/dist/assets/{chunk-C7G6YPKG-e_K9OGTz.js → chunk-C7G6YPKG-BSjZ86D0.js} +1 -1
  29. package/dist/assets/{chunk-CQNSW5MT-C2IiHyHz.js → chunk-CQNSW5MT-1D1W2lF6.js} +1 -1
  30. package/dist/assets/{chunk-CYSBUYHQ-DCC6KmGp.js → chunk-CYSBUYHQ-ISpyj_lK.js} +1 -1
  31. package/dist/assets/{chunk-EMLP6XTP-BYGgekQ0.js → chunk-EMLP6XTP-Cp8iUBt2.js} +1 -1
  32. package/dist/assets/{chunk-EX3LRPZG-FGcwuVsA.js → chunk-EX3LRPZG-BN5RzF5j.js} +1 -1
  33. package/dist/assets/{chunk-FWX5IMBZ-CV3Ih_Os.js → chunk-FWX5IMBZ-DecJDW4r.js} +2 -2
  34. package/dist/assets/{chunk-HOUHSVGY-CXpq_hfV.js → chunk-HOUHSVGY-BE_XNgGk.js} +1 -1
  35. package/dist/assets/{chunk-ICXQ74PX-CZIpjupq.js → chunk-ICXQ74PX-BFOKMkWV.js} +1 -1
  36. package/dist/assets/{chunk-JG7HCLWE-CdgwBpW7.js → chunk-JG7HCLWE-DL-pl8VB.js} +1 -1
  37. package/dist/assets/{chunk-JWPE2WC7-BPjAZpOQ.js → chunk-JWPE2WC7-B-bcwfmh.js} +1 -1
  38. package/dist/assets/{chunk-MOJQB5TN-DbJDm8to.js → chunk-MOJQB5TN-BC0taFro.js} +1 -1
  39. package/dist/assets/{chunk-MOZMSUNE-BUa1fqKn.js → chunk-MOZMSUNE-RrhfU6MO.js} +1 -1
  40. package/dist/assets/{chunk-OGEWGWER-CtnzLgRu.js → chunk-OGEWGWER-TuI7SR7i.js} +1 -1
  41. package/dist/assets/{chunk-OSBZ3O6U-fUgdpTUM.js → chunk-OSBZ3O6U-C5jMBKlU.js} +1 -1
  42. package/dist/assets/{chunk-PUDLZKDR-CtDWZT9-.js → chunk-PUDLZKDR-C5lMBn0K.js} +1 -1
  43. package/dist/assets/{chunk-Q4XR5HBZ-BxnK2qxr.js → chunk-Q4XR5HBZ-B-kzUbwT.js} +1 -1
  44. package/dist/assets/{chunk-QBLGF6JB-CH4UKoCF.js → chunk-QBLGF6JB-CRb_WAEj.js} +1 -1
  45. package/dist/assets/{chunk-R7FJI6CG-BxwFoF1v.js → chunk-R7FJI6CG-De6Y7ozO.js} +1 -1
  46. package/dist/assets/{chunk-RYQCIY6F-DpHAmq7O.js → chunk-RYQCIY6F-Igv92q8k.js} +1 -1
  47. package/dist/assets/{chunk-U6XO7XAA-BjH2VUHU.js → chunk-U6XO7XAA-bCjRshkT.js} +1 -1
  48. package/dist/assets/{chunk-V7JOEXUC-DKJZ3HGj.js → chunk-V7JOEXUC-0J1s_Kgq.js} +1 -1
  49. package/dist/assets/chunk-VAUOI2AC-DnaryNw2.js +1 -0
  50. package/dist/assets/{chunk-VR4S4FIN-Cf-o2GtI.js → chunk-VR4S4FIN-DX6lXnNx.js} +1 -1
  51. package/dist/assets/{chunk-WYO6CB5R-zeNXGm20.js → chunk-WYO6CB5R-DLqMXfFC.js} +3 -3
  52. package/dist/assets/chunk-XXDRQBXY-BToo1uqb.js +1 -0
  53. package/dist/assets/{chunk-YOTPTUD7-Ck87Kqxe.js → chunk-YOTPTUD7-CY4obsV0.js} +1 -1
  54. package/dist/assets/{chunk-ZGVPDNZ5-BbfK6Bfd.js → chunk-ZGVPDNZ5-BleImZKe.js} +1 -1
  55. package/dist/assets/{chunk-ZIRB5QZD-BDpzh4Yl.js → chunk-ZIRB5QZD-C1TfdjpX.js} +1 -1
  56. package/dist/assets/{circle-dashed-CU3yApvP.js → circle-dashed-CEEssYIw.js} +1 -1
  57. package/dist/assets/classDiagram-OUVF2IWQ-D_TusZGx.js +1 -0
  58. package/dist/assets/classDiagram-v2-EOCWNBFH-B1NFZTmS.js +1 -0
  59. package/dist/assets/client-C6YQx7A-.js +1 -0
  60. package/dist/assets/config-split-page-DKPelvjR.js +1 -0
  61. package/dist/assets/confirm-dialog-BCGeh61X.js +1 -0
  62. package/dist/assets/{cose-bilkent-JH36ORCC-CQfMxKCT.js → cose-bilkent-JH36ORCC-CVgUHXkj.js} +1 -1
  63. package/dist/assets/createLucideIcon-CF8U9dh7.js +1 -0
  64. package/dist/assets/cynefin-VYW2F7L2-CJZSs5s_.js +1 -0
  65. package/dist/assets/{cynefinDiagram-TSTJHNR4-CxFTiC-p.js → cynefinDiagram-TSTJHNR4-cdfImbfI.js} +1 -1
  66. package/dist/assets/{dagre-CaBNMcB1.js → dagre-CHNN9L9I.js} +1 -1
  67. package/dist/assets/{dagre-VKFMJZFB-S_7Hc7bI.js → dagre-VKFMJZFB-PscaENwr.js} +1 -1
  68. package/dist/assets/desktop-capabilities-page-BENHdKfk.js +1 -0
  69. package/dist/assets/desktop-update-config-BJMTQMRS.js +1 -0
  70. package/dist/assets/{diagram-FQU43EPY-C7zENvFb.js → diagram-FQU43EPY-CH_wye41.js} +1 -1
  71. package/dist/assets/{diagram-G47NLZAW-DqYTCqZA.js → diagram-G47NLZAW-Dtjpmi6D.js} +1 -1
  72. package/dist/assets/{diagram-NH7WQ7WH-BfSJtXRc.js → diagram-NH7WQ7WH-UdjLHyaz.js} +1 -1
  73. package/dist/assets/{diagram-OA4YK3LP-CFO-j67H.js → diagram-OA4YK3LP-DYsToEaL.js} +1 -1
  74. package/dist/assets/{diagram-WEI45ONY-DBQDbTaJ.js → diagram-WEI45ONY-CA7kuIer.js} +1 -1
  75. package/dist/assets/dialog-DQXou6pg.js +5 -0
  76. package/dist/assets/dist-CiC9Fd9J.js +1 -0
  77. package/dist/assets/doc-browser-CCYS_csH.js +1 -0
  78. package/dist/assets/doc-browser-context-CPLWVFLd.js +1 -0
  79. package/dist/assets/{docx-preview-B4-aDfvO.js → docx-preview-D--EsUWi.js} +1 -1
  80. package/dist/assets/{ebnfDiagram-CCIWWBDH-CfDNIXFN.js → ebnfDiagram-CCIWWBDH-BrjaoOuq.js} +1 -1
  81. package/dist/assets/{erDiagram-Q63AITRT-D95rFXMM.js → erDiagram-Q63AITRT-nZQa2kCM.js} +1 -1
  82. package/dist/assets/es2015-DHRpDU-q.js +41 -0
  83. package/dist/assets/eventmodeling-45OFAUF4-rc7kUq4V.js +1 -0
  84. package/dist/assets/extensions-CsWT7x3v.js +1 -0
  85. package/dist/assets/{eye-C84inPcV.js → eye-DJtw5KJ5.js} +1 -1
  86. package/dist/assets/flowDiagram-23GEKE2U-DAjaeGO8.js +1 -0
  87. package/dist/assets/form-actions-DDQk0END.js +1 -0
  88. package/dist/assets/{ganttDiagram-NO4QXBWP-Bawg0P0r.js → ganttDiagram-NO4QXBWP-CyFZHIHN.js} +1 -1
  89. package/dist/assets/gitGraph-TEB2WS4Q-Ce0gf6ps.js +1 -0
  90. package/dist/assets/{gitGraphDiagram-IHSO6WYX-BbKh9nbL.js → gitGraphDiagram-IHSO6WYX-Dfpq3z2M.js} +1 -1
  91. package/dist/assets/{i18n-20rSH40D.js → i18n-BjPkAKMQ.js} +2 -2
  92. package/dist/assets/info-DKCQHKI2-Cp-Tr78m.js +1 -0
  93. package/dist/assets/{infoDiagram-FWYZ7A6U-DPffZXYh.js → infoDiagram-FWYZ7A6U-Diiz0k1E.js} +1 -1
  94. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CBMsLwZ2.js → ishikawaDiagram-FXEZZL3T-B3R3SN4M.js} +1 -1
  95. package/dist/assets/{journeyDiagram-5HDEW3XC-Mz5U4OzU.js → journeyDiagram-5HDEW3XC-DFOLKiNv.js} +1 -1
  96. package/dist/assets/{kanban-definition-HUTT4EX6-FXZq2k19.js → kanban-definition-HUTT4EX6-BMXpDp3g.js} +1 -1
  97. package/dist/assets/katex-B4FQSo9k.js +1 -0
  98. package/dist/assets/keyboard-shortcuts-settings-page-hqTP7akj.js +1 -0
  99. package/dist/assets/{line-BZwCgT9K.js → line-64_FhCoJ.js} +1 -1
  100. package/dist/assets/{linear-CTe9mKUw.js → linear-aF1fg7bK.js} +1 -1
  101. package/dist/assets/loader-circle-B-4WwzBj.js +1 -0
  102. package/dist/assets/login-page-BUwshAq4.js +1 -0
  103. package/dist/assets/login-page-CdlI6B8e.js +1 -0
  104. package/dist/assets/main-BVYdyT60.css +1 -0
  105. package/dist/assets/main-DYEALeoQ.js +2 -0
  106. package/dist/assets/main-i18n-catalog.config-1o2hjZ0m.js +1 -0
  107. package/dist/assets/{map-Ci48ZwAp.js → map-BC3Amra3.js} +1 -1
  108. package/dist/assets/mcp-marketplace-page-CRRQT6SP.js +1 -0
  109. package/dist/assets/{mermaid-parser.core-CzPD3U_z.js → mermaid-parser.core-DdMcZwnE.js} +2 -2
  110. package/dist/assets/{mermaid.core-geIMNPbV.js → mermaid.core-BHdiEBbI.js} +3 -3
  111. package/dist/assets/{mindmap-definition-LN4V7U3C-xqlKxsr_.js → mindmap-definition-LN4V7U3C-CtHVaZyV.js} +1 -1
  112. package/dist/assets/model-config-page-BSsHOhV7.js +1 -0
  113. package/dist/assets/navigation-history-CyawyVz0.js +1 -0
  114. package/dist/assets/navigation-link-D-fxdv0i.js +3 -0
  115. package/dist/assets/{ordinal-MxnX8yhv.js → ordinal-6b3jw4cz.js} +1 -1
  116. package/dist/assets/packet-7NZHBO7P-BOJuCraS.js +1 -0
  117. package/dist/assets/panel-app-i18n-catalog.config-kQO7QAwH.js +1 -0
  118. package/dist/assets/panelStandalone-BeI0Ndsx.js +2 -0
  119. package/dist/assets/{pegDiagram-2B236MQR-D50MFTN1.js → pegDiagram-2B236MQR-BtbG3Bgu.js} +1 -1
  120. package/dist/assets/pie-RZYD4A2V-D-FEO81x.js +1 -0
  121. package/dist/assets/{pieDiagram-ENE6RG2P-CpA13oiC.js → pieDiagram-ENE6RG2P-FmLl2hzN.js} +1 -1
  122. package/dist/assets/privacy-settings-page-pW_1naDz.js +1 -0
  123. package/dist/assets/projects-k6SLda_A.js +1 -0
  124. package/dist/assets/provider-models-mVzuEQBS.js +1 -0
  125. package/dist/assets/provider-scoped-model-input-CVbtT8L9.js +1 -0
  126. package/dist/assets/providers-config-page-rBlVrHkb.js +1 -0
  127. package/dist/assets/{puzzle-D6gulz7u.js → puzzle-kKiVft9-.js} +1 -1
  128. package/dist/assets/pwa-BgGM4kkY.js +1 -0
  129. package/dist/assets/{quadrantDiagram-ABIIQ3AL-CYCgaj4l.js → quadrantDiagram-ABIIQ3AL-7-OzMNpF.js} +1 -1
  130. package/dist/assets/radar-I7S5WNFK-Bq3eK1vK.js +1 -0
  131. package/dist/assets/railroad-3IZDKUUU-C3uZ1esg.js +1 -0
  132. package/dist/assets/railroad-abnf-AHOZXSZD-D3iZd1KT.js +1 -0
  133. package/dist/assets/railroad-ebnf-EBAXGLYW-Dl0FWqZu.js +1 -0
  134. package/dist/assets/railroad-peg-LSFZ7HO6-B51SbzGp.js +1 -0
  135. package/dist/assets/{railroadDiagram-RFXS5EU6-4LKDGlXN.js → railroadDiagram-RFXS5EU6-B_UVtLJO.js} +1 -1
  136. package/dist/assets/{refresh-cw-h9Xq3LY3.js → refresh-cw-BeG0y6yZ.js} +1 -1
  137. package/dist/assets/remote-wYWqir2w.js +1 -0
  138. package/dist/assets/{requirementDiagram-TGXJPOKE-CxNOU0JH.js → requirementDiagram-TGXJPOKE-D8TO2YeZ.js} +1 -1
  139. package/dist/assets/{rotate-cw-B6xm41Wn.js → rotate-cw-Ci2dcTO5.js} +1 -1
  140. package/dist/assets/runtime-config-page-DCXN0nkS.js +1 -0
  141. package/dist/assets/{sankeyDiagram-HTMAVEWB-DbCBDe2S.js → sankeyDiagram-HTMAVEWB-CUzIcq0B.js} +1 -1
  142. package/dist/assets/{save-fff_WpY2.js → save-Cr895abt.js} +1 -1
  143. package/dist/assets/search-config-page-CNQd481d.js +1 -0
  144. package/dist/assets/secrets-config-page--q7M58L8.js +3 -0
  145. package/dist/assets/security-config-CJb2pK2O.js +1 -0
  146. package/dist/assets/select-Bq-UmfCK.js +1 -0
  147. package/dist/assets/{sequenceDiagram-DBY2YBRQ-DA6W2BS_.js → sequenceDiagram-DBY2YBRQ-kqJzXbwu.js} +1 -1
  148. package/dist/assets/service-apps-panel-iLLEByRF.js +1 -0
  149. package/dist/assets/{settings-2-CE3ELQyk.js → settings-2-IodCcaXd.js} +1 -1
  150. package/dist/assets/{sizeCapture-X5ZJPWSS-T_q_d_VW.js → sizeCapture-X5ZJPWSS-D9ISogq1.js} +1 -1
  151. package/dist/assets/{src-CYpUlx-4.js → src-Bc0PoUJ1.js} +1 -1
  152. package/dist/assets/{stateDiagram-2N3HPSRC-mi8z2G0a.js → stateDiagram-2N3HPSRC-CqH5xc9W.js} +1 -1
  153. package/dist/assets/stateDiagram-v2-6OUMAXLB-CcOGfDdx.js +1 -0
  154. package/dist/assets/status-dot-DUYSKRCU.js +1 -0
  155. package/dist/assets/{swimlanes-5IMT3BWC-DkBEhWE4.js → swimlanes-5IMT3BWC-mwejV-rW.js} +2 -2
  156. package/dist/assets/swimlanesDiagram-G3AALYLV-BMI2k8RZ.js +8 -0
  157. package/dist/assets/tag-chip-CQU51ST3.js +1 -0
  158. package/dist/assets/theme-provider-D-zZkXxS.js +1 -0
  159. package/dist/assets/{timeline-definition-FHXFAJF6-BoFmqBw1.js → timeline-definition-FHXFAJF6-CuikIDlX.js} +1 -1
  160. package/dist/assets/trash-2-BDdqDh6E.js +1 -0
  161. package/dist/assets/treeView-QDETBFTQ-C0_07QI1.js +1 -0
  162. package/dist/assets/treemap-6X3UGDF4-Djpx6ccG.js +1 -0
  163. package/dist/assets/use-config-Bxx7DdaL.js +1 -0
  164. package/dist/assets/{use-desktop-capabilities-BkuRd2cY.js → use-desktop-capabilities-BTgdFgJy.js} +1 -1
  165. package/dist/assets/use-viewport-layout-CDcca0YL.js +1 -0
  166. package/dist/assets/{vennDiagram-L72KCM5P-BlZ3Or5U.js → vennDiagram-L72KCM5P-BD0P0qHh.js} +1 -1
  167. package/dist/assets/wardley-OPB4EBWU-DZVFxu81.js +1 -0
  168. package/dist/assets/{wardleyDiagram-EHGQE667-yDfr33i3.js → wardleyDiagram-EHGQE667-C6ma3t5D.js} +1 -1
  169. package/dist/assets/x-LUUwl8rK.js +1 -0
  170. package/dist/assets/{xychartDiagram-FW5EYKEG-mIXwIGAQ.js → xychartDiagram-FW5EYKEG-D7E40NBk.js} +1 -1
  171. package/dist/index.html +37 -54
  172. package/dist/panel-standalone.html +11 -15
  173. package/package.json +5 -5
  174. package/src/app/components/layout/__tests__/app-layout.test.tsx +8 -0
  175. package/src/app/components/layout/app-layout.tsx +18 -46
  176. package/src/app/configs/__tests__/app-navigation.config.test.ts +4 -0
  177. package/src/app/configs/app-navigation.config.ts +2 -0
  178. package/src/app/configs/page-resource-renderers.config.ts +13 -0
  179. package/src/app/index.tsx +4 -0
  180. package/src/app/presenters/app.presenter.ts +13 -2
  181. package/src/features/agents/components/__tests__/agents-page.test.tsx +4 -0
  182. package/src/features/agents/components/agent-details-dialog.tsx +3 -0
  183. package/src/features/agents/components/agents-page.tsx +7 -3
  184. package/src/features/apps/components/app-package-card.tsx +2 -2
  185. package/src/features/chat/components/conversation/chat-conversation-content.tsx +32 -19
  186. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -0
  187. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  188. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +2 -2
  189. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
  190. package/src/features/chat/components/layout/__tests__/chat-page-shell.test.tsx +7 -6
  191. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +14 -12
  192. package/src/features/chat/components/layout/chat-page-shell.tsx +33 -64
  193. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +8 -4
  194. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +64 -256
  195. package/src/features/chat/components/layout/chat-sidebar.tsx +8 -30
  196. package/src/features/chat/components/providers/chat-runtime.provider.tsx +62 -0
  197. package/src/features/chat/features/conversation/components/__tests__/floating-session-conversation.test.tsx +70 -0
  198. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +27 -0
  199. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +1 -0
  200. package/src/features/chat/features/conversation/components/session-conversation-panel-tab.tsx +25 -0
  201. package/src/features/chat/features/conversation/hooks/use-chat-composer-reference-intent.ts +2 -1
  202. package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +2 -1
  203. package/src/features/chat/features/message/components/__tests__/chat-message-assistant-header.container.test.tsx +3 -0
  204. package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +3 -0
  205. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +3 -0
  206. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -3
  207. package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +20 -0
  208. package/src/features/chat/features/session/components/chat-mobile-session-row.tsx +61 -0
  209. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +0 -35
  210. package/src/features/chat/features/session/components/chat-sidebar-session-entry.tsx +2 -0
  211. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +13 -5
  212. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +5 -3
  213. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +8 -0
  214. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +3 -0
  215. package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +6 -0
  216. package/src/features/chat/features/session/utils/chat-session-route.utils.ts +12 -0
  217. package/src/features/chat/features/workspace/components/__tests__/chat-session-child-sessions.test.tsx +28 -0
  218. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +9 -0
  219. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +6 -2
  220. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +49 -12
  221. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +13 -6
  222. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +6 -0
  223. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +21 -36
  224. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +40 -31
  225. package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +6 -1
  226. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  227. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  228. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +27 -0
  229. package/src/features/chat/features/workspace/utils/__tests__/workspace-file-panel-route.utils.test.ts +94 -0
  230. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +2 -0
  231. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +15 -0
  232. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +11 -0
  233. package/src/features/chat/features/workspace/utils/workspace-file-panel-route.utils.ts +147 -0
  234. package/src/features/chat/index.ts +20 -4
  235. package/src/features/chat/managers/__tests__/chat-completion-notification.manager.test.ts +8 -0
  236. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +7 -2
  237. package/src/features/chat/managers/__tests__/session-surface.manager.test.ts +45 -0
  238. package/src/features/chat/managers/chat-completion-notification.manager.ts +5 -0
  239. package/src/features/chat/managers/chat-composer-intent.manager.ts +16 -0
  240. package/src/features/chat/managers/chat-thread.manager.ts +18 -27
  241. package/src/features/chat/managers/session-surface.manager.ts +46 -0
  242. package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +23 -5
  243. package/src/features/chat/pages/ncp-chat-page.tsx +6 -86
  244. package/src/features/chat/presenters/chat.presenter.ts +2 -1
  245. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +2 -2
  246. package/src/features/chat/stores/chat-thread.store.ts +7 -1
  247. package/src/features/chat/stores/floating-session.store.ts +11 -0
  248. package/src/features/cron/components/__tests__/cron-config.test.tsx +4 -0
  249. package/src/features/cron/components/cron-job-detail-dialog.tsx +3 -1
  250. package/src/features/cron/components/cron-job-row.tsx +5 -1
  251. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +3 -0
  252. package/src/features/inbox/components/inbox-reader-dialog.tsx +3 -0
  253. package/src/features/inbox/pages/inbox-page.test.ts +3 -0
  254. package/src/features/inbox/pages/inbox-page.tsx +3 -0
  255. package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +5 -1
  256. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +3 -0
  257. package/src/features/marketplace/components/curated-shelves/__tests__/marketplace-curated-scene-route.test.tsx +2 -0
  258. package/src/features/marketplace/components/marketplace-list-card.tsx +4 -0
  259. package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
  260. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +3 -0
  261. package/src/features/notifications/components/__tests__/app-notification-toast.test.tsx +19 -0
  262. package/src/features/notifications/components/app-notification-toast.tsx +33 -15
  263. package/src/features/notifications/managers/app-notification.manager.ts +2 -0
  264. package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +11 -4
  265. package/src/features/panel-apps/components/__tests__/panel-app-toolbar.test.tsx +11 -5
  266. package/src/features/panel-apps/components/panel-app-main-sidebar-menu-item.tsx +5 -38
  267. package/src/features/panel-apps/index.ts +1 -1
  268. package/src/features/projects/components/project-materials.test.tsx +2 -0
  269. package/src/features/projects/components/project-skills.tsx +7 -3
  270. package/src/features/projects/components/work/project-work-item-drawer.test.tsx +2 -0
  271. package/src/features/projects/components/work/project-work-item-drawer.tsx +3 -1
  272. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +67 -0
  273. package/src/features/right-panel-resources/components/__tests__/page-resource-sidebar-nav.test.tsx +158 -0
  274. package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +42 -0
  275. package/src/features/right-panel-resources/components/current-page-actions.tsx +36 -0
  276. package/src/features/right-panel-resources/components/page-resource-actions-menu.tsx +71 -0
  277. package/src/features/right-panel-resources/components/page-resource-icon.tsx +245 -0
  278. package/src/features/right-panel-resources/components/page-resource-sidebar-nav.tsx +122 -0
  279. package/src/features/right-panel-resources/components/system-object-resource.tsx +100 -0
  280. package/src/features/right-panel-resources/components/workspace-file-resource.tsx +56 -0
  281. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +46 -3
  282. package/src/features/right-panel-resources/hooks/use-page-resource-actions.ts +137 -0
  283. package/src/features/right-panel-resources/index.ts +22 -8
  284. package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +149 -0
  285. package/src/features/right-panel-resources/managers/page-resource.manager.ts +342 -0
  286. package/src/features/right-panel-resources/pages/resource-page.tsx +114 -0
  287. package/src/features/right-panel-resources/stores/page-navigation.store.ts +55 -0
  288. package/src/features/right-panel-resources/types/page-resource.types.ts +11 -0
  289. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +10 -0
  290. package/src/features/right-panel-resources/utils/page-resource-identity.utils.ts +61 -0
  291. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +2 -6
  292. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +2 -0
  293. package/src/features/service-apps/components/service-app-list-item.tsx +5 -1
  294. package/src/features/settings/pages/providers-config-page.tsx +2 -2
  295. package/src/features/side-dock/components/__tests__/side-dock.test.tsx +9 -8
  296. package/src/features/side-dock/components/side-dock.tsx +14 -47
  297. package/src/features/side-dock/managers/side-dock.manager.ts +2 -0
  298. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +3 -0
  299. package/src/platforms/desktop/components/desktop-app-shell.tsx +5 -14
  300. package/src/platforms/mobile/components/__tests__/mobile-app-shell.test.tsx +1 -0
  301. package/src/platforms/mobile/components/__tests__/mobile-bottom-nav.test.tsx +3 -2
  302. package/src/platforms/mobile/components/mobile-app-shell.tsx +5 -4
  303. package/src/platforms/mobile/components/mobile-bottom-nav.tsx +7 -7
  304. package/src/platforms/mobile/components/mobile-topbar.tsx +4 -4
  305. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +4 -3
  306. package/src/shared/components/doc-browser/__tests__/doc-browser-tab-strip.test.tsx +0 -5
  307. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +57 -73
  308. package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +104 -0
  309. package/src/shared/components/doc-browser/doc-browser-context.tsx +5 -1
  310. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +1 -1
  311. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +6 -118
  312. package/src/shared/components/doc-browser/doc-browser.tsx +30 -194
  313. package/src/shared/components/doc-browser/hooks/use-doc-browser-scroll-restoration.ts +1 -1
  314. package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +11 -1
  315. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +3 -7
  316. package/src/shared/components/doc-browser/types/doc-browser.types.ts +8 -1
  317. package/src/shared/components/doc-browser/use-doc-link-interceptor.ts +30 -32
  318. package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +6 -6
  319. package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +22 -0
  320. package/src/shared/components/ui/context-menu/context-menu.tsx +18 -10
  321. package/src/shared/components/workbench/__tests__/workbench-surface.manager.test.ts +70 -0
  322. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +111 -0
  323. package/src/shared/components/workbench/managers/workbench-surface.manager.ts +120 -0
  324. package/src/shared/components/workbench/stores/workbench-surface.store.ts +83 -0
  325. package/src/shared/components/workbench/types/workbench-surface.types.ts +32 -0
  326. package/src/shared/components/workbench/utils/workbench-surface-geometry.utils.ts +46 -0
  327. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +102 -0
  328. package/src/shared/components/workbench/workbench-surface.tsx +401 -0
  329. package/src/shared/hooks/use-panel-app-scroll-restoration.test.tsx +19 -0
  330. package/src/shared/hooks/use-panel-app-scroll-restoration.ts +8 -6
  331. package/src/shared/hooks/use-scroll-restoration.test.tsx +39 -2
  332. package/src/shared/hooks/use-scroll-restoration.ts +33 -33
  333. package/src/shared/lib/api/marketplace.types.ts +1 -0
  334. package/src/shared/lib/i18n/locales/en-US/chat.json +38 -0
  335. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -1
  336. package/src/shared/lib/i18n/locales/zh-CN/chat.json +38 -0
  337. package/src/shared/lib/navigation-history/index.ts +1 -0
  338. package/src/shared/lib/navigation-history/navigation-history.utils.ts +1 -1
  339. package/src/shared/lib/navigation-history/scroll-restoration.manager.test.ts +11 -0
  340. package/src/shared/lib/navigation-history/scroll-restoration.manager.ts +36 -7
  341. package/src/shared/lib/navigation-history/view-memory-storage.store.test.ts +37 -0
  342. package/src/shared/lib/navigation-history/view-memory-storage.store.ts +21 -0
  343. package/src/shared/lib/ui-document-title/index.ts +1 -0
  344. package/dist/assets/account-panel-BW4GbzQd.js +0 -1
  345. package/dist/assets/api-DqzQ-_3w.js +0 -13
  346. package/dist/assets/app-data-C54N2p8b.js +0 -1
  347. package/dist/assets/app-presenter-provider-CBZ_-ewx.js +0 -115
  348. package/dist/assets/appearance-settings-page-C-uZ2Wkf.js +0 -1
  349. package/dist/assets/architecture-TIHT7OUA-DEt0Abz9.js +0 -1
  350. package/dist/assets/boxes-D6uPnkGo.js +0 -1
  351. package/dist/assets/card-BhfAZv5L.js +0 -1
  352. package/dist/assets/channel-CxQkbwRD.js +0 -1
  353. package/dist/assets/channels-list-page-Bv7CVSqV.js +0 -8
  354. package/dist/assets/chevron-down-BL-yMYcX.js +0 -1
  355. package/dist/assets/chunk-2Q5K7J3B-ClVhziok.js +0 -1
  356. package/dist/assets/chunk-VAUOI2AC-DZQxkIsv.js +0 -1
  357. package/dist/assets/chunk-XXDRQBXY-BkExtw5C.js +0 -1
  358. package/dist/assets/circle-alert-lSa3LRvS.js +0 -1
  359. package/dist/assets/classDiagram-OUVF2IWQ-Bd6apBb-.js +0 -1
  360. package/dist/assets/classDiagram-v2-EOCWNBFH-CYxUZGCI.js +0 -1
  361. package/dist/assets/client-BtGBwLTs.js +0 -1
  362. package/dist/assets/config-split-page-DqAXKLmG.js +0 -1
  363. package/dist/assets/confirm-dialog-BTKCWMn6.js +0 -1
  364. package/dist/assets/createLucideIcon-BNKf0_kc.js +0 -1
  365. package/dist/assets/cynefin-VYW2F7L2-CV0bFLH9.js +0 -1
  366. package/dist/assets/desktop-capabilities-page-zLzCSB7A.js +0 -1
  367. package/dist/assets/desktop-update-config-PmofcFf6.js +0 -1
  368. package/dist/assets/dialog-Xe73hpQz.js +0 -5
  369. package/dist/assets/dist-BiIcnf9j.js +0 -1
  370. package/dist/assets/dist-C5I0v8Qn.js +0 -1
  371. package/dist/assets/dist-czPa8xFO.js +0 -1
  372. package/dist/assets/doc-browser-BJrre2S_.js +0 -1
  373. package/dist/assets/doc-browser-BPqA-zQx.js +0 -1
  374. package/dist/assets/doc-browser-context-TILuCY5c.js +0 -1
  375. package/dist/assets/ellipsis-C5YXdOUx.js +0 -1
  376. package/dist/assets/es2015-cuwbYI-l.js +0 -41
  377. package/dist/assets/eventmodeling-45OFAUF4-BzkLWWdP.js +0 -1
  378. package/dist/assets/extensions-CVUFK6Jj.js +0 -1
  379. package/dist/assets/flowDiagram-23GEKE2U-ukkCsB0j.js +0 -1
  380. package/dist/assets/form-actions-BRESe-m_.js +0 -1
  381. package/dist/assets/gitGraph-TEB2WS4Q-BYFhT0Q5.js +0 -1
  382. package/dist/assets/i18n-provider-BPRq6S7O.js +0 -1
  383. package/dist/assets/info-DKCQHKI2-CTmlJdcH.js +0 -1
  384. package/dist/assets/katex-DbZC06Q5.js +0 -1
  385. package/dist/assets/keyboard-shortcuts-settings-page-CScSXYS4.js +0 -1
  386. package/dist/assets/loader-circle-K1BDdHR5.js +0 -1
  387. package/dist/assets/login-page-Dlyvp-81.js +0 -1
  388. package/dist/assets/login-page-f8qQ4xKY.js +0 -1
  389. package/dist/assets/logo-badge-C-5-zim6.js +0 -1
  390. package/dist/assets/main-D2dWy8fM.css +0 -1
  391. package/dist/assets/main-DMNmwcJE.js +0 -2
  392. package/dist/assets/main-i18n-catalog.config-DZ-5ollN.js +0 -1
  393. package/dist/assets/mcp-marketplace-page-FfIfEo6w.js +0 -10
  394. package/dist/assets/mcp-marketplace-page-sH7VptN_.js +0 -1
  395. package/dist/assets/model-config-page-Bcm6-pCX.js +0 -1
  396. package/dist/assets/navigation-link-BAQjgx2F.js +0 -3
  397. package/dist/assets/packet-7NZHBO7P-BbrI0ZlN.js +0 -1
  398. package/dist/assets/panel-app-i18n-catalog.config-p3qAY_Eq.js +0 -1
  399. package/dist/assets/panelStandalone-By-6dDXS.js +0 -2
  400. package/dist/assets/pie-RZYD4A2V-B7zE1ZIr.js +0 -1
  401. package/dist/assets/plus-LA8-jpxP.js +0 -1
  402. package/dist/assets/popover-NkrFlWHp.js +0 -1
  403. package/dist/assets/privacy-settings-page-B1sHLAc1.js +0 -1
  404. package/dist/assets/projects-Voql-cvx.js +0 -1
  405. package/dist/assets/provider-models-hrHMcHqg.js +0 -1
  406. package/dist/assets/provider-scoped-model-input-BQsugx1v.js +0 -1
  407. package/dist/assets/providers-config-page-BDEdHJbw.js +0 -1
  408. package/dist/assets/pwa-CzqfYjFx.js +0 -1
  409. package/dist/assets/radar-I7S5WNFK-1X_q11Ed.js +0 -1
  410. package/dist/assets/railroad-3IZDKUUU-CIXnuFyE.js +0 -1
  411. package/dist/assets/railroad-abnf-AHOZXSZD-D6ImKl2r.js +0 -1
  412. package/dist/assets/railroad-ebnf-EBAXGLYW-2j9d3twU.js +0 -1
  413. package/dist/assets/railroad-peg-LSFZ7HO6-DMVaJGbm.js +0 -1
  414. package/dist/assets/remote-BekqL5nA.js +0 -1
  415. package/dist/assets/runtime-config-page-BH9uF4u_.js +0 -1
  416. package/dist/assets/search-CUe41wjm.js +0 -1
  417. package/dist/assets/search-config-page-DWKlMHgH.js +0 -1
  418. package/dist/assets/secrets-config-page-DiQL088Y.js +0 -3
  419. package/dist/assets/security-config-DmTDKKY4.js +0 -1
  420. package/dist/assets/select-CG5YWnwe.js +0 -1
  421. package/dist/assets/service-apps-panel-CEnyYsQp.js +0 -1
  422. package/dist/assets/skeleton-Drvn83YW.js +0 -1
  423. package/dist/assets/stateDiagram-v2-6OUMAXLB-OlIMT57r.js +0 -1
  424. package/dist/assets/swimlanesDiagram-G3AALYLV-sLThrh07.js +0 -8
  425. package/dist/assets/tabs-BuE0qKMh.js +0 -1
  426. package/dist/assets/tag-chip-B1AYPOKL.js +0 -1
  427. package/dist/assets/theme-provider-DzvAi3pe.js +0 -1
  428. package/dist/assets/tooltip-DYcuWhuP.js +0 -1
  429. package/dist/assets/trash-2-BPPYt2NV.js +0 -1
  430. package/dist/assets/treeView-QDETBFTQ-CCFyazDE.js +0 -1
  431. package/dist/assets/treemap-6X3UGDF4-D6wvq1Hz.js +0 -1
  432. package/dist/assets/use-config-BEdbtpD4.js +0 -1
  433. package/dist/assets/use-panel-app-scroll-restoration-ZnicIfo3.js +0 -1
  434. package/dist/assets/use-viewport-layout-BS18drMT.js +0 -1
  435. package/dist/assets/utils-CBZPzC_b.js +0 -8
  436. package/dist/assets/wardley-OPB4EBWU-BRzaRyFf.js +0 -1
  437. package/dist/assets/x-DdXOqLnX.js +0 -1
  438. package/src/features/panel-apps/components/__tests__/panel-app-main-sidebar-nav.test.tsx +0 -219
  439. package/src/features/panel-apps/components/panel-app-main-sidebar-nav.tsx +0 -258
  440. package/src/shared/components/doc-browser/utils/doc-browser-floating-panel.utils.ts +0 -83
  441. /package/dist/assets/{array-D0DyKZdT.js → array-B0sEvCP9.js} +0 -0
  442. /package/dist/assets/{chunk-KEIR6QF5-CuZFOa6q.js → chunk-KEIR6QF5-BeO7fxDQ.js} +0 -0
  443. /package/dist/assets/{chunk-Y2CYZVJY-Frut-1TF.js → chunk-Y2CYZVJY-JQfgEV36.js} +0 -0
  444. /package/dist/assets/{config-hints-B_C9DAp5.js → config-hints-D3OuwoEY.js} +0 -0
  445. /package/dist/assets/{cytoscape.esm-BibuhnZD.js → cytoscape.esm-CzJ9uXgi.js} +0 -0
  446. /package/dist/assets/{defaultLocale-q7sRUXPc.js → defaultLocale-USmzX3VG.js} +0 -0
  447. /package/dist/assets/{dist-DhMddrrH.js → dist-BYF6XVna.js} +0 -0
  448. /package/dist/assets/{graphlib-BM63WsW3.js → graphlib-DEFMkHdW.js} +0 -0
  449. /package/dist/assets/{host-capabilities-B107nwS3.js → host-capabilities-C0MmWd3M.js} +0 -0
  450. /package/dist/assets/{init-CRMkf9sL.js → init-04ErALoz.js} +0 -0
  451. /package/dist/assets/{jszip.min-6thm2J_a.js → jszip.min-BnQ5NRy2.js} +0 -0
  452. /package/dist/assets/{katex-B26hhTOT.js → katex-CsAM73R9.js} +0 -0
  453. /package/dist/assets/{middleware-0o3JF3tS.js → middleware-CAXxl-af.js} +0 -0
  454. /package/dist/assets/{panel-app-B39rJPj8.js → panel-app-2EACRB8p.js} +0 -0
  455. /package/dist/assets/{path-BFMmafCM.js → path-CzxQ9n2G.js} +0 -0
  456. /package/dist/assets/{rough.esm-5Tjchx1D.js → rough.esm-pT9fdsW3.js} +0 -0
  457. /package/dist/assets/{xlsx-BC8ibjXK.js → xlsx-BRpCSiE4.js} +0 -0
@@ -0,0 +1,62 @@
1
+ import { useWorkbenchSurfaceStore } from '@/shared/components/workbench/stores/workbench-surface.store';
2
+ import { GLOBAL_WORKBENCH_SURFACE, SESSION_WORKBENCH_SURFACE } from '@/shared/components/workbench/types/workbench-surface.types';
3
+ import { useEffect, useMemo, type ReactNode } from 'react';
4
+ import { useLocation, useMatch, useNavigate } from 'react-router-dom';
5
+ import { useAppPresenter } from '@/app/components/app-presenter-provider';
6
+ import { ChatPresenter } from '@/features/chat/presenters/chat.presenter';
7
+ import { ChatPresenterProvider, usePresenter } from './chat-presenter.provider';
8
+ import { useConfirmDialog } from '@/shared/hooks/use-confirm-dialog';
9
+ import { useChatQueryStoreSync } from '@/features/chat/features/ncp/hooks/use-ncp-chat-query-store-sync';
10
+ import { parseSessionKeyFromRoute } from '@/features/chat/features/session/utils/chat-session-route.utils';
11
+ import { useChatThreadStore } from '@/features/chat/stores/chat-thread.store';
12
+ import { useFloatingSessionStore } from '@/features/chat/stores/floating-session.store';
13
+ import { FloatingSessionConversation } from '@/features/chat/features/conversation/components/floating-session-conversation';
14
+ import { useDocBrowserStore } from '@/shared/components/doc-browser/stores/doc-browser.store';
15
+ import { CHAT_SESSION_PANEL_KIND, parseSessionKeyFromPanelUrl } from '@/features/chat/features/session/utils/chat-session-route.utils';
16
+
17
+ function ChatRuntime({ children }: { children: ReactNode }) {
18
+ const presenter = usePresenter();
19
+ const appPresenter = useAppPresenter();
20
+ const location = useLocation();
21
+ const navigate = useNavigate();
22
+ const { confirm, ConfirmDialog } = useConfirmDialog();
23
+ const match = useMatch('/chat/:sessionId');
24
+ const sessionKey = parseSessionKeyFromRoute(match?.params.sessionId);
25
+ const workspaceMinimized = useWorkbenchSurfaceStore((state) => state.surfaces[`session-workspace:${sessionKey ?? 'draft'}`]?.minimized ?? false);
26
+ const workspaceSessionKey = useChatThreadStore(({ snapshot }) =>
27
+ snapshot.workspacePanelParentKey === sessionKey && sessionKey && !snapshot.workspacePanelHidden && !workspaceMinimized &&
28
+ snapshot.activeWorkspacePanelKind === 'child-session'
29
+ ? snapshot.activeChildSessionKey : null,
30
+ );
31
+ const floatingMinimized = useWorkbenchSurfaceStore((state) => state.surfaces[SESSION_WORKBENCH_SURFACE]?.minimized ?? false);
32
+ const panelMinimized = useWorkbenchSurfaceStore((state) => state.surfaces[GLOBAL_WORKBENCH_SURFACE]?.minimized ?? false);
33
+ const floatingSessionKey = useFloatingSessionStore((state) => floatingMinimized ? null : state.session?.sessionKey);
34
+ const panelSessionKey = useDocBrowserStore(({ snapshot }) => {
35
+ const tab = snapshot.tabs.find((item) => item.id === snapshot.activeTabId);
36
+ return snapshot.isOpen && !panelMinimized && tab?.kind === CHAT_SESSION_PANEL_KIND
37
+ ? parseSessionKeyFromPanelUrl(tab.currentUrl) : null;
38
+ });
39
+ useChatQueryStoreSync({ sessionKey });
40
+ useEffect(() => {
41
+ presenter.chatUiManager.syncState({ pathname: location.pathname });
42
+ presenter.chatUiManager.bindActions({ navigate, confirm });
43
+ }, [confirm, location.pathname, navigate, presenter]);
44
+ useEffect(() => {
45
+ appPresenter.chatCompletionNotificationManager.syncVisibleSessions([
46
+ sessionKey, workspaceSessionKey, floatingSessionKey, panelSessionKey,
47
+ ]);
48
+ return () => appPresenter.chatCompletionNotificationManager.syncVisibleSessions([]);
49
+ }, [appPresenter, sessionKey, workspaceSessionKey, floatingSessionKey, panelSessionKey]);
50
+
51
+ return <>{children}<FloatingSessionConversation /><ConfirmDialog /></>;
52
+ }
53
+
54
+ export function ChatRuntimeProvider({ children }: { children: ReactNode }) {
55
+ const appPresenter = useAppPresenter();
56
+ const presenter = useMemo(() => new ChatPresenter(appPresenter), [appPresenter]);
57
+ return (
58
+ <ChatPresenterProvider presenter={presenter}>
59
+ <ChatRuntime>{children}</ChatRuntime>
60
+ </ChatPresenterProvider>
61
+ );
62
+ }
@@ -0,0 +1,70 @@
1
+ import { AppPresenterProvider } from '@/app/components/app-presenter-provider';
2
+ import type { ReactElement } from 'react';
3
+
4
+ vi.mock('@/features/panel-apps/hooks/use-panel-apps', () => ({
5
+ usePanelApps: () => ({ data: { entries: [] } }),
6
+ useUpdatePanelAppPreferences: () => ({ mutate: vi.fn(), isPending: false }),
7
+ }));
8
+ function render(ui: ReactElement) {
9
+ return renderUi(<AppPresenterProvider>{ui}</AppPresenterProvider>);
10
+ }
11
+ import { sessionSurfaceManager } from '@/features/chat/managers/session-surface.manager';
12
+ import { act, render as renderUi, screen } from '@testing-library/react';
13
+ import userEvent from '@testing-library/user-event';
14
+ import { MemoryRouter, useLocation } from 'react-router-dom';
15
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
16
+ import { FloatingSessionConversation } from '@/features/chat/features/conversation/components/floating-session-conversation';
17
+ import { buildSessionPath } from '@/features/chat/features/session/utils/chat-session-route.utils';
18
+
19
+ vi.mock('@/features/chat/features/conversation/components/session-conversation-area', () => ({
20
+ SessionConversationArea: ({ sessionKey }: { sessionKey: string }) =>
21
+ <textarea aria-label={sessionKey} />,
22
+ }));
23
+
24
+ function MainConversation() {
25
+ return <><textarea aria-label="main" /><span data-testid="path">{useLocation().pathname}</span></>;
26
+ }
27
+
28
+ describe('Floating conversation shell', () => {
29
+ beforeEach(() => sessionSurfaceManager.close());
30
+
31
+ it('preserves the main editor and floating editor identity through minimize and restore', async () => {
32
+ const user = userEvent.setup();
33
+ render(<MemoryRouter initialEntries={['/chat/current']}>
34
+ <MainConversation /><FloatingSessionConversation />
35
+ </MemoryRouter>);
36
+ const main = screen.getByRole('textbox', { name: 'main' });
37
+ await user.type(main, 'main draft');
38
+ act(() => sessionSurfaceManager.open({ sessionKey: 'other', title: 'Other task' }));
39
+ expect(document.activeElement).toBe(screen.getByTestId('floating-session-conversation'));
40
+ const floating = screen.getByRole('textbox', { name: 'other' });
41
+ await user.type(floating, 'follow-up');
42
+ await user.keyboard('{Escape}');
43
+ expect(screen.queryByRole('textbox', { name: 'other' })).toBeNull();
44
+ await user.click(screen.getByRole('button', { name: 'Expand view' }));
45
+ expect(screen.getByRole('textbox', { name: 'other' })).toBe(floating);
46
+ expect((floating as HTMLTextAreaElement).value).toBe('follow-up');
47
+ expect(screen.getByRole('textbox', { name: 'main' })).toBe(main);
48
+ expect((main as HTMLTextAreaElement).value).toBe('main draft');
49
+ expect(screen.getByTestId('path').textContent).toBe('/chat/current');
50
+ await user.click(screen.getByRole('button', { name: 'Close view' }));
51
+ expect(floating.isConnected).toBe(false);
52
+ expect(main.isConnected).toBe(true);
53
+ });
54
+
55
+ it('switches only the floating target and navigates only on explicit main-view action', async () => {
56
+ const user = userEvent.setup();
57
+ render(<MemoryRouter initialEntries={['/settings']}>
58
+ <MainConversation /><FloatingSessionConversation />
59
+ </MemoryRouter>);
60
+ act(() => sessionSurfaceManager.open({ sessionKey: 'one', title: 'One' }));
61
+ const previous = screen.getByRole('textbox', { name: 'one' });
62
+ act(() => sessionSurfaceManager.open({ sessionKey: 'two', title: 'Two' }));
63
+ expect(previous.isConnected).toBe(false);
64
+ expect(screen.getByRole('textbox', { name: 'two' })).toBeTruthy();
65
+ expect(screen.getByTestId('path').textContent).toBe('/settings');
66
+ await user.click(screen.getByRole('button', { name: 'Open in main area' }));
67
+ expect(screen.getByTestId('path').textContent).toBe(buildSessionPath('two'));
68
+ expect(screen.queryByTestId('floating-session-conversation')).toBeNull();
69
+ });
70
+ });
@@ -0,0 +1,27 @@
1
+ import { PageResourceActionsMenu } from '@/features/right-panel-resources';
2
+ import { pageResourceFromTarget } from '@/features/right-panel-resources';
3
+ import { buildSessionPanelUrl } from '@/features/chat/features/session/utils/chat-session-route.utils';
4
+ import { MessageSquare } from 'lucide-react';
5
+ import { useNavigate } from 'react-router-dom';
6
+ import { getAppPresenter } from '@/app/presenters/app.presenter';
7
+ import { sessionSurfaceManager } from '@/features/chat/managers/session-surface.manager';
8
+ import { useFloatingSessionStore } from '@/features/chat/stores/floating-session.store';
9
+ import { buildSessionPath } from '@/features/chat/features/session/utils/chat-session-route.utils';
10
+ import { WorkbenchSurface } from '@/shared/components/workbench/workbench-surface';
11
+ import { SESSION_WORKBENCH_SURFACE } from '@/shared/components/workbench/types/workbench-surface.types';
12
+ import { SessionConversationArea } from './session-conversation-area';
13
+
14
+ export function FloatingSessionConversation() {
15
+ const session = useFloatingSessionStore((state) => state.session);
16
+ const navigate = useNavigate();
17
+ const presenter = getAppPresenter();
18
+ if (!session) return null;
19
+ return <WorkbenchSurface id={SESSION_WORKBENCH_SURFACE} manager={presenter.workbenchSurfaceManager}
20
+ title={session.title} icon={<MessageSquare className="h-4 w-4 shrink-0" />} testId="floating-session-conversation" focusOnOpen
21
+ navigation={<div className="flex min-w-0 flex-1 items-center gap-2"><span className="min-w-0 flex-1 truncate text-xs">{session.title}</span><PageResourceActionsMenu page={pageResourceFromTarget({ kind: 'chat-session', title: session.title, url: buildSessionPanelUrl(session.sessionKey), resourceUri: buildSessionPanelUrl(session.sessionKey), historyPolicy: 'none' })} /></div>}
22
+ onClose={sessionSurfaceManager.close}
23
+ onPlace={() => sessionSurfaceManager.dock(session, presenter.docBrowserManager)}
24
+ onOpenMain={() => { navigate(buildSessionPath(session.sessionKey)); sessionSurfaceManager.close(); }}>
25
+ <SessionConversationArea key={session.sessionKey} sessionKey={session.sessionKey} />
26
+ </WorkbenchSurface>;
27
+ }
@@ -415,6 +415,7 @@ export function SessionConversationArea(props: SessionConversationAreaProps) {
415
415
  <>
416
416
  <SessionConversationAlerts inputQuery={inputQuery} />
417
417
  <ChatConversationContent
418
+ resourceWorkingDir={selectedSession?.workingDir ?? selectedSession?.projectRoot ?? null}
418
419
  hasPreviousMessages={agent.hasPreviousMessages}
419
420
  historyError={agent.historyError}
420
421
  isHistoryLoading={agent.isHydrating}
@@ -0,0 +1,25 @@
1
+ import { MessageSquare } from 'lucide-react';
2
+ import { CHAT_SESSION_PANEL_KIND, parseSessionKeyFromPanelUrl } from '@/features/chat/features/session/utils/chat-session-route.utils';
3
+ import { SessionConversationArea } from './session-conversation-area';
4
+ import type { DocBrowserCustomTabRenderers } from '@/shared/components/doc-browser/doc-browser-renderer.types';
5
+ import type { DocBrowserTab } from '@/shared/components/doc-browser/types/doc-browser.types';
6
+ import { t } from '@/shared/lib/i18n';
7
+
8
+ function SessionPanelContent({ tab }: { tab: DocBrowserTab }) {
9
+ const sessionKey = parseSessionKeyFromPanelUrl(tab.currentUrl);
10
+ return (
11
+ <div data-testid="session-conversation-panel-tab" className="flex h-full min-h-0 min-w-0 flex-col bg-background text-foreground">
12
+ {sessionKey
13
+ ? <SessionConversationArea key={sessionKey} sessionKey={sessionKey} />
14
+ : <p role="status" className="p-4 text-sm text-muted-foreground">{t('chatPanelUnavailable')}</p>}
15
+ </div>
16
+ );
17
+ }
18
+
19
+ export const CHAT_SESSION_PANEL_RENDERERS: DocBrowserCustomTabRenderers = {
20
+ [CHAT_SESSION_PANEL_KIND]: {
21
+ getTitle: (tab) => tab.title,
22
+ renderIcon: () => <MessageSquare className="h-4 w-4" />,
23
+ renderContent: ({ tab }) => <SessionPanelContent tab={tab} />,
24
+ },
25
+ };
@@ -3,6 +3,7 @@ import { type ChatInputBarHandle } from '@nextclaw/agent-chat-ui';
3
3
  import {
4
4
  CHAT_CONVERSATION_EXCERPT_TOKEN_KIND,
5
5
  CHAT_UI_RESOURCE_TOKEN_KIND,
6
+ CHAT_SYSTEM_OBJECT_TOKEN_KIND,
6
7
  CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
7
8
  } from '@nextclaw/shared';
8
9
 
@@ -42,7 +43,7 @@ export function useChatComposerReferenceIntent(params: {
42
43
  role: intent.role,
43
44
  excerpt: intent.excerpt,
44
45
  }
45
- : intent.kind === CHAT_UI_RESOURCE_TOKEN_KIND
46
+ : (intent.kind === CHAT_UI_RESOURCE_TOKEN_KIND || intent.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND)
46
47
  ? { reference: intent.reference }
47
48
  : undefined,
48
49
  });
@@ -32,7 +32,8 @@ vi.mock("@/app/presenters/app.presenter", () => ({
32
32
  }),
33
33
  }));
34
34
 
35
- vi.mock("@/features/panel-apps", () => ({
35
+ vi.mock("@/features/panel-apps", async (importOriginal) => ({
36
+ ...await importOriginal<object>(),
36
37
  PANEL_APP_IFRAME_SANDBOX:
37
38
  "allow-scripts allow-forms allow-modals allow-popups allow-popups-to-escape-sandbox allow-downloads allow-pointer-lock allow-presentation",
38
39
  findPanelAppEntryByDisplayId: (
@@ -147,3 +147,6 @@ it("keeps a new session's empty first assistant draft in the awaiting state", ()
147
147
  );
148
148
  expect(assistantDraftRender?.isSending).toBe(true);
149
149
  });
150
+
151
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn() }));
152
+ vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: vi.fn(), open: vi.fn() } }) }));
@@ -168,3 +168,6 @@ it("shows an error when a persisted v1 skill is no longer resolvable", async ()
168
168
  ));
169
169
  expect(captures.openFilePreview).not.toHaveBeenCalled();
170
170
  });
171
+
172
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn() }));
173
+ vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: vi.fn(), open: vi.fn() } }) }));
@@ -891,3 +891,6 @@ it("shows edit only while the latest user message is actually editable", () => {
891
891
  );
892
892
  expect(busyUserMessage).not.toHaveProperty("actions");
893
893
  });
894
+
895
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn() }));
896
+ vi.mock("@/app/components/app-presenter-provider", () => ({ useAppPresenter: () => ({ pageResourceManager: { resolve: vi.fn(), open: vi.fn() } }) }));
@@ -1,8 +1,10 @@
1
+ import { useNavigate } from 'react-router-dom';
1
2
  import { useCallback } from "react";
2
3
  import type { ChatInlineTokenViewModel } from "@nextclaw/agent-chat-ui";
3
4
  import {
4
5
  CHAT_PROJECT_TOKEN_KIND,
5
6
  CHAT_UI_RESOURCE_TOKEN_KIND,
7
+ CHAT_SYSTEM_OBJECT_TOKEN_KIND,
6
8
  CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
7
9
  } from "@nextclaw/shared";
8
10
  import { toast } from "sonner";
@@ -23,12 +25,14 @@ export function useChatInlineTokenActions(params: {
23
25
  }) {
24
26
  const { selectedSession, sessionKey } = params;
25
27
  const presenter = usePresenter();
28
+ const navigate = useNavigate();
26
29
  const appPresenter = useAppPresenter();
27
30
  const projectRoot = selectedSession?.projectRoot ?? selectedSession?.workingDir;
28
31
 
29
32
  const handleInlineTokenClick = useCallback((token: ChatInlineTokenViewModel) => {
30
- if (token.kind === CHAT_UI_RESOURCE_TOKEN_KIND && "key" in token) {
31
- appPresenter.docBrowserManager.open(token.key);
33
+ if ((token.kind === CHAT_UI_RESOURCE_TOKEN_KIND || token.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) && "key" in token) {
34
+ const page = appPresenter.pageResourceManager.resolve(token.key);
35
+ if (page) appPresenter.pageResourceManager.open(page, 'default', navigate);
32
36
  return;
33
37
  }
34
38
  if (token.kind === "panel_app" && "key" in token) {
@@ -105,7 +109,7 @@ export function useChatInlineTokenActions(params: {
105
109
  previewViewer: "rendered",
106
110
  });
107
111
  }).catch(() => toast.error(t("chatSkillPreviewUnavailable")));
108
- }, [appPresenter.docBrowserManager, presenter, projectRoot, selectedSession?.projectRoot, sessionKey]);
112
+ }, [appPresenter, navigate, presenter, projectRoot, selectedSession?.projectRoot, sessionKey]);
109
113
 
110
114
  const handleAttachmentOpen = useCallback((file: {
111
115
  label: string;
@@ -1,7 +1,9 @@
1
+ import { sessionSurfaceManager } from '@/features/chat/managers/session-surface.manager';
1
2
  import { render, screen, within } from "@testing-library/react";
2
3
  import userEvent from "@testing-library/user-event";
3
4
  import { beforeEach, expect, it, vi } from "vitest";
4
5
  import { ChatSidebarSessionItem } from "@/features/chat/features/session/components/chat-sidebar-session-item";
6
+ import { useFloatingSessionStore } from '@/features/chat/stores/floating-session.store';
5
7
 
6
8
  const mocks = vi.hoisted(() => ({
7
9
  copyText: vi.fn(),
@@ -20,6 +22,7 @@ vi.mock("sonner", () => ({
20
22
  }));
21
23
 
22
24
  beforeEach(() => {
25
+ sessionSurfaceManager.close();
23
26
  mocks.copyText.mockReset();
24
27
  mocks.copyText.mockResolvedValue(true);
25
28
  mocks.deleteSession.mockReset();
@@ -81,6 +84,15 @@ it("shows session actions only on hover or when an action owns focus", () => {
81
84
  expect(screen.getByRole("button", { name: "More actions" })).toBeTruthy();
82
85
  });
83
86
 
87
+ it("opens any sidebar session as a floating conversation", async () => {
88
+ const user = userEvent.setup();
89
+ await user.click(screen.getByRole('button', { name: 'More actions' }));
90
+ await user.click(screen.getByRole('button', { name: 'Open in floating window' }));
91
+ expect(useFloatingSessionStore.getState().session).toEqual({
92
+ sessionKey: 'session:current', title: 'Current Task',
93
+ });
94
+ });
95
+
84
96
  it("copies the sidebar session ID from the more-actions menu", async () => {
85
97
  const user = userEvent.setup();
86
98
 
@@ -121,3 +133,11 @@ it("shows session context from the row on hover", async () => {
121
133
  expect(within(tooltip).getByText("2")).toBeTruthy();
122
134
  expect(within(tooltip).getByText("3")).toBeTruthy();
123
135
  });
136
+
137
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn(), useLocation: () => ({ pathname: '/chat', search: '' }) }));
138
+ vi.mock("@/features/panel-apps/hooks/use-panel-apps", () => ({ usePanelApps: () => ({ data: { entries: [] } }), useUpdatePanelAppPreferences: () => ({ mutate: vi.fn() }) }));
139
+ vi.mock("@/app/components/app-presenter-provider", async () => {
140
+ const { PageResourceManager } = await import("@/features/right-panel-resources/managers/page-resource.manager");
141
+ const app = { docBrowserManager: { openTarget: vi.fn() }, chatComposerIntentManager: { requestUiResourceReference: vi.fn() } };
142
+ return { useAppPresenter: () => ({ ...app, pageResourceManager: new PageResourceManager(app as never) }) };
143
+ });
@@ -0,0 +1,61 @@
1
+ import { Pencil, Pin, Trash2 } from 'lucide-react';
2
+ import { AgentAvatar } from '@/shared/components/common/agent-avatar';
3
+ import { ChatSessionMoreActionsMenu } from '@/features/chat/features/session/components/session-header/chat-session-more-actions-menu';
4
+ import { ChatSessionHeaderMenuItem } from '@/features/chat/features/session/components/session-header/chat-session-header-menu-item';
5
+ import { SessionRunBadge } from './session-run-badge';
6
+ import type { ChatSidebarSessionItemProps } from './chat-sidebar-session-item';
7
+ import { t } from '@/shared/lib/i18n';
8
+ import { cn } from '@/shared/lib/utils';
9
+
10
+ const SESSION_AVATAR_COLORS = [
11
+ 'bg-blue-100 text-blue-800 [html[data-theme-appearance=dark]_&]:bg-blue-950 [html[data-theme-appearance=dark]_&]:text-blue-200',
12
+ 'bg-emerald-100 text-emerald-800 [html[data-theme-appearance=dark]_&]:bg-emerald-950 [html[data-theme-appearance=dark]_&]:text-emerald-200',
13
+ 'bg-violet-100 text-violet-800 [html[data-theme-appearance=dark]_&]:bg-violet-950 [html[data-theme-appearance=dark]_&]:text-violet-200',
14
+ 'bg-amber-100 text-amber-800 [html[data-theme-appearance=dark]_&]:bg-amber-950 [html[data-theme-appearance=dark]_&]:text-amber-200',
15
+ 'bg-rose-100 text-rose-800 [html[data-theme-appearance=dark]_&]:bg-rose-950 [html[data-theme-appearance=dark]_&]:text-rose-200',
16
+ ];
17
+
18
+ function sessionAvatarColor(sessionKey: string): string {
19
+ let hash = 0;
20
+ for (const character of sessionKey) hash = (hash * 31 + character.charCodeAt(0)) | 0;
21
+ return SESSION_AVATAR_COLORS[Math.abs(hash) % SESSION_AVATAR_COLORS.length];
22
+ }
23
+
24
+ /** Mobile presentation of the same session entry and actions used by the sidebar. */
25
+ export function ChatMobileSessionRow(props: ChatSidebarSessionItemProps) {
26
+ const { sessionKey, title, previewText, trailingText, agentId, agentLabel,
27
+ agentAvatarUrl, showUnreadDot, runStatus, isPinned, onSelect,
28
+ onStartEditing, onTogglePinned, onDelete } = props;
29
+ return (
30
+ <div className="relative flex min-w-0 items-center">
31
+ <button type="button" onClick={onSelect} className="flex min-h-[76px] min-w-0 flex-1 items-center gap-3 py-3 pl-4 pr-1 text-left active:bg-muted">
32
+ <span className="relative shrink-0">
33
+ {agentAvatarUrl || (agentId && agentId.toLowerCase() !== 'main') ? (
34
+ <AgentAvatar agentId={agentId || 'main'} displayName={agentLabel} avatarUrl={agentAvatarUrl} className="h-12 w-12 rounded-xl text-lg" />
35
+ ) : (
36
+ <span aria-hidden="true" className={cn('flex h-12 w-12 items-center justify-center rounded-xl text-base font-medium', sessionAvatarColor(sessionKey))}>
37
+ {Array.from(title.trim()).slice(0, 2).join('')}
38
+ </span>
39
+ )}
40
+ {showUnreadDot ? <span aria-label={t('chatSessionUnread')} className="absolute -right-1 -top-1 h-3 w-3 rounded-full border-2 border-background bg-primary" /> : null}
41
+ </span>
42
+ <span className="flex min-w-0 flex-1 flex-col gap-1">
43
+ <span className="flex min-w-0 items-center gap-2">
44
+ <span className="min-w-0 flex-1 truncate text-[16px] font-medium leading-6 text-foreground">{title}</span>
45
+ <span className="shrink-0 text-[11px] text-muted-foreground">{trailingText}</span>
46
+ </span>
47
+ <span className="flex min-w-0 items-center gap-1.5">
48
+ {runStatus ? <SessionRunBadge status={runStatus} /> : null}
49
+ {isPinned ? <Pin aria-label={t('chatSidebarUnpinSession')} className="h-3 w-3 shrink-0 text-muted-foreground" /> : null}
50
+ <span className="min-w-0 truncate text-[13px] leading-5 text-muted-foreground">{previewText}</span>
51
+ </span>
52
+ </span>
53
+ </button>
54
+ <ChatSessionMoreActionsMenu sessionKey={sessionKey} sessionTitle={title} className="h-11 w-9 shrink-0 rounded-none text-muted-foreground">
55
+ <ChatSessionHeaderMenuItem icon={Pin} label={t(isPinned ? 'chatSidebarUnpinSession' : 'chatSidebarPinSession')} onClick={onTogglePinned} />
56
+ <ChatSessionHeaderMenuItem icon={Pencil} label={t('edit')} onClick={onStartEditing} />
57
+ <ChatSessionHeaderMenuItem icon={Trash2} label={t('delete')} onClick={onDelete} destructive />
58
+ </ChatSessionMoreActionsMenu>
59
+ </div>
60
+ );
61
+ }
@@ -12,7 +12,6 @@ import {
12
12
  Plus,
13
13
  } from "lucide-react";
14
14
  import { usePresenter } from "@/features/chat/components/providers/chat-presenter.provider";
15
- import { ChatSessionTypeMenu } from "@/features/chat/features/session-type/components/chat-session-type-menu";
16
15
  import { Popover, PopoverTrigger } from "@/shared/components/ui/popover";
17
16
  import { ChatPopoverContent } from "@/features/chat/components/chat-popover-content";
18
17
  import { IconActionButton } from "@/shared/components/ui/actions/icon-action-button";
@@ -68,7 +67,6 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
68
67
  const collapsedProjectRoots = useChatSessionListStore(
69
68
  (state) => state.snapshot.collapsedProjectRoots,
70
69
  );
71
- const [openProjectRoot, setOpenProjectRoot] = useState<string | null>(null);
72
70
  const [openProjectMenuRoot, setOpenProjectMenuRoot] = useState<string | null>(
73
71
  null,
74
72
  );
@@ -80,7 +78,6 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
80
78
  ),
81
79
  [defaultSessionType, sessionTypeOptions],
82
80
  );
83
- const supportsSessionTypeChoice = sessionTypeOptions.length > 1;
84
81
  const removeProject = async (group: ChatSidebarProjectGroup) => {
85
82
  if (!group.projectId) return;
86
83
  setOpenProjectMenuRoot(null);
@@ -213,37 +210,6 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
213
210
  data-project-actions
214
211
  className="pointer-events-none absolute right-2 top-1/2 flex -translate-y-1/2 items-center opacity-0 transition-opacity group-hover/project:pointer-events-auto group-hover/project:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100"
215
212
  >
216
- {supportsSessionTypeChoice ? (
217
- <Popover
218
- open={openProjectRoot === group.projectRoot}
219
- onOpenChange={(nextOpen) => {
220
- setOpenProjectRoot(nextOpen ? group.projectRoot : null);
221
- }}
222
- >
223
- <PopoverTrigger asChild>
224
- <IconActionButton
225
- icon={<Plus className="h-3.5 w-3.5" />}
226
- label={actionLabel}
227
- />
228
- </PopoverTrigger>
229
- <ChatPopoverContent
230
- align="end"
231
- className="w-56 rounded-2xl border border-border bg-popover p-1.5 text-popover-foreground shadow-[0_24px_60px_-28px_rgba(15,23,42,0.38)]"
232
- >
233
- <ChatSessionTypeMenu
234
- options={sessionTypeOptions}
235
- selectedSessionType={preferredSessionType}
236
- onSelect={(sessionType) => {
237
- presenter.chatSessionListManager.createSession({
238
- projectRoot: group.projectRoot,
239
- sessionType,
240
- });
241
- setOpenProjectRoot(null);
242
- }}
243
- />
244
- </ChatPopoverContent>
245
- </Popover>
246
- ) : (
247
213
  <IconActionButton
248
214
  icon={<Plus className="h-3.5 w-3.5" />}
249
215
  label={actionLabel}
@@ -254,7 +220,6 @@ export function ChatSidebarProjectGroups(props: ChatSidebarProjectGroupsProps) {
254
220
  })
255
221
  }
256
222
  />
257
- )}
258
223
  <IconActionButton
259
224
  icon={
260
225
  <Pin
@@ -11,6 +11,7 @@ import type { ChatSessionTypeOption } from "@/features/chat/features/session-typ
11
11
  import { t } from "@/shared/lib/i18n";
12
12
 
13
13
  export function ChatSidebarSessionEntry(props: {
14
+ variant?: 'desktop' | 'mobile';
14
15
  item: NcpSessionListItemView;
15
16
  selectedSessionKey: string | null;
16
17
  optimisticReadAtBySessionKey: Record<string, string>;
@@ -74,6 +75,7 @@ export function ChatSidebarSessionEntry(props: {
74
75
 
75
76
  return (
76
77
  <ChatSidebarSessionItem
78
+ variant={props.variant}
77
79
  sessionKey={session.key}
78
80
  active={active}
79
81
  showUnreadDot={shouldShowUnreadSessionIndicator({
@@ -1,4 +1,5 @@
1
1
  import { AgentAvatar } from "@/shared/components/common/agent-avatar";
2
+ import { ChatMobileSessionRow } from './chat-mobile-session-row';
2
3
  import { SessionContextIconNode } from "@/features/chat/features/session/components/session-context-icon";
3
4
  import { SessionRunBadge } from "@/features/chat/features/session/components/session-run-badge";
4
5
  import { ChatSessionMoreActionsMenu } from "@/features/chat/features/session/components/session-header/chat-session-more-actions-menu";
@@ -21,7 +22,8 @@ import {
21
22
  import { ChatSidebarContextCard } from "@/features/chat/features/session/components/chat-sidebar-context-card";
22
23
  import { ChatSessionHeaderMenuItem } from "@/features/chat/features/session/components/session-header/chat-session-header-menu-item";
23
24
 
24
- type ChatSidebarSessionItemProps = {
25
+ export type ChatSidebarSessionItemProps = {
26
+ variant?: 'desktop' | 'mobile';
25
27
  sessionKey: string;
26
28
  active: boolean;
27
29
  showUnreadDot: boolean;
@@ -264,6 +266,7 @@ function ChatSidebarSessionDisplayView({
264
266
  />
265
267
  <ChatSessionMoreActionsMenu
266
268
  sessionKey={sessionKey}
269
+ sessionTitle={title}
267
270
  triggerSize="sm"
268
271
  triggerTone="strong"
269
272
  >
@@ -279,7 +282,8 @@ function ChatSidebarSessionDisplayView({
279
282
  );
280
283
  }
281
284
 
282
- export function ChatSidebarSessionItem({
285
+ export function ChatSidebarSessionItem(props: ChatSidebarSessionItemProps) {
286
+ const {
283
287
  sessionKey,
284
288
  active,
285
289
  showUnreadDot,
@@ -305,17 +309,20 @@ export function ChatSidebarSessionItem({
305
309
  onCancel,
306
310
  onTogglePinned,
307
311
  onDelete,
308
- }: ChatSidebarSessionItemProps) {
312
+ } = props;
309
313
  return (
310
314
  <div
311
315
  className={cn(
312
- "w-full rounded-lg px-2.5 py-2 text-left text-[13px] transition-colors",
316
+ props.variant === 'mobile'
317
+ ? 'w-full border-b border-border/50 bg-background text-left'
318
+ : "w-full rounded-lg px-2.5 py-2 text-left text-[13px] transition-colors",
313
319
  active
314
320
  ? "bg-background/90 font-medium text-foreground"
315
321
  : "text-foreground/80 hover:bg-background/65 hover:text-foreground",
316
322
  )}
317
323
  >
318
324
  {isEditing ? (
325
+ <div className={props.variant === 'mobile' ? 'p-4' : undefined}>
319
326
  <ChatSidebarSessionEditingView
320
327
  sessionKey={sessionKey}
321
328
  draftLabel={draftLabel}
@@ -324,7 +331,8 @@ export function ChatSidebarSessionItem({
324
331
  onSave={onSave}
325
332
  onCancel={onCancel}
326
333
  />
327
- ) : (
334
+ </div>
335
+ ) : props.variant === 'mobile' ? <ChatMobileSessionRow {...props} /> : (
328
336
  <ChatSidebarSessionDisplayView
329
337
  sessionKey={sessionKey}
330
338
  active={active}
@@ -12,6 +12,7 @@ import { t } from "@/shared/lib/i18n";
12
12
  type SessionTypeOption = ChatSessionTypeOption;
13
13
 
14
14
  type ChatSidebarSessionListProps = {
15
+ variant?: 'desktop' | 'mobile';
15
16
  isLoading: boolean;
16
17
  isProjectFirstView: boolean;
17
18
  groups: ChatSidebarDateGroup[];
@@ -32,6 +33,7 @@ function ChatSidebarEmptyState({ label }: { label: string }) {
32
33
  }
33
34
 
34
35
  export function ChatSidebarSessionList({
36
+ variant = 'desktop',
35
37
  defaultSessionType,
36
38
  groups,
37
39
  isLoading,
@@ -68,13 +70,13 @@ export function ChatSidebarSessionList({
68
70
  }
69
71
 
70
72
  return (
71
- <div className="space-y-2">
73
+ <div className={variant === 'mobile' ? undefined : 'space-y-2'}>
72
74
  {groups.map((group) => (
73
75
  <div key={group.label}>
74
- <div className="px-2 pb-1 pt-0.5 text-[11px] font-medium uppercase tracking-wider text-muted-foreground/65">
76
+ <div className={variant === 'mobile' ? 'px-4 py-1 text-[11px] text-muted-foreground' : 'px-2 pb-1 pt-0.5 text-[11px] font-medium uppercase tracking-wider text-muted-foreground/65'}>
75
77
  {group.label}
76
78
  </div>
77
- <div className="space-y-0.5">
79
+ <div className={variant === 'mobile' ? undefined : 'space-y-0.5'}>
78
80
  {group.items.map(renderSessionItem)}
79
81
  </div>
80
82
  </div>
@@ -237,3 +237,11 @@ describe('ChatSessionHeaderActions', () => {
237
237
  expect(mocks.onToggleWorkspace).toHaveBeenCalledTimes(1);
238
238
  });
239
239
  });
240
+
241
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn(), useLocation: () => ({ pathname: '/chat', search: '' }) }));
242
+ vi.mock("@/features/panel-apps/hooks/use-panel-apps", () => ({ usePanelApps: () => ({ data: { entries: [] } }), useUpdatePanelAppPreferences: () => ({ mutate: vi.fn() }) }));
243
+ vi.mock("@/app/components/app-presenter-provider", async () => {
244
+ const { PageResourceManager } = await import("@/features/right-panel-resources/managers/page-resource.manager");
245
+ const app = { docBrowserManager: { openTarget: vi.fn() }, chatComposerIntentManager: { requestUiResourceReference: vi.fn() } };
246
+ return { useAppPresenter: () => ({ ...app, pageResourceManager: new PageResourceManager(app as never) }) };
247
+ });
@@ -12,6 +12,7 @@ const SESSION_HEADER_ACTION_GROUP_CLASS = 'flex shrink-0 items-center gap-1.5';
12
12
 
13
13
  type ChatSessionHeaderActionsProps = {
14
14
  sessionKey: string | null;
15
+ sessionTitle?: string;
15
16
  canDeleteSession: boolean;
16
17
  isDeletePending: boolean;
17
18
  currentPath?: string | null;
@@ -24,6 +25,7 @@ type ChatSessionHeaderActionsProps = {
24
25
 
25
26
  export function ChatSessionHeaderActions({
26
27
  sessionKey,
28
+ sessionTitle,
27
29
  canDeleteSession,
28
30
  isDeletePending,
29
31
  currentPath,
@@ -62,6 +64,7 @@ export function ChatSessionHeaderActions({
62
64
  {sessionKey ? (
63
65
  <ChatSessionMoreActionsMenu
64
66
  sessionKey={sessionKey}
67
+ sessionTitle={sessionTitle}
65
68
  disabled={isBusy}
66
69
  >
67
70
  <ChatSessionHeaderMenuItem