@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,4 @@
1
+ import { CurrentPageActions } from '@/features/right-panel-resources';
1
2
  import { lazy, Suspense } from "react";
2
3
  import {
3
4
  isChatSessionDetailRoute,
@@ -25,7 +26,6 @@ type MobileAppShellProps = {
25
26
 
26
27
  export function MobileAppShell({
27
28
  pathname,
28
- isDocBrowserOpen,
29
29
  docBrowserDockControls,
30
30
  docBrowserRenderers = {},
31
31
  docBrowserTabMenuGroups,
@@ -33,12 +33,13 @@ export function MobileAppShell({
33
33
  children,
34
34
  }: MobileAppShellProps) {
35
35
  const isMainRoute = isMainWorkspaceRoute(pathname);
36
- const showTopbar = !isChatSessionDetailRoute(pathname);
36
+ const showTopbar = pathname !== '/chat' && !isChatSessionDetailRoute(pathname);
37
37
  const showBottomNav = !isChatSessionDetailRoute(pathname);
38
38
 
39
39
  return (
40
40
  <div className="flex h-[100svh] flex-col bg-background font-sans text-foreground supports-[height:100dvh]:h-[100dvh]">
41
41
  {showTopbar ? <MobileTopbar leadingInset={topbarLeadingInset} /> : null}
42
+ {!isMainRoute ? <CurrentPageActions /> : null}
42
43
  <div className="relative flex-1 min-h-0 overflow-hidden">
43
44
  {isMainRoute ? (
44
45
  <div className="h-full min-h-0 overflow-hidden">{children}</div>
@@ -49,7 +50,7 @@ export function MobileAppShell({
49
50
  )}
50
51
  </div>
51
52
  {showBottomNav ? <MobileBottomNav /> : null}
52
- {isDocBrowserOpen ? (
53
+ {(
53
54
  <Suspense fallback={null}>
54
55
  <DocBrowser
55
56
  customTabRenderers={docBrowserRenderers}
@@ -58,7 +59,7 @@ export function MobileAppShell({
58
59
  getTabMenuGroups={docBrowserTabMenuGroups}
59
60
  />
60
61
  </Suspense>
61
- ) : null}
62
+ )}
62
63
  </div>
63
64
  );
64
65
  }
@@ -20,7 +20,7 @@ export function MobileBottomNav() {
20
20
  <nav
21
21
  data-testid="mobile-bottom-nav"
22
22
  aria-label={t("settings")}
23
- className="shrink-0 border-t border-gray-200/80 bg-white/95 backdrop-blur-sm"
23
+ className="shrink-0 border-t border-border/60 bg-background text-foreground"
24
24
  style={{
25
25
  paddingBottom: "calc(env(safe-area-inset-bottom, 0px) + 0.25rem)",
26
26
  }}
@@ -39,19 +39,19 @@ export function MobileBottomNav() {
39
39
  className={cn(
40
40
  "group flex min-h-[2.875rem] flex-col items-center justify-center gap-0.5 rounded-xl px-2 py-1 text-[10px] font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border",
41
41
  active
42
- ? "bg-gray-100 text-gray-900"
43
- : "text-gray-500 hover:bg-gray-50 hover:text-gray-800",
42
+ ? "bg-muted text-foreground"
43
+ : "text-muted-foreground hover:bg-muted hover:text-foreground",
44
44
  )}
45
45
  >
46
46
  <span className="relative">
47
47
  <item.icon
48
48
  className={cn(
49
49
  "h-3.5 w-3.5",
50
- active ? "text-gray-900" : "text-gray-400",
50
+ active ? "text-foreground" : "text-muted-foreground",
51
51
  )}
52
52
  />
53
53
  {item.target === "/inbox" && unreadCount > 0 ? (
54
- <span className="absolute -right-1 -top-1 h-1.5 w-1.5 rounded-full bg-primary ring-1 ring-white" />
54
+ <span className="absolute -right-1 -top-1 h-1.5 w-1.5 rounded-full bg-primary ring-1 ring-background" />
55
55
  ) : null}
56
56
  </span>
57
57
  <span className="max-w-full truncate">{item.label}</span>
@@ -63,9 +63,9 @@ export function MobileBottomNav() {
63
63
  <button
64
64
  type="button"
65
65
  onClick={() => openApps(docBrowser)}
66
- className="group flex min-h-[2.875rem] w-full flex-col items-center justify-center gap-0.5 rounded-xl px-2 py-1 text-[10px] font-medium text-gray-500 transition-colors hover:bg-gray-50 hover:text-gray-800 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
66
+ className="group flex min-h-[2.875rem] w-full flex-col items-center justify-center gap-0.5 rounded-xl px-2 py-1 text-[10px] font-medium text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
67
67
  >
68
- <Boxes className="h-3.5 w-3.5 text-gray-400" />
68
+ <Boxes className="h-3.5 w-3.5 text-muted-foreground" />
69
69
  <span className="max-w-full truncate">{t("appsTitle")}</span>
70
70
  </button>
71
71
  </li>
@@ -11,7 +11,7 @@ export function MobileTopbar({ leadingInset }: { leadingInset?: string }) {
11
11
  return (
12
12
  <header
13
13
  data-testid="mobile-topbar"
14
- className="shrink-0 border-b border-gray-200/80 bg-white/95 backdrop-blur-sm"
14
+ className="shrink-0 border-b border-border/60 bg-secondary text-foreground"
15
15
  style={{
16
16
  paddingTop: "calc(env(safe-area-inset-top, 0px) + 0.25rem)",
17
17
  }}
@@ -24,18 +24,18 @@ export function MobileTopbar({ leadingInset }: { leadingInset?: string }) {
24
24
  <button
25
25
  type="button"
26
26
  onClick={() => navigate(routeMeta.backTarget as string)}
27
- className="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-gray-200 text-gray-600 transition-colors hover:bg-gray-50 hover:text-gray-900"
27
+ className="inline-flex h-11 w-11 shrink-0 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
28
28
  aria-label={routeMeta.backLabel ?? t("backToMain")}
29
29
  >
30
30
  <ArrowLeft className="h-4 w-4" />
31
31
  </button>
32
32
  ) : null}
33
33
  <div className="min-w-0 flex-1">
34
- <h1 className="truncate text-center text-[15px] font-semibold text-gray-900">
34
+ <h1 className="truncate text-center text-[17px] font-semibold text-foreground">
35
35
  {routeMeta.title}
36
36
  </h1>
37
37
  </div>
38
- {routeMeta.backTarget ? <div className="h-8 w-8 shrink-0" aria-hidden="true" /> : null}
38
+ {routeMeta.backTarget ? <div className="h-11 w-11 shrink-0" aria-hidden="true" /> : null}
39
39
  </div>
40
40
  </header>
41
41
  );
@@ -1,3 +1,4 @@
1
+ import { WorkbenchSurfaceManager } from '@/shared/components/workbench/managers/workbench-surface.manager';
1
2
  import { act, renderHook, waitFor } from '@testing-library/react';
2
3
  import type { ReactNode } from 'react';
3
4
  import { DocBrowserProvider, useDocBrowser } from '@/shared/components/doc-browser/doc-browser-context';
@@ -18,7 +19,7 @@ const wrapper = ({ children }: { children: ReactNode }) => (
18
19
  <DocBrowserProvider manager={testDocBrowserManager}>{children}</DocBrowserProvider>
19
20
  );
20
21
 
21
- const testDocBrowserManager = new DocBrowserManager(new RightPanelResourceRouteResolver());
22
+ const testDocBrowserManager = new DocBrowserManager(new WorkbenchSurfaceManager(), new RightPanelResourceRouteResolver());
22
23
 
23
24
  const docBrowserStorageKey = 'nextclaw.doc-browser.state';
24
25
 
@@ -56,7 +57,7 @@ async function resetMemoryThenRehydrate(savedState: string | null) {
56
57
  describe('DocBrowserManager layout notifications', () => {
57
58
  it('notifies the app layout coordinator after opening the docked browser', () => {
58
59
  const onRightPanelOpened = vi.fn();
59
- const manager = new DocBrowserManager(
60
+ const manager = new DocBrowserManager(new WorkbenchSurfaceManager(),
60
61
  new RightPanelResourceRouteResolver(),
61
62
  onRightPanelOpened,
62
63
  );
@@ -71,7 +72,7 @@ describe('DocBrowserManager layout notifications', () => {
71
72
 
72
73
  it('notifies the app layout coordinator after changing dock mode', () => {
73
74
  const onRightPanelOpened = vi.fn();
74
- const manager = new DocBrowserManager(
75
+ const manager = new DocBrowserManager(new WorkbenchSurfaceManager(),
75
76
  new RightPanelResourceRouteResolver(),
76
77
  onRightPanelOpened,
77
78
  );
@@ -20,16 +20,11 @@ function renderTabStrip(tabs: DocBrowserTab[]) {
20
20
  activeTabId={tabs[0]?.id ?? ""}
21
21
  canGoBack={false}
22
22
  canGoForward={false}
23
- isDocked={true}
24
- isFullscreen={false}
25
23
  onGoBack={vi.fn()}
26
24
  onGoForward={vi.fn()}
27
25
  onOpenNewTab={vi.fn()}
28
26
  onSetActiveTab={vi.fn()}
29
27
  onCloseTab={vi.fn()}
30
- onClose={vi.fn()}
31
- onDragStart={vi.fn()}
32
- onToggleMode={vi.fn()}
33
28
  />,
34
29
  );
35
30
  }
@@ -1,4 +1,14 @@
1
- import { fireEvent, render, screen } from "@testing-library/react";
1
+ import { MemoryRouter } from 'react-router-dom';
2
+ import { AppPresenterProvider } from '@/app/components/app-presenter-provider';
3
+ import type { ReactElement } from 'react';
4
+
5
+ function render(ui: ReactElement) {
6
+ return renderUi(<MemoryRouter><AppPresenterProvider>{ui}</AppPresenterProvider></MemoryRouter>);
7
+ }
8
+
9
+ import { WorkbenchSurfaceManager } from '@/shared/components/workbench/managers/workbench-surface.manager';
10
+ import { useWorkbenchSurfaceStore } from '@/shared/components/workbench/stores/workbench-surface.store';
11
+ import { fireEvent, render as renderUi, screen } from "@testing-library/react";
2
12
  import userEvent from "@testing-library/user-event";
3
13
  import { beforeEach, describe, expect, it, vi } from "vitest";
4
14
  import { DocBrowser } from "@/shared/components/doc-browser/doc-browser";
@@ -137,6 +147,7 @@ function firePointerEvent(
137
147
  }
138
148
 
139
149
  function resetDocBrowserTestState() {
150
+ useWorkbenchSurfaceStore.setState({ surfaces: {} });
140
151
  vi.clearAllMocks();
141
152
  docBrowserState.mode = "docked";
142
153
  docBrowserState.tabs = [
@@ -190,7 +201,7 @@ describe("DocBrowser", () => {
190
201
  expect(screen.getByTestId("doc-browser-panel").style.width).toBe("420px");
191
202
  expect(
192
203
  screen.getByTestId("doc-browser-panel").getAttribute("data-theme-surface"),
193
- ).toBe("doc-browser");
204
+ ).toBe("workspace-panel");
194
205
  expect(screen.getByTestId("resizable-right-panel-handle")).toBeTruthy();
195
206
  });
196
207
 
@@ -213,9 +224,9 @@ describe("DocBrowser", () => {
213
224
 
214
225
  const panel = screen.getByTestId("doc-browser-panel");
215
226
 
216
- expect(panel.className).toContain("fixed");
217
- expect(panel.className).toContain("inset-0");
218
- expect(panel.className).toContain("w-screen");
227
+ expect(panel.style.position).toBe("fixed");
228
+ expect(panel.style.inset).toBe("0");
229
+ expect(panel.style.width).toBe("100%");
219
230
  expect(
220
231
  screen.queryByRole("button", { name: /float/i }) ??
221
232
  screen.queryByRole("button", { name: /dock/i }),
@@ -224,7 +235,7 @@ describe("DocBrowser", () => {
224
235
  expect(panel.querySelector(".cursor-se-resize")).toBeNull();
225
236
  });
226
237
 
227
- it("keeps browser window controls on the tab strip", async () => {
238
+ it("separates shared window controls from navigation", async () => {
228
239
  const user = userEvent.setup();
229
240
  render(
230
241
  <DocBrowser customTabRenderers={PANEL_APPS_DOC_BROWSER_RENDERERS} />,
@@ -232,7 +243,7 @@ describe("DocBrowser", () => {
232
243
 
233
244
  const tabStrip = screen.getByTestId("doc-browser-tab-strip");
234
245
  const tabActions = screen.getByTestId("doc-browser-tab-actions");
235
- const floatButton = screen.getByRole("button", { name: "Float Window" });
246
+ const floatButton = screen.getByRole("button", { name: "Float view group" });
236
247
  const newTabButton = screen.getByRole("button", { name: "New Tab" });
237
248
 
238
249
  expect(
@@ -243,12 +254,12 @@ describe("DocBrowser", () => {
243
254
  ).toBe(true);
244
255
  expect(
245
256
  tabStrip.contains(floatButton),
246
- ).toBe(true);
257
+ ).toBe(false);
247
258
  expect(floatButton.querySelector(".lucide-picture-in-picture2")).toBeTruthy();
248
259
  expect(floatButton.querySelector(".lucide-maximize2")).toBeNull();
249
260
  expect(
250
- tabStrip.contains(screen.getByRole("button", { name: "Close" })),
251
- ).toBe(true);
261
+ tabStrip.contains(screen.getByRole("button", { name: "Hide view group" })),
262
+ ).toBe(false);
252
263
  expect(tabActions.contains(newTabButton)).toBe(true);
253
264
  expect(screen.queryByText("Embedded Browser")).toBeNull();
254
265
 
@@ -532,9 +543,9 @@ describe("DocBrowser panel app navigation", () => {
532
543
  await user.click(screen.getByRole("button", { name: "Back" }));
533
544
  expect(docBrowserState.goBack).toHaveBeenCalledTimes(1);
534
545
 
535
- expect(screen.queryByRole("button", { name: "Add to main sidebar" })).toBeNull();
546
+ expect(screen.queryByRole("button", { name: "Pin to left sidebar" })).toBeNull();
536
547
  await user.click(screen.getByRole("button", { name: "More panel app actions" }));
537
- await user.click(screen.getByRole("button", { name: "Add to main sidebar" }));
548
+ await user.click(screen.getByRole("button", { name: "Pin to left sidebar" }));
538
549
  expect(panelAppHooks.mutate).toHaveBeenCalledWith({
539
550
  id: "piano",
540
551
  preferences: { mainSidebar: true },
@@ -560,7 +571,7 @@ describe("DocBrowser panel app navigation", () => {
560
571
  render(<DocBrowser customTabRenderers={PANEL_APPS_DOC_BROWSER_RENDERERS} />);
561
572
 
562
573
  await user.click(screen.getByRole("button", { name: "More panel app actions" }));
563
- await user.click(screen.getByRole("button", { name: "Add to main sidebar" }));
574
+ await user.click(screen.getByRole("button", { name: "Pin to left sidebar" }));
564
575
  expect(panelAppHooks.mutate).toHaveBeenCalledWith({
565
576
  id: "piano",
566
577
  preferences: { mainSidebar: true },
@@ -640,40 +651,18 @@ describe("DocBrowser floating interactions", () => {
640
651
  installDocBrowserPointerTestEnvironment();
641
652
  });
642
653
 
643
- it("starts floating drag from the header background without stealing tab actions", () => {
644
- const onDragStart = vi.fn();
645
-
646
- render(
647
- <DocBrowserTabStrip
648
- tabs={docBrowserState.tabs}
649
- activeTabId="docs"
650
- canGoBack={false}
651
- canGoForward={false}
652
- isDocked={false}
653
- isFullscreen={false}
654
- onGoBack={vi.fn()}
655
- onGoForward={vi.fn()}
656
- onOpenNewTab={vi.fn()}
657
- onSetActiveTab={vi.fn()}
658
- onCloseTab={vi.fn()}
659
- onClose={vi.fn()}
660
- onDragStart={onDragStart}
661
- onToggleMode={vi.fn()}
662
- />,
663
- );
664
-
665
- fireEvent.pointerDown(screen.getByRole("button", { name: "Docs" }));
666
- expect(onDragStart).not.toHaveBeenCalled();
667
-
668
- const tabStrip = screen.getByTestId("doc-browser-tab-strip");
669
- const headerDragSurface = tabStrip.querySelector(".doc-browser-tab-scrollbar");
670
- expect(headerDragSurface).toBeInstanceOf(HTMLElement);
671
- expect((headerDragSurface as HTMLElement).className).toContain("cursor-grab");
672
- expect(screen.getByRole("button", { name: "Docs" }).parentElement?.className).toContain("cursor-pointer");
673
-
674
- fireEvent.pointerDown(headerDragSurface as HTMLElement);
675
-
676
- expect(onDragStart).toHaveBeenCalledTimes(1);
654
+ it("drags the shared header without stealing tab actions", () => {
655
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
656
+ render(<DocBrowser />);
657
+ const panel = screen.getByTestId('doc-browser-panel');
658
+ const before = panel.style.left;
659
+ firePointerEvent(screen.getByRole('button', { name: 'Docs' }), 'pointerdown', { clientX: 100, pointerId: 1 });
660
+ firePointerEvent(window, 'pointermove', { clientX: 120, pointerId: 1 });
661
+ expect(panel.style.left).toBe(before);
662
+ firePointerEvent(panel.querySelector('header')!, 'pointerdown', { clientX: 100, pointerId: 1 });
663
+ firePointerEvent(window, 'pointermove', { clientX: 140, pointerId: 1 });
664
+ firePointerEvent(window, 'pointerup', { clientX: 140, pointerId: 1 });
665
+ expect(parseFloat(panel.style.left)).toBe(parseFloat(before) + 40);
677
666
  });
678
667
 
679
668
  it("opens the same tab action from right click and the more button", () => {
@@ -685,16 +674,11 @@ describe("DocBrowser floating interactions", () => {
685
674
  activeTabId="docs"
686
675
  canGoBack={false}
687
676
  canGoForward={false}
688
- isDocked={true}
689
- isFullscreen={false}
690
677
  onGoBack={vi.fn()}
691
678
  onGoForward={vi.fn()}
692
679
  onOpenNewTab={vi.fn()}
693
680
  onSetActiveTab={vi.fn()}
694
681
  onCloseTab={vi.fn()}
695
- onClose={vi.fn()}
696
- onDragStart={vi.fn()}
697
- onToggleMode={vi.fn()}
698
682
  getTabMenuGroups={() => [{
699
683
  key: "chat",
700
684
  items: [{ key: "add", label: "Add to Chat", onSelect: onAddToChat }],
@@ -711,12 +695,12 @@ describe("DocBrowser floating interactions", () => {
711
695
  });
712
696
 
713
697
  it("keeps the floating panel left edge stable when resizing from the right", () => {
714
- docBrowserState.mode = "floating";
698
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
715
699
 
716
700
  render(<DocBrowser />);
717
701
 
718
702
  firePointerEvent(
719
- screen.getByTestId("doc-browser-resize-right"),
703
+ document.querySelector('[data-workbench-resize="right"]')!,
720
704
  "pointerdown",
721
705
  {
722
706
  clientX: 1160,
@@ -726,17 +710,17 @@ describe("DocBrowser floating interactions", () => {
726
710
  firePointerEvent(window, "pointermove", { clientX: 1120, pointerId: 1 });
727
711
 
728
712
  const panel = screen.getByTestId("doc-browser-panel");
729
- expect(panel.style.left).toBe("680px");
730
- expect(panel.style.width).toBe("440px");
713
+ expect(panel.style.left).toBe("80px");
714
+ expect(panel.style.width).toBe("520px");
731
715
  });
732
716
 
733
717
  it("keeps the floating panel right edge stable when resizing from the left", () => {
734
- docBrowserState.mode = "floating";
718
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
735
719
 
736
720
  render(<DocBrowser />);
737
721
 
738
722
  firePointerEvent(
739
- screen.getByTestId("doc-browser-resize-left"),
723
+ document.querySelector('[data-workbench-resize="left"]')!,
740
724
  "pointerdown",
741
725
  {
742
726
  clientX: 680,
@@ -746,17 +730,17 @@ describe("DocBrowser floating interactions", () => {
746
730
  firePointerEvent(window, "pointermove", { clientX: 620, pointerId: 1 });
747
731
 
748
732
  const panel = screen.getByTestId("doc-browser-panel");
749
- expect(panel.style.left).toBe("620px");
750
- expect(panel.style.width).toBe("540px");
733
+ expect(panel.style.left).toBe("20px");
734
+ expect(panel.style.width).toBe("620px");
751
735
  });
752
736
 
753
737
  it("keeps the floating panel bottom edge stable when resizing from the top", () => {
754
- docBrowserState.mode = "floating";
738
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
755
739
 
756
740
  render(<DocBrowser />);
757
741
 
758
742
  firePointerEvent(
759
- screen.getByTestId("doc-browser-resize-top"),
743
+ document.querySelector('[data-workbench-resize="top"]')!,
760
744
  "pointerdown",
761
745
  {
762
746
  clientX: 900,
@@ -772,16 +756,16 @@ describe("DocBrowser floating interactions", () => {
772
756
 
773
757
  const panel = screen.getByTestId("doc-browser-panel");
774
758
  expect(panel.style.top).toBe("120px");
775
- expect(panel.style.height).toBe("560px");
759
+ expect(panel.style.height).toBe("600px");
776
760
  });
777
761
 
778
762
  it("resizes the floating panel from the bottom-left corner", () => {
779
- docBrowserState.mode = "floating";
763
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
780
764
 
781
765
  render(<DocBrowser />);
782
766
 
783
767
  firePointerEvent(
784
- screen.getByTestId("doc-browser-resize-bottom-left"),
768
+ document.querySelector('[data-workbench-resize="bottom-left"]')!,
785
769
  "pointerdown",
786
770
  {
787
771
  clientX: 680,
@@ -796,19 +780,19 @@ describe("DocBrowser floating interactions", () => {
796
780
  });
797
781
 
798
782
  const panel = screen.getByTestId("doc-browser-panel");
799
- expect(panel.style.left).toBe("620px");
783
+ expect(panel.style.left).toBe("20px");
800
784
  expect(panel.style.top).toBe("80px");
801
- expect(panel.style.width).toBe("540px");
802
- expect(panel.style.height).toBe("640px");
785
+ expect(panel.style.width).toBe("620px");
786
+ expect(panel.style.height).toBe("680px");
803
787
  });
804
788
 
805
789
  it("resizes the floating panel from the top-right corner", () => {
806
- docBrowserState.mode = "floating";
790
+ new WorkbenchSurfaceManager().place('global-resources', 'floating');
807
791
 
808
792
  render(<DocBrowser />);
809
793
 
810
794
  firePointerEvent(
811
- screen.getByTestId("doc-browser-resize-top-right"),
795
+ document.querySelector('[data-workbench-resize="top-right"]')!,
812
796
  "pointerdown",
813
797
  {
814
798
  clientX: 1160,
@@ -823,10 +807,10 @@ describe("DocBrowser floating interactions", () => {
823
807
  });
824
808
 
825
809
  const panel = screen.getByTestId("doc-browser-panel");
826
- expect(panel.style.left).toBe("680px");
810
+ expect(panel.style.left).toBe("80px");
827
811
  expect(panel.style.top).toBe("120px");
828
- expect(panel.style.width).toBe("440px");
829
- expect(panel.style.height).toBe("560px");
812
+ expect(panel.style.width).toBe("520px");
813
+ expect(panel.style.height).toBe("600px");
830
814
  });
831
815
  });
832
816
 
@@ -0,0 +1,104 @@
1
+ import { fireEvent, render, screen } from "@testing-library/react";
2
+ import { MemoryRouter, useLocation } from "react-router-dom";
3
+ import { beforeEach, describe, expect, it } from "vitest";
4
+ import {
5
+ ChatMessageMarkdown,
6
+ ChatResourceLinkProvider,
7
+ } from "@nextclaw/agent-chat-ui";
8
+ import { AppPresenterProvider } from "@/app/components/app-presenter-provider";
9
+ import { getPresenter } from "@/app/presenters/app.presenter";
10
+ import { useDocLinkInterceptor } from "@/shared/components/doc-browser/use-doc-link-interceptor";
11
+ import { useDocBrowserStore } from "@/shared/components/doc-browser/stores/doc-browser.store";
12
+ import { createDefaultDocBrowserState } from "@/shared/components/doc-browser/utils/doc-browser-state.utils";
13
+ import { PageResourceIcon } from "@/features/right-panel-resources";
14
+ import { pageResourceTab } from "@/features/right-panel-resources";
15
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
16
+
17
+ function LinkedMarkdown({
18
+ text = "[Notes](nextclaw://panel-app/example-notes)",
19
+ }: {
20
+ text?: string;
21
+ }) {
22
+ useDocLinkInterceptor();
23
+ const { pathname } = useLocation();
24
+ return (
25
+ <>
26
+ <output data-testid="route">{pathname}</output>
27
+ <ChatResourceLinkProvider
28
+ renderIcon={(uri) => (
29
+ <PageResourceIcon uri={uri} icon={{ type: "text", value: "✎" }} />
30
+ )}
31
+ >
32
+ <ChatMessageMarkdown
33
+ text={text}
34
+ role="assistant"
35
+ texts={{ copyCodeLabel: "Copy", copiedCodeLabel: "Copied" }}
36
+ />
37
+ </ChatResourceLinkProvider>
38
+ </>
39
+ );
40
+ }
41
+
42
+ describe("ordinary Markdown resource links end to end", () => {
43
+ beforeEach(() =>
44
+ useDocBrowserStore.setState({ snapshot: createDefaultDocBrowserState() }),
45
+ );
46
+ function setup(text?: string) {
47
+ return render(
48
+ <QueryClientProvider client={new QueryClient()}>
49
+ <MemoryRouter initialEntries={["/chat"]}>
50
+ <AppPresenterProvider>
51
+ <LinkedMarkdown text={text} />
52
+ </AppPresenterProvider>
53
+ </MemoryRouter>
54
+ </QueryClientProvider>,
55
+ );
56
+ }
57
+ it.each(["cron-job", "skill", "agent", "project", "inbox-delivery"])(
58
+ "opens a normal Markdown %s object link in the shared resource viewer",
59
+ (kind) => {
60
+ const uri = "nextclaw://objects/" + kind + "/existing-object";
61
+ setup("[Object](" + uri + ")");
62
+ fireEvent.click(screen.getByRole("link", { name: "Object" }));
63
+ const { snapshot } = useDocBrowserStore.getState();
64
+ expect(snapshot.isOpen).toBe(true);
65
+ expect(
66
+ snapshot.tabs.find((tab) => tab.id === snapshot.activeTabId),
67
+ ).toMatchObject({
68
+ kind: "system-object",
69
+ resourceUri: uri,
70
+ title: "Object",
71
+ });
72
+ expect(screen.getByTestId("route").textContent).toBe("/chat");
73
+ },
74
+ );
75
+ it("opens a normal Panel App link in the global sidebar without a catalog lookup", () => {
76
+ setup();
77
+ const link = screen.getByRole("link", { name: "Notes" });
78
+ expect(link.querySelector("span")?.textContent).toContain("✎");
79
+ fireEvent.click(link);
80
+ expect(screen.getByTestId("route").textContent).toBe("/chat");
81
+ const { snapshot } = useDocBrowserStore.getState();
82
+ expect(snapshot.isOpen).toBe(true);
83
+ expect(snapshot.tabs.find((tab) => tab.id === snapshot.activeTabId)).toMatchObject({ kind: "panel-app", resourceUri: "nextclaw://panel-app/example-notes" });
84
+ });
85
+ it("focuses an existing global tab without navigating the main conversation away", () => {
86
+ const page = getPresenter().pageResourceManager.resolve(
87
+ "nextclaw://panel-app/example-notes",
88
+ )!;
89
+ const tab = pageResourceTab(page);
90
+ useDocBrowserStore.setState({
91
+ snapshot: {
92
+ ...createDefaultDocBrowserState(),
93
+ isOpen: true,
94
+ tabs: [tab],
95
+ activeTabId: tab.id,
96
+ },
97
+ });
98
+ setup();
99
+ fireEvent.click(screen.getByRole("link", { name: "Notes" }));
100
+ expect(screen.getByTestId("route").textContent).toBe("/chat");
101
+ expect(useDocBrowserStore.getState().snapshot.tabs).toHaveLength(1);
102
+ expect(useDocBrowserStore.getState().snapshot.isOpen).toBe(true);
103
+ });
104
+ });
@@ -1,3 +1,5 @@
1
+ import { useWorkbenchSurfaceStore } from '@/shared/components/workbench/stores/workbench-surface.store';
2
+ import { GLOBAL_WORKBENCH_SURFACE } from '@/shared/components/workbench/types/workbench-surface.types';
1
3
  import { createContext, useContext, useMemo, type ReactNode } from 'react';
2
4
  import type { DocBrowserManager } from '@/shared/components/doc-browser/managers/doc-browser.manager';
3
5
  import { useDocBrowserStore } from '@/shared/components/doc-browser/stores/doc-browser.store';
@@ -44,6 +46,7 @@ export function DocBrowserProvider({
44
46
  children: ReactNode;
45
47
  manager: DocBrowserManager;
46
48
  }) {
49
+ const mode = useWorkbenchSurfaceStore((state) => state.surfaces[GLOBAL_WORKBENCH_SURFACE]?.placement ?? 'docked');
47
50
  const snapshot = useDocBrowserStore((state) => state.snapshot);
48
51
  const currentTab = useMemo(() => {
49
52
  return snapshot.tabs.find((tab) => tab.id === snapshot.activeTabId) ?? snapshot.tabs[0];
@@ -51,6 +54,7 @@ export function DocBrowserProvider({
51
54
 
52
55
  const value = useMemo<DocBrowserContextValue>(() => ({
53
56
  ...snapshot,
57
+ mode,
54
58
  currentTab,
55
59
  open: manager.open,
56
60
  openTarget: manager.openTarget,
@@ -64,7 +68,7 @@ export function DocBrowserProvider({
64
68
  goForward: manager.goForward,
65
69
  closeTab: manager.closeTab,
66
70
  setActiveTab: manager.setActiveTab,
67
- }), [currentTab, manager, snapshot]);
71
+ }), [currentTab, manager, snapshot, mode]);
68
72
 
69
73
  return (
70
74
  <DocBrowserContext.Provider value={value}>
@@ -92,7 +92,7 @@ export function DocBrowserFrameContent({
92
92
  name={createUiContentParamsWindowName(currentTab?.contentParams)}
93
93
  className="absolute inset-0 w-full h-full border-0"
94
94
  title={currentTab?.title || 'NextClaw Docs'}
95
- sandbox={iframeSandbox}
95
+ sandbox={iframeSandbox ?? (currentTab?.kind === 'content' ? undefined : 'allow-same-origin allow-scripts allow-popups allow-forms')}
96
96
  tabIndex={onIframePointerOver ? 0 : undefined}
97
97
  onLoad={onIframeLoad}
98
98
  onPointerOver={onIframePointerOver}