@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
@@ -1,3 +1,6 @@
1
+ import { PageResourceActionItems } 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';
1
4
  import { useState, type ReactNode } from 'react';
2
5
  import { copyText } from '@nextclaw/agent-chat-ui';
3
6
  import { Copy, MoreVertical } from 'lucide-react';
@@ -14,6 +17,7 @@ import { ChatSessionHeaderMenuItem } from './chat-session-header-menu-item';
14
17
 
15
18
  type ChatSessionMoreActionsMenuProps = {
16
19
  sessionKey: string;
20
+ sessionTitle?: string;
17
21
  children?: ReactNode;
18
22
  disabled?: boolean;
19
23
  triggerSize?: IconActionButtonSize;
@@ -30,6 +34,7 @@ export async function copySessionId(sessionKey: string) {
30
34
 
31
35
  export function ChatSessionMoreActionsMenu({
32
36
  sessionKey,
37
+ sessionTitle,
33
38
  children,
34
39
  disabled = false,
35
40
  triggerSize = 'md',
@@ -59,6 +64,7 @@ export function ChatSessionMoreActionsMenu({
59
64
  </PopoverTrigger>
60
65
  <ChatPopoverContent align="end" className="w-56 p-2">
61
66
  <div className="space-y-1" onClick={() => setIsOpen(false)}>
67
+ <PageResourceActionItems page={pageResourceFromTarget({ kind: 'chat-session', title: sessionTitle || t('chatFloatingConversation'), url: buildSessionPanelUrl(sessionKey), resourceUri: buildSessionPanelUrl(sessionKey), historyPolicy: 'none' })} onSelect={() => setIsOpen(false)} />
62
68
  <ChatSessionHeaderMenuItem
63
69
  icon={Copy}
64
70
  label={t('chatSessionCopyId')}
@@ -1,4 +1,16 @@
1
1
  const SESSION_ROUTE_PREFIX = 'sid_';
2
+ export const CHAT_SESSION_PANEL_KIND = 'chat-session';
3
+ const SESSION_PANEL_PREFIX = 'nextclaw://chat-session/';
4
+
5
+ export function buildSessionPanelUrl(sessionKey: string): string {
6
+ return SESSION_PANEL_PREFIX + encodeSessionRouteId(sessionKey);
7
+ }
8
+
9
+ export function parseSessionKeyFromPanelUrl(url: string): string | null {
10
+ return url.startsWith(SESSION_PANEL_PREFIX)
11
+ ? decodeSessionRouteId(url.slice(SESSION_PANEL_PREFIX.length))
12
+ : null;
13
+ }
2
14
  export const CHAT_DRAFT_SESSION_PATH = '/chat/draft';
3
15
  const DRAFT_SESSION_ROUTE_ID = CHAT_DRAFT_SESSION_PATH.slice('/chat/'.length);
4
16
 
@@ -65,6 +65,26 @@ it('keeps existing child sessions selectable beside the create action', async ()
65
65
  expect(mocks.selectChildSessionDetail).toHaveBeenCalledWith('child-1');
66
66
  });
67
67
 
68
+ it('shows a spinner only for child sessions that are running', () => {
69
+ render(
70
+ <ChatSessionChildSessions
71
+ childSessionTabs={[
72
+ createChildSession(),
73
+ {
74
+ ...createChildSession(),
75
+ sessionKey: 'child-2',
76
+ title: 'Running branch',
77
+ runStatus: 'running',
78
+ },
79
+ ]}
80
+ sessionKey="parent-1"
81
+ />,
82
+ );
83
+
84
+ expect(screen.getAllByLabelText('Running')).toHaveLength(1);
85
+ expect(screen.getByRole('button', { name: /Running branch.*Running/ })).toBeTruthy();
86
+ });
87
+
68
88
  it('copies a child session ID from its own more-actions menu', async () => {
69
89
  const user = userEvent.setup();
70
90
  render(<ChatSessionChildSessions childSessionTabs={[createChildSession()]} sessionKey="parent-1" />);
@@ -75,3 +95,11 @@ it('copies a child session ID from its own more-actions menu', async () => {
75
95
  expect(mocks.copyText).toHaveBeenCalledWith('child-1');
76
96
  expect(mocks.selectChildSessionDetail).not.toHaveBeenCalled();
77
97
  });
98
+
99
+ vi.mock("react-router-dom", async (importOriginal) => ({ ...(await importOriginal<object>()), useNavigate: () => vi.fn(), useLocation: () => ({ pathname: '/chat', search: '' }) }));
100
+ vi.mock("@/features/panel-apps/hooks/use-panel-apps", () => ({ usePanelApps: () => ({ data: { entries: [] } }), useUpdatePanelAppPreferences: () => ({ mutate: vi.fn() }) }));
101
+ vi.mock("@/app/components/app-presenter-provider", async () => {
102
+ const { PageResourceManager } = await import("@/features/right-panel-resources/managers/page-resource.manager");
103
+ const app = { docBrowserManager: { openTarget: vi.fn() }, chatComposerIntentManager: { requestUiResourceReference: vi.fn() } };
104
+ return { useAppPresenter: () => ({ ...app, pageResourceManager: new PageResourceManager(app as never) }) };
105
+ });
@@ -534,6 +534,15 @@ describe("ChatSessionWorkspaceFilePreview Office rendering", () => {
534
534
  });
535
535
 
536
536
  describe("ChatSessionWorkspaceFilePreview text rendering", () => {
537
+ it("renders an immutable object snapshot without reading a same-named local file", () => {
538
+ serverPathReadMock.mockReturnValue({ data: null, isLoading: false });
539
+ serverPathBrowseMock.mockReturnValue({ data: null, isLoading: false });
540
+ renderWorkspaceFilePreview({ file: { path: "snapshot.md", rawText: "# Resource snapshot", previewViewer: "rendered" } });
541
+ expect(screen.getByTestId("markdown-preview").textContent).toBe("# Resource snapshot");
542
+ expect(serverPathReadMock).toHaveBeenCalledWith(expect.objectContaining({ enabled: false }));
543
+ expect(serverPathBrowseMock).toHaveBeenCalledWith(expect.objectContaining({ enabled: false }));
544
+ });
545
+
537
546
  it("renders preview files inside a full-height workspace code surface", () => {
538
547
  mockTextRead();
539
548
  renderWorkspaceFilePreview();
@@ -205,7 +205,9 @@ beforeEach(() => {
205
205
  });
206
206
  });
207
207
 
208
- function createChildTab(): ResolvedChildSessionTab {
208
+ function createChildTab(
209
+ overrides: Partial<ResolvedChildSessionTab> = {},
210
+ ): ResolvedChildSessionTab {
209
211
  return {
210
212
  sessionKey: 'child-1',
211
213
  parentSessionKey: 'parent-1',
@@ -219,6 +221,7 @@ function createChildTab(): ResolvedChildSessionTab {
219
221
  preferredModel: 'minimax/MiniMax-M3',
220
222
  projectName: 'nextbot',
221
223
  projectRoot: '/Users/peiwang/Projects/nextbot',
224
+ ...overrides,
222
225
  };
223
226
  }
224
227
 
@@ -252,7 +255,7 @@ it('shows child session content without a redundant metadata header', () => {
252
255
 
253
256
  it('shows all session workspace entries in the overview', async () => {
254
257
  const user = userEvent.setup();
255
- const childTab = createChildTab();
258
+ const childTab = createChildTab({ runStatus: 'running' });
256
259
 
257
260
  render(
258
261
  <ChatSessionWorkspacePanelContent
@@ -277,6 +280,7 @@ it('shows all session workspace entries in the overview', async () => {
277
280
  const projectFilesButton = screen.getByRole('button', { name: /Project files/ });
278
281
 
279
282
  expect((childSessionsButton as HTMLButtonElement).disabled).toBe(false);
283
+ expect(within(childSessionsButton).getByLabelText('Running')).toBeTruthy();
280
284
  expect((cronJobsButton as HTMLButtonElement).disabled).toBe(false);
281
285
  expect(projectFilesButton.compareDocumentPosition(screen.getByText('Token usage')) & Node.DOCUMENT_POSITION_FOLLOWING)
282
286
  .toBeTruthy();
@@ -1,4 +1,18 @@
1
- import { render, screen } from "@testing-library/react";
1
+ import { getPresenter } from '@/app/presenters/app.presenter';
2
+ import { buildSessionPath } from '@/features/chat/features/session/utils/chat-session-route.utils';
3
+ import { AppPresenterProvider } from '@/app/components/app-presenter-provider';
4
+ import type { ReactElement } from 'react';
5
+ import { MemoryRouter } from 'react-router-dom';
6
+
7
+ vi.mock('@/features/panel-apps/hooks/use-panel-apps', () => ({
8
+ usePanelApps: () => ({ data: { entries: [] } }),
9
+ useUpdatePanelAppPreferences: () => ({ mutate: vi.fn(), isPending: false }),
10
+ }));
11
+ function render(ui: ReactElement) {
12
+ return renderUi(<AppPresenterProvider><MemoryRouter initialEntries={[buildSessionPath('session-1')]}>{ui}</MemoryRouter></AppPresenterProvider>);
13
+ }
14
+ import { useWorkbenchSurfaceStore } from '@/shared/components/workbench/stores/workbench-surface.store';
15
+ import { render as renderUi, screen } from "@testing-library/react";
2
16
  import userEvent from "@testing-library/user-event";
3
17
  import { beforeEach, describe, expect, it, vi } from "vitest";
4
18
  import { ChatSessionWorkspacePanel } from "@/features/chat/features/workspace/components/chat-session-workspace-panel";
@@ -91,7 +105,9 @@ function renderPanel(displayMode: "docked" | "overlay" = "docked") {
91
105
 
92
106
  describe("ChatSessionWorkspacePanel", () => {
93
107
  beforeEach(() => {
108
+ useWorkbenchSurfaceStore.setState({ surfaces: {} });
94
109
  vi.clearAllMocks();
110
+ vi.spyOn(getPresenter().chatComposerIntentManager, 'requestFileReference').mockImplementation(mocks.requestFileReference);
95
111
  });
96
112
 
97
113
  it("refreshes the active workspace file from the top action bar", async () => {
@@ -130,23 +146,46 @@ describe("ChatSessionWorkspacePanel", () => {
130
146
  onSelect: vi.fn(),
131
147
  },
132
148
  ]}
133
- onClose={vi.fn()}
134
149
  onGoBack={vi.fn()}
135
150
  onGoForward={vi.fn()}
136
151
  />,
137
152
  );
138
153
 
139
- await user.click(screen.getByRole("button", { name: "More actions" }));
154
+ await user.click(screen.getByRole("button", { name: "Page actions: Child session" }));
140
155
 
141
156
  expect(screen.getByRole("menuitem", { name: "Copy session ID" })).toBeTruthy();
142
157
  });
143
158
 
159
+ it("shows the running spinner on workspace tabs", () => {
160
+ render(
161
+ <WorkspaceTabsBar
162
+ canGoBack={false}
163
+ canGoForward={false}
164
+ tabs={[
165
+ {
166
+ key: "child-sessions",
167
+ kind: "child-sessions",
168
+ title: "Child sessions",
169
+ tooltip: "Child sessions",
170
+ active: true,
171
+ runStatus: "running",
172
+ onSelect: vi.fn(),
173
+ },
174
+ ]}
175
+ onGoBack={vi.fn()}
176
+ onGoForward={vi.fn()}
177
+ />,
178
+ );
179
+
180
+ expect(screen.getByLabelText("Running")).toBeTruthy();
181
+ });
182
+
144
183
  it("adds an opened project file to the active chat from its action menu", async () => {
145
184
  const user = userEvent.setup();
146
185
  renderPanel();
147
186
 
148
187
  await user.click(
149
- screen.getByRole("button", { name: "File actions" }),
188
+ screen.getByRole("button", { name: "Page actions: Preview: README.md" }),
150
189
  );
151
190
  await user.click(screen.getByRole("menuitem", { name: "Add to chat" }));
152
191
 
@@ -166,17 +205,17 @@ describe("ChatSessionWorkspacePanel", () => {
166
205
  expect(panel.getAttribute("data-theme-surface")).toBe("workspace-panel");
167
206
 
168
207
  await user.click(
169
- screen.getByRole("button", { name: "Maximize workspace panel" }),
208
+ screen.getByRole("button", { name: "Maximize" }),
170
209
  );
171
210
 
172
- expect(panel.className).toContain("absolute");
173
- expect(panel.className).not.toContain("fixed");
211
+ expect(panel.style.position).toBe("fixed");
212
+ expect(panel.style.position).toBe("fixed");
174
213
  expect(
175
214
  screen.queryByTestId("resizable-right-panel-handle"),
176
215
  ).toBeNull();
177
216
 
178
217
  await user.click(
179
- screen.getByRole("button", { name: "Restore workspace panel" }),
218
+ screen.getByRole("button", { name: "Restore size" }),
180
219
  );
181
220
 
182
221
  expect(panel.className).not.toContain("absolute");
@@ -187,10 +226,8 @@ describe("ChatSessionWorkspacePanel", () => {
187
226
  renderPanel("overlay");
188
227
 
189
228
  expect(
190
- screen.queryByRole("button", { name: "Maximize workspace panel" }),
229
+ screen.queryByRole("button", { name: "Maximize" }),
191
230
  ).toBeNull();
192
- expect(screen.getByTestId("chat-session-workspace-panel").className).toContain(
193
- "fixed",
194
- );
231
+ expect(screen.getByTestId("chat-session-workspace-panel").style.position).toBe("fixed");
195
232
  });
196
233
  });
@@ -152,30 +152,34 @@ export function resolveWorkspacePreviewErrorText(error: unknown): string {
152
152
  : t('chatWorkspacePreviewFailed');
153
153
  }
154
154
 
155
- function WorkspaceDiffBody({ diffBlock }: { diffBlock: ChatFileOperationBlockViewModel | null }) {
155
+ function WorkspaceDiffBody({ diffBlock, fileKey }: { diffBlock: ChatFileOperationBlockViewModel | null; fileKey: string }) {
156
156
  if (!diffBlock) {
157
157
  return <WorkspaceFilePreviewStatus text={t('chatWorkspaceDiffEmpty')} />;
158
158
  }
159
- return <WorkspaceCodeSurface block={diffBlock} />;
159
+ return <WorkspaceCodeSurface block={diffBlock} restorationKey={`workspace-preview:diff:${fileKey}`} />;
160
160
  }
161
161
 
162
162
  function WorkspaceCodeSurface({
163
163
  block,
164
+ restorationKey,
164
165
  targetColumn,
165
166
  targetLine,
166
167
  }: {
167
168
  block: ChatFileOperationBlockViewModel;
169
+ restorationKey: string;
168
170
  targetColumn?: number | null;
169
171
  targetLine?: number | null;
170
172
  }) {
173
+ const { scrollRef, onScroll } = useScrollRestoration<HTMLDivElement>({ restorationKey, isEnabled: !targetLine });
171
174
  return (
172
- <div className="h-full overflow-auto custom-scrollbar bg-white">
175
+ <div ref={scrollRef} onScroll={onScroll} className="h-full overflow-auto custom-scrollbar bg-card">
173
176
  <FileOperationCodeSurface block={block} layout="workspace" targetColumn={targetColumn} targetLine={targetLine} />
174
177
  </div>
175
178
  );
176
179
  }
177
180
 
178
181
  function WorkspacePreviewBody({
182
+ fileKey,
179
183
  contentUrl,
180
184
  contentUrlKind,
181
185
  contentLabel,
@@ -194,6 +198,7 @@ function WorkspacePreviewBody({
194
198
  targetColumn,
195
199
  targetLine,
196
200
  }: {
201
+ fileKey: string;
197
202
  contentUrl: string | null;
198
203
  contentUrlKind: WorkspaceFileContentKind | null;
199
204
  contentLabel: string;
@@ -272,7 +277,7 @@ function WorkspacePreviewBody({
272
277
  }
273
278
 
274
279
  if (previewBlock) {
275
- return <WorkspaceCodeSurface block={previewBlock} targetColumn={targetColumn} targetLine={targetLine} />;
280
+ return <WorkspaceCodeSurface block={previewBlock} restorationKey={`workspace-preview:source:${fileKey}`} targetColumn={targetColumn} targetLine={targetLine} />;
276
281
  }
277
282
 
278
283
  return <WorkspaceFilePreviewStatus text={t('chatWorkspacePreviewEmpty')} />;
@@ -304,7 +309,7 @@ export function ChatSessionWorkspaceFilePreview({
304
309
  const markdownScrollRef = useRef<HTMLDivElement>(null);
305
310
  const isPreviewMode = file.viewMode === 'preview';
306
311
  const suppliedContentUrl = file.contentUrl?.trim() || null;
307
- const usesServerPath = isPreviewMode && !suppliedContentUrl;
312
+ const usesServerPath = isPreviewMode && !suppliedContentUrl && file.rawText == null;
308
313
  const previewQuery = useServerPathRead({
309
314
  path: file.path,
310
315
  basePath: sessionWorkingDir,
@@ -338,6 +343,7 @@ export function ChatSessionWorkspaceFilePreview({
338
343
  const localContentUrlCandidate = buildServerPathContentUrl(file.path, sessionWorkingDir);
339
344
  const shouldRenderLocalContent = Boolean(
340
345
  !suppliedContentUrl &&
346
+ file.rawText == null &&
341
347
  isPreviewMode &&
342
348
  localContentUrlCandidate &&
343
349
  file.previewViewer !== 'source' &&
@@ -400,6 +406,7 @@ export function ChatSessionWorkspaceFilePreview({
400
406
  );
401
407
  const previewBody = (
402
408
  <WorkspacePreviewBody
409
+ fileKey={file.key}
403
410
  contentUrl={contentUrl}
404
411
  contentUrlKind={contentUrlKind}
405
412
  contentLabel={file.label?.trim() || resolvedPath}
@@ -445,7 +452,7 @@ export function ChatSessionWorkspaceFilePreview({
445
452
 
446
453
  <div className="flex-1 min-h-0 overflow-hidden">
447
454
  {file.viewMode === 'diff' ? (
448
- <WorkspaceDiffBody diffBlock={diffBlock} />
455
+ <WorkspaceDiffBody diffBlock={diffBlock} fileKey={file.key} />
449
456
  ) : excerptPath && previewText ? (
450
457
  <WorkspaceTextSelectionMenu
451
458
  fileLabel={file.label?.trim() || excerptPath.split('/').at(-1) || excerptPath}
@@ -17,6 +17,7 @@ import { ChatSessionWorkspaceFilePreview } from '@/features/chat/features/worksp
17
17
  import { ChatSessionWorkspaceDirectoryBrowser } from '@/features/chat/features/workspace/components/chat-session-workspace-directory-browser';
18
18
  import { SessionCronJobContent } from '@/features/chat/features/workspace/components/session-cron-job-content';
19
19
  import { ChatSessionChildSessions } from '@/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions';
20
+ import { SessionRunBadge } from '@/features/chat/features/session/components/session-run-badge';
20
21
  import { ChatSessionTokenUsage } from '@/features/chat/features/workspace/components/overview/chat-session-token-usage';
21
22
  import { ChatSessionContinuousAttention } from '@/features/chat/features/workspace/components/overview/chat-session-continuous-attention';
22
23
  import { useNcpSessionObservations } from '@/features/chat/features/ncp/hooks/use-ncp-session-queries';
@@ -32,6 +33,7 @@ import { t } from '@/shared/lib/i18n';
32
33
  import { resolveWorkspaceRelativePath } from '@/shared/lib/session-project';
33
34
  import { cn } from '@/shared/lib/utils';
34
35
  import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
36
+ import type { SessionRunStatus } from '@/features/chat/types/session-run-status.types';
35
37
 
36
38
  type ChatSessionWorkspacePanelContentProps = {
37
39
  activeSelection: WorkspaceSelection;
@@ -51,12 +53,14 @@ function WorkspaceOverviewEntry({
51
53
  description,
52
54
  icon,
53
55
  onClick,
56
+ runStatus,
54
57
  title,
55
58
  }: {
56
59
  count?: number;
57
60
  description: string;
58
61
  icon: ReactNode;
59
62
  onClick: () => void;
63
+ runStatus?: SessionRunStatus;
60
64
  title: string;
61
65
  }) {
62
66
  return (
@@ -76,6 +80,7 @@ function WorkspaceOverviewEntry({
76
80
  {count}
77
81
  </span>
78
82
  ) : null}
83
+ {runStatus ? <SessionRunBadge status={runStatus} /> : null}
79
84
  </span>
80
85
  <span className="mt-0.5 block text-xs leading-5 text-gray-500">{description}</span>
81
86
  </span>
@@ -117,6 +122,7 @@ function WorkspaceOverview({
117
122
  count={childSessionTabs.length}
118
123
  description={t('chatWorkspaceChildSessionsDescription')}
119
124
  icon={<GitBranch className="h-4 w-4" />}
125
+ runStatus={childSessionTabs.some((tab) => tab.runStatus === 'running') ? 'running' : undefined}
120
126
  title={t('chatWorkspaceChildSessions')}
121
127
  onClick={() => {
122
128
  if (sessionKey) {
@@ -8,15 +8,16 @@ import {
8
8
  FolderTree,
9
9
  GitBranch,
10
10
  LayoutDashboard,
11
- Maximize2,
12
11
  MessageSquarePlus,
13
12
  MessageSquareText,
14
- Minimize2,
15
13
  RefreshCw,
14
+ PanelRight,
15
+ PictureInPicture2,
16
16
  X,
17
17
  } from "lucide-react";
18
18
  import type { WorkspaceTabViewModel } from "@/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils";
19
19
  import { copySessionId } from "@/features/chat/features/session/components/session-header/chat-session-more-actions-menu";
20
+ import { SessionRunBadge } from "@/features/chat/features/session/components/session-run-badge";
20
21
  import { AgentIdentityAvatar } from "@/shared/components/common/agent-identity";
21
22
  import { FileTypeIcon } from "@/shared/components/file-type-icon";
22
23
  import {
@@ -104,7 +105,7 @@ function buildWorkspaceFileMenuGroups(
104
105
  ? [{
105
106
  key: "close",
106
107
  icon: <X className="h-4 w-4" />,
107
- label: t("chatWorkspaceCloseFile"),
108
+ label: t("workbenchCloseTab"),
108
109
  onSelect: tab.onClose,
109
110
  }]
110
111
  : [];
@@ -153,7 +154,9 @@ function buildCompactWorkspaceTabs(
153
154
  fileName={tab.fileName}
154
155
  />
155
156
  ),
156
- badge: tab.kind === "file" && tab.viewMode === "diff" ? (
157
+ badge: tab.runStatus ? (
158
+ <SessionRunBadge status={tab.runStatus} />
159
+ ) : tab.kind === "file" && tab.viewMode === "diff" ? (
157
160
  <span className="shrink-0 rounded border border-amber-200 bg-amber-50 px-1 py-0 text-[9px] font-medium uppercase tracking-[0.08em] text-amber-700">
158
161
  {t("chatWorkspaceDiff")}
159
162
  </span>
@@ -162,41 +165,39 @@ function buildCompactWorkspaceTabs(
162
165
  closeLabel: `${
163
166
  tab.kind === "file"
164
167
  ? t("chatWorkspaceCloseFile")
165
- : t("chatWorkspaceCloseTab")
168
+ : t("workbenchCloseTab")
166
169
  }: ${tab.title}`,
167
170
  closePlacement: "leading-hover",
168
171
  onSelect: tab.onSelect,
169
172
  onClose: tab.onClose,
170
- menuLabel:
171
- tab.kind === "child-session"
172
- ? t("chatSessionMoreActions")
173
- : t("chatWorkspaceFileMoreActions"),
174
- menuGroups:
175
- tab.menuGroups ??
176
- buildWorkspaceSessionMenuGroups(tab) ??
177
- buildWorkspaceFileMenuGroups(tab),
173
+ menuLabel: `${t('pageActions')}: ${tab.title}`,
174
+ menuGroups: [
175
+ ...(tab.menuGroups ?? []),
176
+ ...(buildWorkspaceSessionMenuGroups(tab) ?? buildWorkspaceFileMenuGroups(tab) ?? []).map((group) => ({
177
+ ...group,
178
+ items: group.items.filter((item) => !tab.menuGroups?.some((shared) => shared.items.some((action) => action.key === item.key))),
179
+ })).filter((group) => group.items.length > 0),
180
+ { key: 'placement', items: [
181
+ ...(tab.onMoveGlobal ? [{ key: 'move-global', label: t('workbenchMoveGlobal'), icon: <PanelRight className="h-4 w-4" />, onSelect: tab.onMoveGlobal }] : []),
182
+ ...(tab.onFloat ? [{ key: 'float', label: t('workbenchFloatView'), icon: <PictureInPicture2 className="h-4 w-4" />, onSelect: tab.onFloat }] : []),
183
+ ] },
184
+ ],
178
185
  }));
179
186
  }
180
187
 
181
188
  export function WorkspaceTabsBar({
182
189
  canGoBack,
183
190
  canGoForward,
184
- isMaximized = false,
185
- onClose,
186
191
  onGoBack,
187
192
  onGoForward,
188
193
  onRefreshFile,
189
- onToggleMaximize,
190
194
  tabs,
191
195
  }: {
192
196
  canGoBack: boolean;
193
197
  canGoForward: boolean;
194
- isMaximized?: boolean;
195
- onClose: () => void;
196
198
  onGoBack: () => void;
197
199
  onGoForward: () => void;
198
200
  onRefreshFile?: () => void;
199
- onToggleMaximize?: () => void;
200
201
  tabs: readonly WorkspaceTabViewModel[];
201
202
  }) {
202
203
  const compactTabs = buildCompactWorkspaceTabs(tabs);
@@ -213,27 +214,11 @@ export function WorkspaceTabsBar({
213
214
  },
214
215
  ]
215
216
  : []),
216
- ...(onToggleMaximize
217
- ? [
218
- {
219
- key: "maximize",
220
- icon: isMaximized ? (
221
- <Minimize2 className="h-4 w-4" />
222
- ) : (
223
- <Maximize2 className="h-4 w-4" />
224
- ),
225
- label: isMaximized
226
- ? t("chatWorkspaceRestorePanel")
227
- : t("chatWorkspaceMaximizePanel"),
228
- onClick: onToggleMaximize,
229
- },
230
- ]
231
- : []),
232
- { key: "close", icon: <X className="h-4 w-4" />, label: t("chatWorkspaceClosePanel"), onClick: onClose },
233
217
  ];
234
218
 
235
219
  return (
236
220
  <CompactTabStrip
221
+ className="h-10 min-w-0 flex-1 border-0 bg-transparent px-0"
237
222
  testId="workspace-tabs-bar"
238
223
  scrollTestId="workspace-tabs-scroll"
239
224
  tabs={compactTabs}
@@ -1,3 +1,8 @@
1
+ import { usePageResourceActions } from '@/features/right-panel-resources';
2
+ import { pageResourceFromTarget } from '@/features/right-panel-resources';
3
+ import { createWorkspaceFilePanelTarget } from '@/features/chat/features/workspace/utils/workspace-file-panel-route.utils';
4
+ import { buildSessionPanelUrl } from '@/features/chat/features/session/utils/chat-session-route.utils';
5
+ import { sessionSurfaceManager } from '@/features/chat/managers/session-surface.manager';
1
6
  import { useEffect, useMemo, useState } from "react";
2
7
  import { useQueryClient } from "@tanstack/react-query";
3
8
  import type { CronJobView } from "@/shared/lib/api";
@@ -23,8 +28,9 @@ import {
23
28
  import { WorkspaceTabsBar } from "./chat-session-workspace-panel-nav";
24
29
  import { usePresenter } from "@/features/chat/components/providers/chat-presenter.provider";
25
30
  import { ChatSessionWorkspacePanelContent } from "@/features/chat/features/workspace/components/chat-session-workspace-panel-content";
26
- import { ResizableRightPanel } from "@/shared/components/resizable-right-panel/resizable-right-panel";
27
- import { cn } from "@/shared/lib/utils";
31
+ import { WorkbenchSurface } from "@/shared/components/workbench/workbench-surface";
32
+ import { getAppPresenter } from "@/app/presenters/app.presenter";
33
+ import { t } from "@/shared/lib/i18n";
28
34
  import {
29
35
  canGoBackInNavigationHistory,
30
36
  canGoForwardInNavigationHistory,
@@ -34,6 +40,7 @@ import { buildServerPathReadQueryKey } from "@/shared/hooks/use-server-path-read
34
40
 
35
41
  type ChatSessionWorkspacePanelProps = {
36
42
  sessionKey: string | null;
43
+ hidden?: boolean;
37
44
  childSessionTabs: readonly ChatChildSessionTab[];
38
45
  activeChildSessionKey: string | null;
39
46
  activeSideChatDraft: ChatWorkspaceSideChatDraft | null;
@@ -55,6 +62,7 @@ type ChatSessionWorkspacePanelProps = {
55
62
 
56
63
  export function ChatSessionWorkspacePanel({
57
64
  sessionKey,
65
+ hidden = false,
58
66
  childSessionTabs,
59
67
  activeChildSessionKey,
60
68
  activeSideChatDraft,
@@ -74,8 +82,8 @@ export function ChatSessionWorkspacePanel({
74
82
  displayMode = "docked",
75
83
  }: ChatSessionWorkspacePanelProps) {
76
84
  const presenter = usePresenter();
85
+ const pageActions = usePageResourceActions();
77
86
  const queryClient = useQueryClient();
78
- const [isMaximized, setIsMaximized] = useState(false);
79
87
  const [filePreviewRefreshVersion, setFilePreviewRefreshVersion] = useState(0);
80
88
  const resolvedChildTabs = useNcpChildSessionTabsView(childSessionTabs);
81
89
  const optimisticReadAtBySessionKey = useChatSessionListStore(
@@ -159,8 +167,6 @@ export function ChatSessionWorkspacePanel({
159
167
  return null;
160
168
  }
161
169
 
162
- const isContainerMaximized = displayMode === "docked" && isMaximized;
163
- const isOverlayPanel = displayMode === "overlay" || isContainerMaximized;
164
170
  const activeFile =
165
171
  activeSelection.kind === "file" && activeSelection.file.viewMode === "preview"
166
172
  ? activeSelection.file
@@ -185,40 +191,43 @@ export function ChatSessionWorkspacePanel({
185
191
  : undefined;
186
192
 
187
193
  return (
188
- <ResizableRightPanel
189
- data-testid="chat-session-workspace-panel"
190
- data-theme-surface="workspace-panel"
191
- className={cn(
192
- isOverlayPanel
193
- ? "bg-white"
194
- : "hidden border-gray-200/70 bg-white/95 backdrop-blur-sm md:flex",
195
- isContainerMaximized ? "shadow-xl" : null,
196
- )}
197
- defaultWidth={workspacePanelWidth}
198
- width={workspacePanelWidth}
199
- minWidth={CHAT_WORKSPACE_PANEL_MIN_WIDTH}
200
- maxWidth={CHAT_WORKSPACE_PANEL_MAX_WIDTH}
194
+ <WorkbenchSurface
195
+ id={`session-workspace:${sessionKey ?? 'draft'}`} manager={getAppPresenter().workbenchSurfaceManager}
196
+ title={t('workbenchSessionGroup')} testId="chat-session-workspace-panel" hidden={hidden}
197
+ width={workspacePanelWidth} minWidth={CHAT_WORKSPACE_PANEL_MIN_WIDTH} maxWidth={CHAT_WORKSPACE_PANEL_MAX_WIDTH}
201
198
  onWidthCommit={presenter.chatThreadManager.setWorkspacePanelWidth}
202
- overlay={isOverlayPanel}
203
- overlayScope={isContainerMaximized ? "container" : "viewport"}
204
- >
199
+ fullscreen={displayMode === "overlay"} onClose={presenter.chatThreadManager.closeWorkspacePanel} closeLabel={t('workbenchHideGroup')}
200
+ navigation={
205
201
  <WorkspaceTabsBar
206
- tabs={workspaceTabs}
202
+ tabs={workspaceTabs.map((tab) => ({
203
+ ...tab,
204
+ menuGroups: (() => {
205
+ const file = workspaceFileTabs.find((item) => `file:${item.key}` === tab.key);
206
+ const target = file ? createWorkspaceFilePanelTarget(file, { workingDir: sessionWorkingDir, projectRoot: sessionProjectRoot })
207
+ : tab.sessionKey ? { kind: 'chat-session', title: tab.title, url: buildSessionPanelUrl(tab.sessionKey), resourceUri: buildSessionPanelUrl(tab.sessionKey), historyPolicy: 'none' as const } : tab.kind !== 'side-chat-draft' ? { kind: 'workspace', title: tab.title, url: `nextclaw://workspace?${new URLSearchParams({ session: sessionKey ?? '', page: tab.kind })}`, historyPolicy: 'none' as const } : null;
208
+ return target ? [...pageActions(pageResourceFromTarget(target), 'workspace'), ...(tab.menuGroups ?? [])] : tab.menuGroups;
209
+ })(),
210
+ onMoveGlobal: tab.kind === 'file' ? () => presenter.chatThreadManager.moveFileToGlobal(tab.key.slice('file:'.length), { workingDir: sessionWorkingDir, projectRoot: sessionProjectRoot }, getAppPresenter().docBrowserManager)
211
+ : tab.kind === 'child-session' && tab.sessionKey ? () => {
212
+ sessionSurfaceManager.dock({ sessionKey: tab.sessionKey!, title: tab.title }, getAppPresenter().docBrowserManager);
213
+ tab.onClose?.();
214
+ } : undefined,
215
+ onFloat: tab.kind === 'child-session' && tab.sessionKey ? () => {
216
+ sessionSurfaceManager.open({ sessionKey: tab.sessionKey!, title: tab.title });
217
+ tab.onClose?.();
218
+ } : undefined,
219
+ }))}
207
220
  canGoBack={canGoBackInNavigationHistory(workspaceHistory)}
208
221
  canGoForward={canGoForwardInNavigationHistory(workspaceHistory)}
209
- isMaximized={isContainerMaximized}
210
222
  onGoBack={presenter.chatThreadManager.goBackWorkspacePanel}
211
223
  onGoForward={presenter.chatThreadManager.goForwardWorkspacePanel}
212
224
  onRefreshFile={refreshActiveFile}
213
- onToggleMaximize={
214
- displayMode === "docked"
215
- ? () => setIsMaximized((value) => !value)
216
- : undefined
217
- }
218
- onClose={presenter.chatThreadManager.closeWorkspacePanel}
225
+
219
226
  />
227
+ }
228
+ >
220
229
 
221
- <div className="flex min-h-0 flex-1 flex-col bg-white">
230
+ <div className="flex min-h-0 flex-1 flex-col bg-card">
222
231
  <ChatSessionWorkspacePanelContent
223
232
  activeSelection={activeSelection}
224
233
  childSessionTabs={resolvedChildTabs}
@@ -232,6 +241,6 @@ export function ChatSessionWorkspacePanel({
232
241
  sessionWorkingDir={sessionWorkingDir}
233
242
  />
234
243
  </div>
235
- </ResizableRightPanel>
244
+ </WorkbenchSurface>
236
245
  );
237
246
  }