@nextclaw/ui 0.26.5 → 0.27.1

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 (433) hide show
  1. package/CHANGELOG.md +82 -0
  2. package/dist/.vite/manifest.json +1342 -1227
  3. package/dist/assets/{abnfDiagram-VRR7QNED-Dcw10Yt1.js → abnfDiagram-VRR7QNED-BT0_ycaq.js} +1 -1
  4. package/dist/assets/account-panel-BVNV8XqM.js +1 -0
  5. package/dist/assets/agents-CfpN8PQc.js +1 -0
  6. package/dist/assets/agents-E4nu-17c.js +1 -0
  7. package/dist/assets/{aiden0z-pptx-renderer.es--oNqetPA.js → aiden0z-pptx-renderer.es-ClCaf_Wh.js} +1 -1
  8. package/dist/assets/api-CI6_8Qt1.js +20 -0
  9. package/dist/assets/app-presenter-provider-2DwHRRle.js +28 -0
  10. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  11. package/dist/assets/appearance-settings-page-Cn9w3F-K.js +1 -0
  12. package/dist/assets/apps-YFlJirpx.js +1 -0
  13. package/dist/assets/{arc-DBRedCax.js → arc-cmSdpq1Z.js} +1 -1
  14. package/dist/assets/architecture-TIHT7OUA-BImoGh10.js +1 -0
  15. package/dist/assets/{architectureDiagram-ZJ3FMSHR-Dufhtuv-.js → architectureDiagram-ZJ3FMSHR-aYglVeoS.js} +1 -1
  16. package/dist/assets/{blockDiagram-677ZJIJ3-BUk0vtJ7.js → blockDiagram-677ZJIJ3-Di_PBl5q.js} +1 -1
  17. package/dist/assets/{book-open-Bcnn2_uV.js → book-open-i_BjUBqL.js} +1 -1
  18. package/dist/assets/{c4Diagram-LMCZKHZV-CxDcVE9p.js → c4Diagram-LMCZKHZV-CfuxybOL.js} +1 -1
  19. package/dist/assets/{card-Cqs73hGI.js → card-DokH7OBp.js} +1 -1
  20. package/dist/assets/channel-BDQry0ob.js +1 -0
  21. package/dist/assets/channels-list-page-B7G9lHUm.js +8 -0
  22. package/dist/assets/chunk-2Q5K7J3B-DkgSFfIy.js +1 -0
  23. package/dist/assets/{chunk-32BRIVSS-DSF3KElA.js → chunk-32BRIVSS-CCGc4qg4.js} +1 -1
  24. package/dist/assets/{chunk-52WLFC77-Costxzr3.js → chunk-52WLFC77-aJoxU2Ow.js} +1 -1
  25. package/dist/assets/{chunk-5FCAYU7R-rhqzGGZo.js → chunk-5FCAYU7R-CGwtZSax.js} +1 -1
  26. package/dist/assets/{chunk-5HE753X5-BsEsmIao.js → chunk-5HE753X5-DqaMSMeS.js} +1 -1
  27. package/dist/assets/{chunk-5JV3BV7I-Dqw_DCoN.js → chunk-5JV3BV7I-DnabINcd.js} +1 -1
  28. package/dist/assets/{chunk-5TONJI2A-Cft82fp8.js → chunk-5TONJI2A-BhpKv1k2.js} +1 -1
  29. package/dist/assets/{chunk-5VM5RSS4-DqNHn9Dl.js → chunk-5VM5RSS4-DvkRPit_.js} +1 -1
  30. package/dist/assets/{chunk-7BUUIJ7U-A5SBEMYY.js → chunk-7BUUIJ7U-CgDQOLnC.js} +1 -1
  31. package/dist/assets/{chunk-BIQX33UG-1Ng3mTrH.js → chunk-BIQX33UG-9FEv5b7T.js} +1 -1
  32. package/dist/assets/{chunk-C7G6YPKG-DRJEy8ZI.js → chunk-C7G6YPKG-CNGFAFYL.js} +1 -1
  33. package/dist/assets/{chunk-CQNSW5MT-Bydv_J3J.js → chunk-CQNSW5MT-DovTZx0M.js} +1 -1
  34. package/dist/assets/{chunk-CYSBUYHQ-HkMIg12u.js → chunk-CYSBUYHQ-DpLEgYa1.js} +1 -1
  35. package/dist/assets/{chunk-EMLP6XTP-C5ndDvm3.js → chunk-EMLP6XTP-D4NuN01W.js} +1 -1
  36. package/dist/assets/{chunk-EX3LRPZG-DzeloZRo.js → chunk-EX3LRPZG-D8Jf4kc2.js} +1 -1
  37. package/dist/assets/{chunk-FWX5IMBZ-n_2_CLTQ.js → chunk-FWX5IMBZ-BdHymAs0.js} +2 -2
  38. package/dist/assets/{chunk-HOUHSVGY-kx_slvu3.js → chunk-HOUHSVGY-Dd_Ycn9Z.js} +1 -1
  39. package/dist/assets/{chunk-ICXQ74PX-sQLMURqL.js → chunk-ICXQ74PX-BRPUu3ff.js} +1 -1
  40. package/dist/assets/{chunk-JG7HCLWE-CMUn5Elc.js → chunk-JG7HCLWE-DnCasQja.js} +1 -1
  41. package/dist/assets/{chunk-JWPE2WC7-Cra3s-Uk.js → chunk-JWPE2WC7-C3CkbEj1.js} +1 -1
  42. package/dist/assets/{chunk-MOJQB5TN-umcrg5Bi.js → chunk-MOJQB5TN-Pi--K4-1.js} +1 -1
  43. package/dist/assets/{chunk-MOZMSUNE-BnljD1ig.js → chunk-MOZMSUNE-3VTspvlh.js} +1 -1
  44. package/dist/assets/{chunk-OGEWGWER-BXx5pQjU.js → chunk-OGEWGWER-BetLLyJt.js} +1 -1
  45. package/dist/assets/{chunk-OSBZ3O6U-D-1qfdWu.js → chunk-OSBZ3O6U-D1VcupAj.js} +1 -1
  46. package/dist/assets/{chunk-PUDLZKDR-DLzX78LC.js → chunk-PUDLZKDR-Cy4G8SjV.js} +1 -1
  47. package/dist/assets/{chunk-Q4XR5HBZ-DTK-rtW6.js → chunk-Q4XR5HBZ-UYxXzi7_.js} +1 -1
  48. package/dist/assets/{chunk-QBLGF6JB-CsFeIGfr.js → chunk-QBLGF6JB-CHiGeRY1.js} +1 -1
  49. package/dist/assets/{chunk-R7FJI6CG-4xNYUeng.js → chunk-R7FJI6CG-C5kVJus8.js} +1 -1
  50. package/dist/assets/{chunk-RYQCIY6F-DJiHiTE5.js → chunk-RYQCIY6F-C6cuuEBn.js} +1 -1
  51. package/dist/assets/{chunk-U6XO7XAA-BVYkauHz.js → chunk-U6XO7XAA-CM0EK7Y0.js} +1 -1
  52. package/dist/assets/{chunk-V7JOEXUC-BsazE8cS.js → chunk-V7JOEXUC-DWJZIsME.js} +1 -1
  53. package/dist/assets/chunk-VAUOI2AC-CsTIB8qD.js +1 -0
  54. package/dist/assets/{chunk-VR4S4FIN-7RoZQffO.js → chunk-VR4S4FIN-CY5KYeEi.js} +1 -1
  55. package/dist/assets/{chunk-WYO6CB5R-DEuS6N1R.js → chunk-WYO6CB5R-B30N3ZP8.js} +3 -3
  56. package/dist/assets/chunk-XXDRQBXY-DK6dz0Q3.js +1 -0
  57. package/dist/assets/{chunk-YOTPTUD7-9KBrosZL.js → chunk-YOTPTUD7-CBu82JpO.js} +1 -1
  58. package/dist/assets/{chunk-ZGVPDNZ5-IYgN9f5A.js → chunk-ZGVPDNZ5-BN5NX5qA.js} +1 -1
  59. package/dist/assets/{chunk-ZIRB5QZD-BUo0-zcp.js → chunk-ZIRB5QZD-DcDXK29L.js} +1 -1
  60. package/dist/assets/{circle-dashed-EY1ScSMe.js → circle-dashed-Cx8CIEbg.js} +1 -1
  61. package/dist/assets/classDiagram-OUVF2IWQ-BYygHCrp.js +1 -0
  62. package/dist/assets/classDiagram-v2-EOCWNBFH-BgQ0XKYz.js +1 -0
  63. package/dist/assets/{client-CH7w6yRV.js → client-CUJUci3r.js} +1 -1
  64. package/dist/assets/config-split-page-hY1xug28.js +1 -0
  65. package/dist/assets/confirm-dialog-B-ejV666.js +1 -0
  66. package/dist/assets/{app-presenter-provider-jNGlmBLe.css → context-menu-DEcVZfaU.css} +1 -1
  67. package/dist/assets/context-menu-dGVv8klA.js +211 -0
  68. package/dist/assets/{cose-bilkent-JH36ORCC-DhqbC1fR.js → cose-bilkent-JH36ORCC-CmeJVoTw.js} +1 -1
  69. package/dist/assets/{createLucideIcon-Cfo2ySi5.js → createLucideIcon-reFMl-W-.js} +1 -1
  70. package/dist/assets/cron-CH5c55CR.js +1 -0
  71. package/dist/assets/cynefin-VYW2F7L2-DKbotNWS.js +1 -0
  72. package/dist/assets/{cynefinDiagram-TSTJHNR4-C-TBRi5V.js → cynefinDiagram-TSTJHNR4-DGOUMgPP.js} +1 -1
  73. package/dist/assets/{dagre-CrgsRasE.js → dagre-CMxSkbJJ.js} +1 -1
  74. package/dist/assets/{dagre-VKFMJZFB-BmafJymp.js → dagre-VKFMJZFB-3YUBEXwo.js} +1 -1
  75. package/dist/assets/{desktop-capabilities-page-BDYITStl.js → desktop-capabilities-page-CYJTQ3nC.js} +1 -1
  76. package/dist/assets/desktop-update-config-guKAozXO.js +1 -0
  77. package/dist/assets/{diagram-FQU43EPY-BoOMwa6D.js → diagram-FQU43EPY-Br1g--ww.js} +1 -1
  78. package/dist/assets/{diagram-G47NLZAW-Le7N6Uym.js → diagram-G47NLZAW-D1wJCBgr.js} +1 -1
  79. package/dist/assets/{diagram-NH7WQ7WH-Fbpj3-MO.js → diagram-NH7WQ7WH-Cgg2auLH.js} +1 -1
  80. package/dist/assets/{diagram-OA4YK3LP-D3QuGGuu.js → diagram-OA4YK3LP-R-wHiWqh.js} +1 -1
  81. package/dist/assets/{diagram-WEI45ONY-Cxu1uiN6.js → diagram-WEI45ONY-CsNnKV0P.js} +1 -1
  82. package/dist/assets/dialog-DLOwdjT1.js +1 -0
  83. package/dist/assets/dist-ZaFFmAGl.js +41 -0
  84. package/dist/assets/doc-browser-ClDUWo9V.js +1 -0
  85. package/dist/assets/doc-browser-context-CTmOmuqa.js +1 -0
  86. package/dist/assets/{docx-preview-CkU2psnd.js → docx-preview-kPn_EtAr.js} +1 -1
  87. package/dist/assets/{download-BoaKzDJk.js → download-DovI3Yvf.js} +1 -1
  88. package/dist/assets/{ebnfDiagram-CCIWWBDH-CCAjuQM6.js → ebnfDiagram-CCIWWBDH-DCyhIPdi.js} +1 -1
  89. package/dist/assets/{erDiagram-Q63AITRT-BuzUAq-d.js → erDiagram-Q63AITRT-D0ZJYAUf.js} +1 -1
  90. package/dist/assets/eventmodeling-45OFAUF4-SIhbIFIw.js +1 -0
  91. package/dist/assets/extensions-BZ3qrM8M.js +1 -0
  92. package/dist/assets/external-link-DUD3AbsF.js +1 -0
  93. package/dist/assets/flowDiagram-23GEKE2U-DdAjkU7I.js +1 -0
  94. package/dist/assets/{form-actions-D9JWSFQu.js → form-actions-B8VniHts.js} +1 -1
  95. package/dist/assets/{ganttDiagram-NO4QXBWP-cJmWVY8F.js → ganttDiagram-NO4QXBWP-CiXDcXZD.js} +1 -1
  96. package/dist/assets/gitGraph-TEB2WS4Q-DnMNpESZ.js +1 -0
  97. package/dist/assets/{gitGraphDiagram-IHSO6WYX-F58o-vtP.js → gitGraphDiagram-IHSO6WYX-BSiIV48S.js} +1 -1
  98. package/dist/assets/{i18n-Bm3Ov7Fy.js → i18n-IGQbjBqS.js} +2 -2
  99. package/dist/assets/inbox-BjBZIbgx.js +1 -0
  100. package/dist/assets/inbox-ClAG7SI_.js +1 -0
  101. package/dist/assets/info-DKCQHKI2-BSm-69p_.js +1 -0
  102. package/dist/assets/{infoDiagram-FWYZ7A6U-Gt59b83C.js → infoDiagram-FWYZ7A6U-CCIgBCVq.js} +1 -1
  103. package/dist/assets/{ishikawaDiagram-FXEZZL3T-1u4IAj1I.js → ishikawaDiagram-FXEZZL3T-nQ_baN5u.js} +1 -1
  104. package/dist/assets/{journeyDiagram-5HDEW3XC-CCQsfV-5.js → journeyDiagram-5HDEW3XC-ABueIPzj.js} +1 -1
  105. package/dist/assets/{kanban-definition-HUTT4EX6-vlB6O_Zn.js → kanban-definition-HUTT4EX6-8FKS3fmQ.js} +1 -1
  106. package/dist/assets/katex-DPgHtix3.js +1 -0
  107. package/dist/assets/keyboard-shortcuts-settings-page-BqfbbKir.js +1 -0
  108. package/dist/assets/{line-D_bHubTL.js → line-Biw8iEUz.js} +1 -1
  109. package/dist/assets/{linear-ChlwuS5y.js → linear-D7CWUHTF.js} +1 -1
  110. package/dist/assets/login-page-BxSMwUsc.js +1 -0
  111. package/dist/assets/{login-page-C-DvcG3L.js → login-page-DYaozpzz.js} +1 -1
  112. package/dist/assets/main-CWYF9QU_.js +2 -0
  113. package/dist/assets/main-D_zmSVS1.css +1 -0
  114. package/dist/assets/main-i18n-catalog.config-itg3Gvzp.js +1 -0
  115. package/dist/assets/{map-oGHTsIu8.js → map-CDu47gTf.js} +1 -1
  116. package/dist/assets/marketplace-CnQ5USfr.js +1 -0
  117. package/dist/assets/mcp-marketplace-page-Dor6H9IC.js +1 -0
  118. package/dist/assets/{mermaid-parser.core-CuRe1ZG4.js → mermaid-parser.core-Cc9wjl82.js} +2 -2
  119. package/dist/assets/{mermaid.core-u4YCFKRf.js → mermaid.core-GWlaVWz1.js} +3 -3
  120. package/dist/assets/{mindmap-definition-LN4V7U3C-DeJAQYTu.js → mindmap-definition-LN4V7U3C-oqnKsz-R.js} +1 -1
  121. package/dist/assets/model-config-page-Cduyz2Hy.js +1 -0
  122. package/dist/assets/{navigation-link-CjxNC8aT.js → navigation-link-D-JSWFxj.js} +2 -2
  123. package/dist/assets/{ordinal-C6JFfkKN.js → ordinal-DImbxqBz.js} +1 -1
  124. package/dist/assets/packet-7NZHBO7P-1YQvC6mT.js +1 -0
  125. package/dist/assets/panel-app-BBTg0tVp.js +1 -0
  126. package/dist/assets/panel-app-i18n-catalog.config-BfLHr1tc.js +1 -0
  127. package/dist/assets/panel-apps-C-izvtu9.js +1 -0
  128. package/dist/assets/panelStandalone-XRlWxbRS.css +1 -0
  129. package/dist/assets/panelStandalone-oHxbXvYt.js +2 -0
  130. package/dist/assets/{pegDiagram-2B236MQR-nVMkxShH.js → pegDiagram-2B236MQR-DYAB8CEz.js} +1 -1
  131. package/dist/assets/pie-RZYD4A2V-BGoNOSwu.js +1 -0
  132. package/dist/assets/{pieDiagram-ENE6RG2P-8aUH44QZ.js → pieDiagram-ENE6RG2P-DGsH0Kk5.js} +1 -1
  133. package/dist/assets/plus-DUdl68Eo.js +1 -0
  134. package/dist/assets/privacy-settings-page-DG9E8N-F.js +1 -0
  135. package/dist/assets/projects-CzBaTOTL.js +1 -0
  136. package/dist/assets/provider-models-COzjYl29.js +1 -0
  137. package/dist/assets/provider-scoped-model-input-Cvy74uj8.js +1 -0
  138. package/dist/assets/providers-config-page-7rCwVnhh.js +1 -0
  139. package/dist/assets/puzzle-C5Wfpjk_.js +1 -0
  140. package/dist/assets/pwa-CAg_9zFs.js +1 -0
  141. package/dist/assets/{quadrantDiagram-ABIIQ3AL-EY8hpFv8.js → quadrantDiagram-ABIIQ3AL-BegGcT3l.js} +1 -1
  142. package/dist/assets/radar-I7S5WNFK-uPku9RRq.js +1 -0
  143. package/dist/assets/railroad-3IZDKUUU-DHnmbuIo.js +1 -0
  144. package/dist/assets/railroad-abnf-AHOZXSZD-DiZs--Iw.js +1 -0
  145. package/dist/assets/railroad-ebnf-EBAXGLYW-Nr53gnNE.js +1 -0
  146. package/dist/assets/railroad-peg-LSFZ7HO6-Cm_PuwJS.js +1 -0
  147. package/dist/assets/{railroadDiagram-RFXS5EU6-CNhcIeji.js → railroadDiagram-RFXS5EU6-B3yJ2yxE.js} +1 -1
  148. package/dist/assets/{refresh-cw-BlXDrVP0.js → refresh-cw-OhwaPDn1.js} +1 -1
  149. package/dist/assets/remote-DvCdHjzA.js +1 -0
  150. package/dist/assets/{requirementDiagram-TGXJPOKE-D8Dcs-Rt.js → requirementDiagram-TGXJPOKE-DtEyoEXG.js} +1 -1
  151. package/dist/assets/{rotate-cw-ei6rPD6z.js → rotate-cw-aBponvp7.js} +1 -1
  152. package/dist/assets/runtime-config-page-BF1wxvzR.js +1 -0
  153. package/dist/assets/{sankeyDiagram-HTMAVEWB-HTrb6aa-.js → sankeyDiagram-HTMAVEWB-h9AYS2UB.js} +1 -1
  154. package/dist/assets/{save-DdF-bXgC.js → save-394QCMXn.js} +1 -1
  155. package/dist/assets/search-BG2qAlNZ.js +1 -0
  156. package/dist/assets/search-config-page-D4LeiB9y.js +1 -0
  157. package/dist/assets/secrets-config-page-BzGcr5Vw.js +3 -0
  158. package/dist/assets/security-config-vD_V0BQF.js +1 -0
  159. package/dist/assets/select-xUXYV0Gr.js +1 -0
  160. package/dist/assets/{sequenceDiagram-DBY2YBRQ-6f_4X16Y.js → sequenceDiagram-DBY2YBRQ-D-uxCkob.js} +1 -1
  161. package/dist/assets/service-apps-panel-D3wwPRzV.js +1 -0
  162. package/dist/assets/{settings-2-CrNhfInU.js → settings-2-CWOGRRaA.js} +1 -1
  163. package/dist/assets/{sizeCapture-X5ZJPWSS-Ck9rsuwL.js → sizeCapture-X5ZJPWSS-DBzZytQo.js} +1 -1
  164. package/dist/assets/{src-C8AUg09O.js → src-zrGbZsfc.js} +1 -1
  165. package/dist/assets/{stateDiagram-2N3HPSRC-Cm33MLHu.js → stateDiagram-2N3HPSRC-DyDy7AHq.js} +1 -1
  166. package/dist/assets/stateDiagram-v2-6OUMAXLB-CtkpO6aA.js +1 -0
  167. package/dist/assets/{status-dot-C3SRFEta.js → status-dot-CYifnSnt.js} +1 -1
  168. package/dist/assets/{swimlanes-5IMT3BWC-B107vmvM.js → swimlanes-5IMT3BWC-BzOduS38.js} +2 -2
  169. package/dist/assets/swimlanesDiagram-G3AALYLV-BSdi6mvi.js +8 -0
  170. package/dist/assets/tag-chip-CjM6lyeh.js +1 -0
  171. package/dist/assets/theme-provider-BToFZGZG.js +1 -0
  172. package/dist/assets/{timeline-definition-FHXFAJF6-CJEoAj33.js → timeline-definition-FHXFAJF6-CmgnEF2t.js} +1 -1
  173. package/dist/assets/trash-2-DvJ6duOW.js +1 -0
  174. package/dist/assets/treeView-QDETBFTQ-DBoqypPR.js +1 -0
  175. package/dist/assets/treemap-6X3UGDF4-BMeL3P0q.js +1 -0
  176. package/dist/assets/use-config-COusaY5p.js +1 -0
  177. package/dist/assets/{use-desktop-capabilities-BYDjFlpt.js → use-desktop-capabilities-B-u6ojjW.js} +1 -1
  178. package/dist/assets/use-viewport-layout-IKKGpjzF.js +1 -0
  179. package/dist/assets/{vennDiagram-L72KCM5P-DzsUHk5I.js → vennDiagram-L72KCM5P-DwS7D2kg.js} +1 -1
  180. package/dist/assets/wardley-OPB4EBWU-Dqxe7zN6.js +1 -0
  181. package/dist/assets/{wardleyDiagram-EHGQE667-1NfFs5ua.js → wardleyDiagram-EHGQE667-B4X8OOL4.js} +1 -1
  182. package/dist/assets/x-E9VB4HQx.js +1 -0
  183. package/dist/assets/{xychartDiagram-FW5EYKEG-Ci8AI3Qo.js → xychartDiagram-FW5EYKEG-BjRQ_0nx.js} +1 -1
  184. package/dist/index.html +44 -106
  185. package/dist/panel-standalone.html +19 -13
  186. package/index.html +15 -66
  187. package/package.json +5 -5
  188. package/src/app/styles/design-system.css +85 -1
  189. package/src/app/styles/island-theme.css +8 -6
  190. package/src/features/agents/components/__tests__/agents-page.test.tsx +8 -5
  191. package/src/features/agents/components/agent-details-dialog.tsx +24 -18
  192. package/src/features/agents/components/agents-page.tsx +27 -38
  193. package/src/features/app-data/components/app-retained-data-section.tsx +4 -4
  194. package/src/features/apps/components/__tests__/app-marketplace-catalog.test.tsx +2 -2
  195. package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +94 -23
  196. package/src/features/apps/components/__tests__/apps-panel.test.tsx +5 -3
  197. package/src/features/apps/components/app-document-access-section.tsx +17 -14
  198. package/src/features/apps/components/app-marketplace-catalog.tsx +69 -42
  199. package/src/features/apps/components/app-marketplace-cover.tsx +5 -2
  200. package/src/features/apps/components/app-marketplace-detail.tsx +20 -8
  201. package/src/features/apps/components/app-marketplace-operation.tsx +8 -3
  202. package/src/features/apps/components/app-marketplace-panel.tsx +168 -0
  203. package/src/features/apps/components/app-package-card.tsx +224 -147
  204. package/src/features/apps/components/app-package-details-dialog.tsx +103 -0
  205. package/src/features/apps/components/app-packages-panel.tsx +162 -147
  206. package/src/features/apps/components/apps-panel.tsx +43 -12
  207. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -1
  208. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  209. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +2 -2
  210. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +9 -7
  211. package/src/features/chat/components/providers/chat-runtime.provider.tsx +1 -1
  212. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +0 -1
  213. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +13 -2
  214. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +2 -3
  215. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +9 -1
  216. package/src/features/chat/features/conversation/components/session-conversation-input-top-slot.tsx +44 -0
  217. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +4 -38
  218. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-controller.test.tsx +86 -10
  219. package/src/features/chat/features/conversation/hooks/__tests__/use-session-conversation-input-state.test.tsx +44 -1
  220. package/src/features/chat/features/conversation/hooks/use-session-conversation-controller.ts +85 -73
  221. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-query.ts +5 -15
  222. package/src/features/chat/features/conversation/hooks/use-session-conversation-input-state.ts +53 -13
  223. package/src/features/chat/features/conversation/hooks/use-session-submission-recovery.ts +83 -0
  224. package/src/features/chat/features/conversation/types/session-conversation-input.types.ts +38 -0
  225. package/src/features/chat/features/input/utils/__tests__/ncp-chat-input-availability.utils.test.ts +1 -29
  226. package/src/features/chat/features/input/utils/ncp-chat-input-availability.utils.ts +1 -8
  227. package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +14 -1
  228. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -2
  229. package/src/features/chat/features/message/utils/chat-message-execution-summary.utils.ts +3 -0
  230. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +1 -0
  231. package/src/features/chat/features/message/utils/chat-message-trigger-details.utils.ts +3 -0
  232. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +1 -1
  233. package/src/features/chat/features/session/components/session-header/chat-session-metadata-dialog.tsx +1 -1
  234. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +2 -2
  235. package/src/features/chat/features/session/utils/__tests__/chat-session-route.utils.test.ts +26 -0
  236. package/src/features/chat/features/session/utils/chat-session-preference-governance.utils.ts +14 -8
  237. package/src/features/chat/features/session/utils/chat-session-route.utils.ts +9 -12
  238. package/src/features/chat/features/welcome/components/__tests__/chat-welcome.test.tsx +31 -6
  239. package/src/features/chat/features/welcome/components/chat-conversation-welcome.tsx +13 -1
  240. package/src/features/chat/features/welcome/components/chat-welcome-agent-picker.tsx +1 -1
  241. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +1 -1
  242. package/src/features/chat/features/welcome/components/chat-welcome-prompt-suggestions.tsx +56 -13
  243. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +3 -3
  244. package/src/features/chat/features/welcome/components/chat-welcome.tsx +14 -4
  245. package/src/features/chat/features/welcome/utils/__tests__/chat-welcome-continuation.utils.test.ts +40 -0
  246. package/src/features/chat/features/welcome/utils/chat-welcome-continuation.utils.ts +21 -0
  247. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.selection.test.tsx +14 -2
  248. package/src/features/chat/features/workspace/components/__tests__/session-cron-job-content.test.tsx +5 -1
  249. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +1 -1
  250. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +3 -7
  251. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +6 -5
  252. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +27 -27
  253. package/src/features/chat/features/workspace/components/overview/chat-session-continuous-attention.tsx +11 -11
  254. package/src/features/chat/features/workspace/components/overview/chat-session-token-usage.tsx +15 -15
  255. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  256. package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +1 -1
  257. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  258. package/src/features/chat/features/workspace/components/session-cron-job-content.tsx +13 -26
  259. package/src/features/chat/index.ts +1 -0
  260. package/src/features/chat/pages/__tests__/ncp-chat-page.test.ts +37 -47
  261. package/src/features/chat/pages/ncp-chat-page.tsx +3 -3
  262. package/src/features/chat/stores/__tests__/chat-composer-draft.store.test.ts +67 -1
  263. package/src/features/chat/stores/chat-composer-draft.store.ts +230 -29
  264. package/src/features/cron/components/__tests__/cron-config.test.tsx +8 -2
  265. package/src/features/cron/components/cron-config.tsx +6 -17
  266. package/src/features/cron/components/cron-job-detail-dialog.tsx +10 -9
  267. package/src/features/cron/components/cron-job-resource.tsx +51 -0
  268. package/src/features/cron/components/cron-job-row.tsx +5 -4
  269. package/src/features/cron/index.ts +1 -0
  270. package/src/features/desktop-capabilities/components/desktop-authorization-dialog.tsx +5 -5
  271. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +46 -6
  272. package/src/features/inbox/components/inbox-reader-dialog.tsx +38 -29
  273. package/src/features/inbox/managers/inbox.manager.test.ts +28 -0
  274. package/src/features/inbox/managers/inbox.manager.ts +18 -4
  275. package/src/features/inbox/pages/inbox-page.test.ts +4 -2
  276. package/src/features/inbox/pages/inbox-page.tsx +14 -10
  277. package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +1 -0
  278. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +1 -0
  279. package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
  280. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +2 -2
  281. package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +23 -1
  282. package/src/features/marketplace/hooks/use-marketplace-item-detail.ts +11 -0
  283. package/src/features/panel-apps/components/panel-app-list-item.tsx +4 -3
  284. package/src/features/panel-apps/components/panel-app-service-action-authorization-dialog.tsx +2 -2
  285. package/src/features/panel-apps/index.ts +1 -0
  286. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +5 -24
  287. package/src/features/projects/components/work/project-work-item-drawer.tsx +7 -10
  288. package/src/features/projects/components/work/project-work-items.tsx +1 -1
  289. package/src/features/projects/pages/project-home-page.tsx +18 -23
  290. package/src/features/projects/pages/projects-page.test.tsx +4 -1
  291. package/src/features/pwa/managers/__tests__/pwa-shell-theme.manager.test.ts +3 -3
  292. package/src/features/pwa/managers/pwa-shell-theme.manager.ts +8 -3
  293. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +13 -2
  294. package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +74 -6
  295. package/src/features/right-panel-resources/components/native-object-resource.tsx +134 -0
  296. package/src/features/right-panel-resources/components/page-resource-icon.tsx +16 -8
  297. package/src/features/right-panel-resources/components/system-object-resource.tsx +66 -1
  298. package/src/features/right-panel-resources/components/workspace-file-resource.tsx +9 -0
  299. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +11 -21
  300. package/src/features/right-panel-resources/index.ts +3 -0
  301. package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +14 -4
  302. package/src/features/right-panel-resources/managers/page-resource.manager.ts +38 -21
  303. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +17 -0
  304. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +3 -2
  305. package/src/features/service-apps/components/service-action-row.tsx +4 -3
  306. package/src/features/service-apps/components/service-app-delete-dialog.tsx +2 -2
  307. package/src/features/service-apps/components/service-app-list-item.tsx +5 -4
  308. package/src/features/service-apps/components/service-apps-panel.tsx +5 -2
  309. package/src/features/settings/components/config/provider-model-suggestions-panel.tsx +1 -1
  310. package/src/features/settings/pages/providers-config-page.tsx +3 -2
  311. package/src/index.css +42 -8
  312. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +16 -0
  313. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +2 -2
  314. package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +29 -1
  315. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +2 -2
  316. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +13 -7
  317. package/src/shared/components/doc-browser/utils/doc-browser-url.utils.ts +2 -1
  318. package/src/shared/components/path-picker/server-path-picker-dialog.tsx +5 -3
  319. package/src/shared/components/ui/__tests__/dialog.test.tsx +37 -1
  320. package/src/shared/components/ui/actions/action-feedback.ts +1 -8
  321. package/src/shared/components/ui/actions/icon-action-button.tsx +1 -1
  322. package/src/shared/components/ui/confirm-dialog.tsx +1 -2
  323. package/src/shared/components/ui/context-menu/context-menu-items.tsx +2 -2
  324. package/src/shared/components/ui/dialog.tsx +29 -7
  325. package/src/shared/components/ui/popover.tsx +14 -3
  326. package/src/shared/components/ui/skeleton.tsx +16 -2
  327. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +2 -2
  328. package/src/shared/components/ui/tooltip.tsx +2 -1
  329. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +21 -0
  330. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +4 -0
  331. package/src/shared/components/workbench/workbench-surface.tsx +4 -1
  332. package/src/shared/lib/i18n/locales/en-US/chat.json +21 -7
  333. package/src/shared/lib/i18n/locales/en-US/core.json +5 -1
  334. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +10 -5
  335. package/src/shared/lib/i18n/locales/en-US/inbox.json +1 -0
  336. package/src/shared/lib/i18n/locales/zh-CN/chat.json +21 -7
  337. package/src/shared/lib/i18n/locales/zh-CN/core.json +5 -1
  338. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +11 -6
  339. package/src/shared/lib/i18n/locales/zh-CN/inbox.json +1 -0
  340. package/src/shared/lib/theme/index.test.ts +28 -1
  341. package/src/shared/lib/theme/index.ts +14 -3
  342. package/src/shared/lib/transport/__tests__/local-transport.service.test.ts +24 -0
  343. package/src/shared/lib/transport/local-transport.service.ts +8 -6
  344. package/dist/assets/account-panel-BAH7FW6z.js +0 -1
  345. package/dist/assets/api-DjiZvIa0.js +0 -20
  346. package/dist/assets/app-presenter-provider-CCRFsFYr.js +0 -232
  347. package/dist/assets/appearance-settings-page-CdP86QJ7.js +0 -1
  348. package/dist/assets/architecture-TIHT7OUA-CvnC-LeA.js +0 -1
  349. package/dist/assets/channel-CpMstUPF.js +0 -1
  350. package/dist/assets/channels-list-page-5qGagKuE.js +0 -8
  351. package/dist/assets/chunk-2Q5K7J3B-Djp3VF0s.js +0 -1
  352. package/dist/assets/chunk-VAUOI2AC-BrbiIC1Q.js +0 -1
  353. package/dist/assets/chunk-XXDRQBXY-Cx9N40wF.js +0 -1
  354. package/dist/assets/classDiagram-OUVF2IWQ-DFN1v3PQ.js +0 -1
  355. package/dist/assets/classDiagram-v2-EOCWNBFH-DRvglADa.js +0 -1
  356. package/dist/assets/config-split-page-CuEGQL8Z.js +0 -1
  357. package/dist/assets/confirm-dialog-CxfecBzO.js +0 -1
  358. package/dist/assets/context-menu-BsCj2fRs.js +0 -1
  359. package/dist/assets/cynefin-VYW2F7L2-DXUGnpJH.js +0 -1
  360. package/dist/assets/desktop-update-config-e-zhkJuS.js +0 -1
  361. package/dist/assets/dialog-QjQoKbIV.js +0 -5
  362. package/dist/assets/doc-browser-CLEdkH9z.js +0 -1
  363. package/dist/assets/doc-browser-context-DwgG6wrz.js +0 -1
  364. package/dist/assets/es2015-Bp6cuSGh.js +0 -41
  365. package/dist/assets/eventmodeling-45OFAUF4-ZBfVS3ZC.js +0 -1
  366. package/dist/assets/extensions-CgShSIkd.js +0 -1
  367. package/dist/assets/eye-kisejBFH.js +0 -1
  368. package/dist/assets/flowDiagram-23GEKE2U-CqdsKk6x.js +0 -1
  369. package/dist/assets/gitGraph-TEB2WS4Q-fHYFd9Es.js +0 -1
  370. package/dist/assets/info-DKCQHKI2-CSaOL_bb.js +0 -1
  371. package/dist/assets/katex-B4FQSo9k.js +0 -1
  372. package/dist/assets/keyboard-shortcuts-settings-page-DZ8A1iLg.js +0 -1
  373. package/dist/assets/loader-circle-Bd1fTm-x.js +0 -1
  374. package/dist/assets/login-page-D99JjH9F.js +0 -1
  375. package/dist/assets/main-Bt5r6b21.js +0 -2
  376. package/dist/assets/main-DXd_aKJV.css +0 -1
  377. package/dist/assets/main-i18n-catalog.config-D0Ll36J_.js +0 -1
  378. package/dist/assets/mcp-marketplace-page-DUoGfSmY.js +0 -1
  379. package/dist/assets/model-config-page-9NNf-mzK.js +0 -1
  380. package/dist/assets/packet-7NZHBO7P-D-YFTczs.js +0 -1
  381. package/dist/assets/panel-app-BYfQu_TS.js +0 -1
  382. package/dist/assets/panel-app-i18n-catalog.config-Ddf2Kv8A.js +0 -1
  383. package/dist/assets/panelStandalone-BRg7B1EI.css +0 -1
  384. package/dist/assets/panelStandalone-BaUzY8Wy.js +0 -2
  385. package/dist/assets/pie-RZYD4A2V-VEnYu9s5.js +0 -1
  386. package/dist/assets/privacy-settings-page-CVMBFuak.js +0 -1
  387. package/dist/assets/projects-BEsU3box.js +0 -1
  388. package/dist/assets/provider-models-Dm-pmWAA.js +0 -1
  389. package/dist/assets/provider-scoped-model-input-CzrXg4cX.js +0 -1
  390. package/dist/assets/providers-config-page-839uUADZ.js +0 -1
  391. package/dist/assets/puzzle-BGvD2DPZ.js +0 -1
  392. package/dist/assets/pwa-DNNK_8E9.js +0 -1
  393. package/dist/assets/radar-I7S5WNFK-BFNIekC1.js +0 -1
  394. package/dist/assets/railroad-3IZDKUUU-lVqJ3Hak.js +0 -1
  395. package/dist/assets/railroad-abnf-AHOZXSZD-DYaefdFC.js +0 -1
  396. package/dist/assets/railroad-ebnf-EBAXGLYW-CTAk6lVq.js +0 -1
  397. package/dist/assets/railroad-peg-LSFZ7HO6-Cob294tg.js +0 -1
  398. package/dist/assets/remote-B5qIuUbT.js +0 -1
  399. package/dist/assets/runtime-config-page-Bf-4JYxQ.js +0 -1
  400. package/dist/assets/search-config-page-C0qA3j-T.js +0 -1
  401. package/dist/assets/secrets-config-page-DxfZWpnk.js +0 -3
  402. package/dist/assets/security-config-CItfIQZ4.js +0 -1
  403. package/dist/assets/select-CWyjnar7.js +0 -1
  404. package/dist/assets/service-apps-panel-D3SOkRVv.js +0 -1
  405. package/dist/assets/stateDiagram-v2-6OUMAXLB-BrNv-raG.js +0 -1
  406. package/dist/assets/swimlanesDiagram-G3AALYLV-ntcxaPXp.js +0 -8
  407. package/dist/assets/tag-chip-BIuavK2K.js +0 -1
  408. package/dist/assets/theme-provider-CWUz4yO9.js +0 -1
  409. package/dist/assets/trash-2-hAbJh9VZ.js +0 -1
  410. package/dist/assets/treeView-QDETBFTQ-DbFmr-gw.js +0 -1
  411. package/dist/assets/treemap-6X3UGDF4-C8aY96pi.js +0 -1
  412. package/dist/assets/use-config-evzage09.js +0 -1
  413. package/dist/assets/use-viewport-layout-D_9XWGDV.js +0 -1
  414. package/dist/assets/wardley-OPB4EBWU-D8d6DbbJ.js +0 -1
  415. package/dist/assets/x-ChPbNv39.js +0 -1
  416. package/src/features/apps/components/app-marketplace-dialog.tsx +0 -168
  417. /package/dist/assets/{array-BV9OtnO8.js → array-DsNX3jRj.js} +0 -0
  418. /package/dist/assets/{chunk-KEIR6QF5-Cx-8EJ4_.js → chunk-KEIR6QF5-BOAXXeyv.js} +0 -0
  419. /package/dist/assets/{chunk-Y2CYZVJY-Dy1ufvjf.js → chunk-Y2CYZVJY-CHjSjwoV.js} +0 -0
  420. /package/dist/assets/{config-hints-DbmiyTKg.js → config-hints-CaB3I7KP.js} +0 -0
  421. /package/dist/assets/{cytoscape.esm-CSCjuT4Z.js → cytoscape.esm-j4J9a91l.js} +0 -0
  422. /package/dist/assets/{defaultLocale-DWTiNsbT.js → defaultLocale-Bmxjp-V_.js} +0 -0
  423. /package/dist/assets/{dist-BVCSkfWY.js → dist-DwLj1Wg5.js} +0 -0
  424. /package/dist/assets/{graphlib-B1yb1Wl8.js → graphlib-CC0HTn1v.js} +0 -0
  425. /package/dist/assets/{host-capabilities-DuIFVsvM.js → host-capabilities-B107nwS3.js} +0 -0
  426. /package/dist/assets/{init-BF6GH5oe.js → init-Biz9Rus1.js} +0 -0
  427. /package/dist/assets/{jszip.min-D12teKzP.js → jszip.min-DQvBVV_R.js} +0 -0
  428. /package/dist/assets/{katex-CsAM73R9.js → katex-BzT-4KBu.js} +0 -0
  429. /package/dist/assets/{navigation-history-CzErJuPG.js → navigation-history-CCnxsAKR.js} +0 -0
  430. /package/dist/assets/{path-C56XkznJ.js → path-4azsBPZv.js} +0 -0
  431. /package/dist/assets/{preload-helper-ca-nBW7U.js → preload-helper-DWTEM3RW.js} +0 -0
  432. /package/dist/assets/{rough.esm-CGfeEbtE.js → rough.esm-w1lBArN6.js} +0 -0
  433. /package/dist/assets/{xlsx-sds5nUpL.js → xlsx--SB9KlFl.js} +0 -0
@@ -6,6 +6,7 @@ import { GLOBAL_WORKBENCH_SURFACE } from "@/shared/components/workbench/types/wo
6
6
  import { useChatThreadStore } from "@/features/chat";
7
7
  import type { ChatThreadManager } from "@/features/chat";
8
8
  import type { AppPresenter } from "@/app/presenters/app.presenter";
9
+ import type { WorkspaceTextExcerpt } from "@/features/chat";
9
10
  import { useDocBrowserStore } from "@/shared/components/doc-browser/stores/doc-browser.store";
10
11
  import { useFloatingSessionStore } from "@/features/chat";
11
12
  import { sessionSurfaceManager } from "@/features/chat";
@@ -61,29 +62,28 @@ export class PageResourceManager {
61
62
  };
62
63
 
63
64
  resolve = (
64
- uri: string,
65
+ rawUri: string,
65
66
  context?: { workingDir?: string | null; sessionKey?: string | null },
66
67
  ): PageResource | null => {
67
- if (!/^(nextclaw:\/\/|https?:\/\/)/i.test(uri)) return null;
68
- if (uri.startsWith("nextclaw://file/")) {
69
- try {
68
+ if (!/^(nextclaw:\/\/|https?:\/\/)/i.test(rawUri)) return null;
69
+ try {
70
+ const uri = this.app.rightPanelResourceRouteResolver.normalize(rawUri);
71
+ if (uri.startsWith("nextclaw://file/")) {
70
72
  const target = resolveFileResourceTarget(uri, context);
71
73
  return target ? pageResourceFromTarget(target) : null;
72
- } catch {
73
- return null;
74
74
  }
75
- }
76
- const saved =
77
- this.remembered.get(uri) ??
78
- usePageNavigationStore.getState().pinned.find((page) => page.uri === uri);
79
- if (saved) return saved;
80
- const tab = useDocBrowserStore
81
- .getState()
82
- .snapshot.tabs.find(
83
- (item) => (item.resourceUri ?? item.currentUrl) === uri,
84
- );
85
- if (tab) return pageResourceFromTab(tab);
86
- try {
75
+ const saved =
76
+ this.remembered.get(uri) ??
77
+ usePageNavigationStore
78
+ .getState()
79
+ .pinned.find((page) => page.uri === uri);
80
+ if (saved) return saved;
81
+ const tab = useDocBrowserStore
82
+ .getState()
83
+ .snapshot.tabs.find(
84
+ (item) => (item.resourceUri ?? item.currentUrl) === uri,
85
+ );
86
+ if (tab) return pageResourceFromTab(tab);
87
87
  if (uri.startsWith("nextclaw://page?")) {
88
88
  const path = new URL(uri).searchParams.get("path");
89
89
  if (
@@ -190,7 +190,9 @@ export class PageResourceManager {
190
190
  location === "floating" ? "floating" : "docked",
191
191
  );
192
192
  if (location === "main")
193
- this.app.workbenchSurfaceManager.toggleMaximize(`session-workspace:${parent ?? "draft"}`);
193
+ this.app.workbenchSurfaceManager.toggleMaximize(
194
+ `session-workspace:${parent ?? "draft"}`,
195
+ );
194
196
  return;
195
197
  }
196
198
  const sessionKey = parseSessionKeyFromPanelUrl(page.uri);
@@ -208,7 +210,7 @@ export class PageResourceManager {
208
210
  (item) => (item.resourceUri ?? item.currentUrl) === page.uri,
209
211
  );
210
212
  if (existing.isOpen && tab) {
211
- this.app.docBrowserManager.openTarget(page.target, { newTab: true });
213
+ this.app.docBrowserManager.setActiveTab(tab.id);
212
214
  this.app.workbenchSurfaceManager.restore(GLOBAL_WORKBENCH_SURFACE);
213
215
  return;
214
216
  }
@@ -216,7 +218,9 @@ export class PageResourceManager {
216
218
  if (
217
219
  location === "main" ||
218
220
  page.target.kind === "route" ||
219
- (location === "default" && page.mainPath && page.target.kind !== "panel-app")
221
+ (location === "default" &&
222
+ page.mainPath &&
223
+ page.target.kind !== "panel-app")
220
224
  ) {
221
225
  navigate(pageResourceMainPath(page));
222
226
  } else if (location === "floating" && sessionKey) {
@@ -295,6 +299,19 @@ export class PageResourceManager {
295
299
  } else this.open(next, "default", navigate);
296
300
  };
297
301
 
302
+ addExcerptToChat = (
303
+ excerpt: WorkspaceTextExcerpt,
304
+ pathname: string,
305
+ navigate: (path: string) => void,
306
+ ): void => {
307
+ const isChat = pathname === "/chat" || pathname.startsWith("/chat/");
308
+ this.app.chatComposerIntentManager.requestExcerptReference({
309
+ ...excerpt,
310
+ targetSessionKey: isChat ? parseSessionKeyFromRoute(pathname.slice("/chat/".length)) : null,
311
+ });
312
+ if (!isChat) navigate("/chat");
313
+ };
314
+
298
315
  addToChat = (
299
316
  page: PageResource,
300
317
  pathname: string,
@@ -2,6 +2,23 @@ import { describe, expect, it } from 'vitest';
2
2
  import { RightPanelResourceRouteResolver } from '@/features/right-panel-resources';
3
3
 
4
4
  describe('RightPanelResourceRouteResolver', () => {
5
+ it('does not treat different document sections as the same destination', () => {
6
+ const resolver = new RightPanelResourceRouteResolver();
7
+ expect(resolver.areUrlsEquivalent('https://docs.nextclaw.io/en/guide/commands#one',
8
+ 'https://docs.nextclaw.io/en/guide/commands#two', 'docs', 'docs')).toBe(false);
9
+ });
10
+ it.each(['nextclaw://docs/guide/commands?source=chat#sessions', 'https://docs.nextclaw.io/zh/guide/commands?source=chat#sessions'])(
11
+ 'keeps document query and anchor in the resource and final destination: %s', (uri) => {
12
+ const target = new RightPanelResourceRouteResolver().resolve(uri);
13
+ expect(target.url).toContain('?source=chat#sessions');
14
+ expect(target.resourceUri).toContain('?source=chat#sessions');
15
+ },
16
+ );
17
+ it('preserves the app marketplace through resource normalization', () => {
18
+ expect(new RightPanelResourceRouteResolver().resolve('nextclaw://apps?tab=marketplace')).toMatchObject({
19
+ kind: 'apps', dedupeKey: 'apps', url: 'nextclaw://apps?tab=marketplace', resourceUri: 'nextclaw://apps?tab=marketplace',
20
+ });
21
+ });
5
22
  it.each(['cron-job', 'inbox-delivery', 'skill', 'agent', 'project'])('resolves %s as an object, not an unsupported website', (type) => {
6
23
  const uri = 'nextclaw://objects/' + type + '/' + encodeURIComponent('workspace:项目/对象');
7
24
  expect(new RightPanelResourceRouteResolver().resolve(uri)).toMatchObject({ kind: 'system-object', url: uri, resourceUri: uri });
@@ -42,15 +42,16 @@ export function createChatUiResourceReferenceFromTab(
42
42
  });
43
43
  }
44
44
 
45
- export type RightPanelAppsTab = 'apps' | 'panel-apps' | 'service-apps';
45
+ export type RightPanelAppsTab = 'apps' | 'panel-apps' | 'service-apps' | 'marketplace';
46
46
 
47
47
  const DEFAULT_RIGHT_PANEL_APPS_TAB: RightPanelAppsTab = 'apps';
48
48
 
49
49
  function isRightPanelAppsTab(value: unknown): value is RightPanelAppsTab {
50
- return value === 'apps' || value === 'panel-apps' || value === 'service-apps';
50
+ return value === 'apps' || value === 'panel-apps' || value === 'service-apps' || value === 'marketplace';
51
51
  }
52
52
 
53
53
  export function createRightPanelAppsUrl(tab: RightPanelAppsTab = DEFAULT_RIGHT_PANEL_APPS_TAB): string {
54
+ if (tab === 'marketplace') return `${RIGHT_PANEL_APPS_URL}?tab=marketplace`;
54
55
  if (tab === 'panel-apps') return RIGHT_PANEL_PANEL_APPS_URL;
55
56
  if (tab === 'service-apps') return RIGHT_PANEL_SERVICE_APPS_URL;
56
57
  return RIGHT_PANEL_APPS_URL;
@@ -1,3 +1,4 @@
1
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
1
2
  import { useState } from "react";
2
3
  import type {
3
4
  AgentProfileView,
@@ -73,7 +74,7 @@ export function ServiceActionRow({
73
74
  <ShieldPlus className="h-3.5 w-3.5" />
74
75
  </button>
75
76
  </PopoverTrigger>
76
- <PopoverContent align="end" className="w-56 rounded-xl p-1.5">
77
+ <PopoverContent align="end" variant="menu">
77
78
  <div className="px-2 py-1.5 text-[11px] font-medium text-muted-foreground">
78
79
  {t("serviceAppsGrantToAgent")}
79
80
  </div>
@@ -85,9 +86,9 @@ export function ServiceActionRow({
85
86
  onGrantAgent(action.id, agent.id);
86
87
  setAgentMenuOpen(false);
87
88
  }}
88
- className="flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-left text-xs text-foreground transition-colors hover:bg-[var(--interaction-hover)] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border"
89
+ className={`${ACTION_MENU_ITEM_CLASS} text-foreground ${ACTION_FEEDBACK.item}`}
89
90
  >
90
- <Bot className="h-3.5 w-3.5 text-muted-foreground" />
91
+ <Bot className="h-4 w-4 shrink-0 text-muted-foreground" />
91
92
  <span className="min-w-0 truncate">
92
93
  {agent.displayName?.trim() || agent.id}
93
94
  </span>
@@ -51,11 +51,11 @@ export function ServiceAppDeleteDialog({
51
51
  onOpenChange={(nextOpen) => !deletePending && onOpenChange(nextOpen)}
52
52
  >
53
53
  <DialogContent
54
- className="max-w-md [&>:last-child]:hidden"
54
+ className="max-w-md"
55
55
  onEscapeKeyDown={(event) => deletePending && event.preventDefault()}
56
56
  onInteractOutside={(event) => deletePending && event.preventDefault()}
57
57
  >
58
- <DialogHeader>
58
+ <DialogHeader showClose={false}>
59
59
  <DialogTitle>{t("serviceAppsDeleteConfirmTitle")}</DialogTitle>
60
60
  <DialogDescription>
61
61
  {t("serviceAppsDeleteConfirmDescription")} {appTitle}
@@ -1,3 +1,4 @@
1
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
1
2
  import { PageResourceActionItems } from "@/features/right-panel-resources";
2
3
  import { pageResourceFromSystemObject } from "@/features/right-panel-resources";
3
4
  import { useState } from "react";
@@ -380,15 +381,15 @@ function ServiceAppMenuItem({
380
381
  <button
381
382
  type="button"
382
383
  className={cn(
383
- "flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left text-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border disabled:cursor-not-allowed disabled:opacity-50",
384
+ ACTION_MENU_ITEM_CLASS,
384
385
  destructive
385
- ? "text-destructive hover:bg-destructive/10"
386
- : "text-muted-foreground hover:bg-[var(--interaction-hover)] hover:text-accent-foreground",
386
+ ? ACTION_FEEDBACK.destructive
387
+ : `text-foreground ${ACTION_FEEDBACK.item}`,
387
388
  )}
388
389
  disabled={disabled}
389
390
  onClick={onClick}
390
391
  >
391
- <Icon className="h-4 w-4 shrink-0" />
392
+ <Icon className={cn("h-4 w-4 shrink-0", !destructive && "text-muted-foreground")} />
392
393
  <span>{label}</span>
393
394
  </button>
394
395
  );
@@ -31,8 +31,10 @@ type ServiceActionView = ServiceActionListView["actions"][number];
31
31
 
32
32
  export function ServiceAppsPanel({
33
33
  onManagePackage,
34
+ resourceId,
34
35
  }: {
35
36
  onManagePackage: (packageId: string) => void;
37
+ resourceId?: string;
36
38
  }) {
37
39
  const serviceApps = useServiceApps();
38
40
  const appData = useAppData();
@@ -84,7 +86,8 @@ export function ServiceAppsPanel({
84
86
  );
85
87
  }
86
88
 
87
- const apps: ServiceAppRecordView[] = serviceApps.data?.entries ?? [];
89
+ const apps: ServiceAppRecordView[] = (serviceApps.data?.entries ?? []).filter((app) => !resourceId || app.id === resourceId);
90
+ if (resourceId && !apps.length) return <p role="alert" className="p-4">{t("resourceNotFound")}</p>;
88
91
  const diagnostics = serviceApps.data?.diagnostics ?? [];
89
92
  const actions: ServiceActionView[] = serviceActions.data?.actions ?? [];
90
93
  const grants: ServiceActionGrantView[] =
@@ -165,7 +168,7 @@ export function ServiceAppsPanel({
165
168
  discoveredActionsByApp[app.id] ??
166
169
  actions.filter((action) => action.appId === app.id)
167
170
  }
168
- actionsOpen={Boolean(expandedActionsByApp[app.id])}
171
+ actionsOpen={expandedActionsByApp[app.id] ?? Boolean(resourceId)}
169
172
  grants={grants}
170
173
  agents={agents.data?.agents ?? []}
171
174
  deletePending={deleteServiceApp.isPending}
@@ -101,7 +101,7 @@ export function ProviderModelSuggestionsPanel(props: ProviderModelSuggestionsPan
101
101
  />
102
102
  </div>
103
103
  ) : null}
104
- <div className='custom-scrollbar max-h-44 overflow-y-auto overscroll-contain'>
104
+ <div className='custom-scrollbar max-h-44 overflow-y-auto'>
105
105
  {visibleModels.map((modelName) => (
106
106
  <label
107
107
  key={modelName}
@@ -1,3 +1,4 @@
1
+ import { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@/shared/components/ui/actions/action-feedback';
1
2
  import { useMemo, useState } from 'react';
2
3
  import { KeyRound, MoreVertical, Plus, Search, Trash2 } from 'lucide-react';
3
4
  import {
@@ -307,10 +308,10 @@ export function ProvidersConfigPage() {
307
308
  <MoreVertical className='h-4 w-4' />
308
309
  </button>
309
310
  </PopoverTrigger>
310
- <PopoverContent className='w-40 p-1' align='end' onClick={(event) => event.stopPropagation()}>
311
+ <PopoverContent variant='menu' align='end' onClick={(event) => event.stopPropagation()}>
311
312
  <button
312
313
  type='button'
313
- className='flex w-full items-center gap-2 rounded-md px-2 py-2 text-sm text-red-600 hover:bg-destructive/10'
314
+ className={`${ACTION_MENU_ITEM_CLASS} ${ACTION_FEEDBACK.destructive}`}
314
315
  onClick={() => setProviderToDelete(provider.providerId)}
315
316
  >
316
317
  <Trash2 className='h-4 w-4' />
package/src/index.css CHANGED
@@ -93,27 +93,35 @@
93
93
  background: hsl(var(--gray-400) / 0.48);
94
94
  }
95
95
 
96
- .doc-browser-tab-scrollbar {
96
+ .compact-tab-scrollbar {
97
97
  scrollbar-width: thin;
98
- scrollbar-color: hsl(var(--gray-300) / 0.34) transparent;
98
+ scrollbar-color: var(--tab-scrollbar-thumb, hsl(var(--gray-300) / 0.34)) transparent;
99
99
  }
100
100
 
101
- .doc-browser-tab-scrollbar::-webkit-scrollbar {
101
+ /* Native thin scrollbars override pixel sizes and may expand on hover. */
102
+ @supports selector(::-webkit-scrollbar) {
103
+ .compact-tab-scrollbar {
104
+ scrollbar-width: auto;
105
+ scrollbar-color: auto;
106
+ }
107
+ }
108
+
109
+ .compact-tab-scrollbar::-webkit-scrollbar {
102
110
  width: 2px;
103
111
  height: 2px;
104
112
  }
105
113
 
106
- .doc-browser-tab-scrollbar::-webkit-scrollbar-track {
114
+ .compact-tab-scrollbar::-webkit-scrollbar-track {
107
115
  background: transparent;
108
116
  }
109
117
 
110
- .doc-browser-tab-scrollbar::-webkit-scrollbar-thumb {
111
- background: hsl(var(--gray-300) / 0.34);
118
+ .compact-tab-scrollbar::-webkit-scrollbar-thumb {
119
+ background: var(--tab-scrollbar-thumb, hsl(var(--gray-300) / 0.34));
112
120
  border-radius: 999px;
113
121
  }
114
122
 
115
- .doc-browser-tab-scrollbar::-webkit-scrollbar-thumb:hover {
116
- background: hsl(var(--gray-400) / 0.44);
123
+ .compact-tab-scrollbar::-webkit-scrollbar-thumb:hover {
124
+ background: var(--tab-scrollbar-thumb-hover, hsl(var(--gray-400) / 0.44));
117
125
  }
118
126
 
119
127
  /* ========================================
@@ -680,6 +688,32 @@
680
688
  --md-table-head-bg: rgba(191, 219, 254, 0.16);
681
689
  }
682
690
 
691
+ :root[data-theme="paper-ink"] .chat-markdown-user {
692
+ --md-text: hsl(var(--primary-foreground));
693
+ --md-muted: hsl(42 20% 80%);
694
+ --md-border: hsl(42 20% 80% / 0.24);
695
+ --md-link: hsl(45 42% 84%);
696
+ --md-inline-code-bg: hsl(45 20% 90% / 0.1);
697
+ --md-inline-code-color: hsl(var(--primary-foreground));
698
+ --md-blockquote-border: hsl(45 30% 80% / 0.5);
699
+ --md-blockquote-bg: hsl(45 20% 90% / 0.06);
700
+ --md-table-head-bg: hsl(45 20% 90% / 0.08);
701
+ }
702
+
703
+ :root[data-theme="plain-paper"] .chat-markdown-user,
704
+ :root[data-theme="plain-paper"] .chat-markdown-assistant,
705
+ :root[data-theme="paper-ink"] .chat-markdown-assistant {
706
+ --md-text: hsl(var(--foreground));
707
+ --md-muted: hsl(var(--gray-600));
708
+ --md-border: hsl(var(--border));
709
+ --md-link: hsl(var(--link-foreground));
710
+ --md-inline-code-bg: hsl(var(--gray-200) / 0.5);
711
+ --md-inline-code-color: hsl(var(--gray-800));
712
+ --md-blockquote-border: hsl(var(--brand-400) / 0.5);
713
+ --md-blockquote-bg: hsl(var(--brand-100) / 0.4);
714
+ --md-table-head-bg: hsl(var(--gray-200) / 0.4);
715
+ }
716
+
683
717
  :root[data-theme="work"] .chat-markdown-assistant {
684
718
  --md-link: #1f73c9;
685
719
  --md-border: rgba(0, 0, 0, 0.11);
@@ -55,6 +55,22 @@ async function resetMemoryThenRehydrate(savedState: string | null) {
55
55
  }
56
56
 
57
57
  describe('DocBrowserManager layout notifications', () => {
58
+ it.each(['nextclaw://objects/chat-session/example', 'nextclaw://chat-session/sid_ZXhhbXBsZQ'])(
59
+ 'restores historical conversation tabs as real session views: %s', async (uri) => {
60
+ window.localStorage.setItem(docBrowserStorageKey, JSON.stringify({ version: 1, state: { snapshot: {
61
+ isOpen: true, activeTabId: 'old',
62
+ tabs: [{ id: 'old', kind: 'system-object', title: 'Conversation', currentUrl: uri, resourceUri: uri }],
63
+ activeHistory: [{ tabId: 'old', kind: 'system-object', url: uri, resourceUri: uri }],
64
+ } } }));
65
+ await rehydrateDocBrowserFromStorage();
66
+ expect(useDocBrowserStore.getState().snapshot.tabs[0]).toMatchObject({
67
+ kind: 'chat-session', currentUrl: 'nextclaw://sessions/example', resourceUri: 'nextclaw://sessions/example',
68
+ });
69
+ expect(useDocBrowserStore.getState().snapshot.activeHistory[0]).toMatchObject({
70
+ kind: 'chat-session', url: 'nextclaw://sessions/example',
71
+ });
72
+ },
73
+ );
58
74
  it('notifies the app layout coordinator after opening the docked browser', () => {
59
75
  const onRightPanelOpened = vi.fn();
60
76
  const manager = new DocBrowserManager(new WorkbenchSurfaceManager(),
@@ -505,7 +505,7 @@ describe("DocBrowser", () => {
505
505
 
506
506
  render(<DocBrowser />);
507
507
 
508
- expect(screen.getByTitle("Local App").getAttribute("tabindex")).toBeNull();
508
+ expect(screen.getAllByTitle("Local App").find((element) => element.tagName === 'IFRAME')!.getAttribute("tabindex")).toBeNull();
509
509
  });
510
510
  });
511
511
 
@@ -875,7 +875,7 @@ describe("DocBrowser content tabs", () => {
875
875
  render(<DocBrowser />);
876
876
 
877
877
  const addressInput = screen.getByRole("textbox", { name: "Address" }) as HTMLInputElement;
878
- const iframe = screen.getByTitle("Local App") as HTMLIFrameElement;
878
+ const iframe = screen.getAllByTitle("Local App").find((element) => element.tagName === 'IFRAME') as HTMLIFrameElement;
879
879
  const externalLink = screen.getByRole("link", { name: /Open in Browser/i }) as HTMLAnchorElement;
880
880
 
881
881
  expect(addressInput.value).toBe("http://127.0.0.1:5173/dashboard");
@@ -54,7 +54,7 @@ describe("ordinary Markdown resource links end to end", () => {
54
54
  </QueryClientProvider>,
55
55
  );
56
56
  }
57
- it.each(["cron-job", "skill", "agent", "project", "inbox-delivery"])(
57
+ it.each(["cron-job", "skill", "agent", "project", "inbox-delivery", "panel-app", "service-app", "mcp-server", "project-work"])(
58
58
  "opens a normal Markdown %s object link in the shared resource viewer",
59
59
  (kind) => {
60
60
  const uri = "nextclaw://objects/" + kind + "/existing-object";
@@ -72,6 +72,34 @@ describe("ordinary Markdown resource links end to end", () => {
72
72
  expect(screen.getByTestId("route").textContent).toBe("/chat");
73
73
  },
74
74
  );
75
+ it.each(['sessions/ncp-mu2x4zdy-9wzl0otb', 'chat-session/ncp-mu2x4zdy-9wzl0otb',
76
+ 'chat-session/sid_bmNwLW11Mng0emR5LTl3emwwb3Ri', 'objects/chat-session/ncp-mu2x4zdy-9wzl0otb',
77
+ 'objects/chat-sessions/ncp-mu2x4zdy-9wzl0otb'])(
78
+ 'opens the actual conversation route from %s', (path) => {
79
+ setup(`[Conversation](nextclaw://${path})`);
80
+ fireEvent.click(screen.getByRole('link', { name: 'Conversation' }));
81
+ expect(screen.getByTestId('route').textContent).toBe('/chat/ncp-mu2x4zdy-9wzl0otb');
82
+ expect(useDocBrowserStore.getState().snapshot.isOpen).toBe(false);
83
+ },
84
+ );
85
+ it.each([
86
+ ['nextclaw://docs/guide/getting-started', 'docs'],
87
+ ['nextclaw://apps?tab=service-apps', 'apps'],
88
+ ['nextclaw://marketplace-detail/skill%3Aexample', 'marketplace-detail'],
89
+ ['nextclaw://file/absolute/tmp/readme.md', 'workspace-file'],
90
+ ])('opens the %s resource family through ordinary Markdown', (uri, kind) => {
91
+ setup(`[Resource](${uri})`);
92
+ fireEvent.click(screen.getByRole('link', { name: 'Resource' }));
93
+ const { snapshot } = useDocBrowserStore.getState();
94
+ expect(snapshot.tabs.find((item) => item.id === snapshot.activeTabId)?.kind).toBe(kind);
95
+ });
96
+ it.each([['nextclaw://marketplace', '/skills'], ['nextclaw://page?path=%2Fagents', '/agents']])(
97
+ 'navigates built-in page %s', (uri, path) => {
98
+ setup(`[Page](${uri})`);
99
+ fireEvent.click(screen.getByRole('link', { name: 'Page' }));
100
+ expect(screen.getByTestId('route').textContent).toBe(path);
101
+ },
102
+ );
75
103
  it("opens a normal Panel App link in the global sidebar without a catalog lookup", () => {
76
104
  setup();
77
105
  const link = screen.getByRole("link", { name: "Notes" });
@@ -112,7 +112,7 @@ export function DocBrowserTabStrip({
112
112
  <span className="truncate">{current?.title || t('docBrowserTabUntitled')}</span><ChevronDown className="h-4 w-4 shrink-0" />
113
113
  </button>
114
114
  </PopoverTrigger>
115
- <PopoverContent align="start" className="max-h-[70dvh] w-72 overflow-y-auto p-1">
115
+ <PopoverContent align="start" variant="menu" className="max-h-[70dvh]">
116
116
  <ContextMenuItems groups={mobileGroups} onClose={() => setMobileMenuOpen(false)} />
117
117
  {mobileToolbar}
118
118
  </PopoverContent>
@@ -126,7 +126,7 @@ export function DocBrowserTabStrip({
126
126
  tabs={compactTabs}
127
127
  actions={actions}
128
128
  className="flex h-10 min-w-0 flex-1 gap-1 border-0 bg-transparent px-0 select-none"
129
- scrollClassName="doc-browser-tab-scrollbar flex h-full max-md:h-11 max-md:basis-full items-center gap-0.5"
129
+ scrollClassName="flex h-full max-md:h-11 max-md:basis-full items-center gap-0.5"
130
130
  tabsClassName="items-center gap-0.5"
131
131
  actionsClassName="h-full max-md:h-11 max-md:w-full items-center gap-0.5"
132
132
  tabBaseClassName="inline-flex cursor-pointer items-center gap-0.5 h-7 max-md:min-h-11 px-2 rounded-md text-xs max-w-[220px] shrink-0 transition-colors"
@@ -1,4 +1,5 @@
1
1
  import { ViewMemoryStorage } from '@/shared/lib/navigation-history';
2
+ import { createSessionResourceUri, parseSessionResourceUri } from '@nextclaw/shared';
2
3
  import { create } from 'zustand';
3
4
  import { createJSONStorage, persist } from 'zustand/middleware';
4
5
  import type {
@@ -80,16 +81,19 @@ function normalizePersistedDocBrowserTab(value: unknown): DocBrowserTab | null {
80
81
  ? value.resourceUri.trim()
81
82
  : undefined;
82
83
  const dockIcon = normalizePersistedDockIcon(value.dockIcon);
84
+ const currentUrl = history[historyIndex] ?? value.currentUrl;
85
+ const sessionId = parseSessionResourceUri(resourceUri ?? currentUrl);
86
+ const sessionUri = sessionId ? createSessionResourceUri(sessionId) : undefined;
83
87
 
84
88
  return {
85
89
  id: value.id,
86
- kind: value.kind,
90
+ kind: sessionUri ? 'chat-session' : value.kind,
87
91
  title: value.title,
88
- currentUrl: history[historyIndex] ?? value.currentUrl,
89
- resourceUri,
92
+ currentUrl: sessionUri ?? currentUrl,
93
+ resourceUri: sessionUri ?? resourceUri,
90
94
  dockIcon,
91
95
  viewState: value.viewState,
92
- dedupeKey,
96
+ dedupeKey: sessionUri ?? dedupeKey,
93
97
  history,
94
98
  historyIndex,
95
99
  navVersion,
@@ -123,12 +127,14 @@ function normalizePersistedActiveHistoryEntry(
123
127
  const resourceUri = typeof value.resourceUri === 'string' && value.resourceUri.trim().length > 0
124
128
  ? value.resourceUri.trim()
125
129
  : undefined;
130
+ const sessionId = parseSessionResourceUri(resourceUri ?? value.url);
131
+ const sessionUri = sessionId ? createSessionResourceUri(sessionId) : undefined;
126
132
 
127
133
  return {
128
- kind: value.kind,
129
- resourceUri,
134
+ kind: sessionUri ? 'chat-session' : value.kind,
135
+ resourceUri: sessionUri ?? resourceUri,
130
136
  tabId: value.tabId,
131
- url: value.url,
137
+ url: sessionUri ?? value.url,
132
138
  };
133
139
  }
134
140
 
@@ -112,7 +112,8 @@ export function getDocsUrl(pathOrUrl: string): string {
112
112
 
113
113
  export function normalizeDocUrl(url: string): string {
114
114
  try {
115
- return new URL(url).pathname.replace(/\.html$/, '').replace(/\/$/, '');
115
+ const parsed = new URL(url);
116
+ return `${parsed.pathname.replace(/\.html$/, '').replace(/\/$/, '')}${parsed.search}${parsed.hash}`;
116
117
  } catch {
117
118
  return url;
118
119
  }
@@ -1,4 +1,4 @@
1
- import { useMemo, useState } from 'react';
1
+ import { useMemo, useState, type ComponentProps } from 'react';
2
2
  import { Search } from 'lucide-react';
3
3
  import { useServerPathBrowse } from '@/shared/hooks/use-server-path-browse';
4
4
  import { useServerPathCreateDirectory } from '@/shared/hooks/use-server-path-create-directory';
@@ -25,6 +25,7 @@ type ServerPathPickerDialogProps = {
25
25
  defaultWorkspacePath?: string | null;
26
26
  isSaving: boolean;
27
27
  onOpenChange: (open: boolean) => void;
28
+ onCloseAutoFocus?: ComponentProps<typeof DialogContent>['onCloseAutoFocus'];
28
29
  onConfirm: (path: string) => Promise<void> | void;
29
30
  title: string;
30
31
  description?: string;
@@ -57,6 +58,7 @@ export function ServerPathPickerDialog({
57
58
  defaultWorkspacePath,
58
59
  isSaving,
59
60
  onOpenChange,
61
+ onCloseAutoFocus,
60
62
  onConfirm,
61
63
  title,
62
64
  description,
@@ -79,8 +81,8 @@ export function ServerPathPickerDialog({
79
81
  onOpenChange(nextOpen);
80
82
  }}
81
83
  >
82
- <DialogContent className="max-h-[92vh] overflow-hidden p-0 sm:h-[44rem] sm:max-w-5xl sm:grid-rows-[auto_minmax(0,1fr)]">
83
- <DialogHeader className="border-b border-border px-5 py-4 pr-12">
84
+ <DialogContent onCloseAutoFocus={onCloseAutoFocus} className="max-h-[92vh] overflow-hidden p-0 sm:h-[44rem] sm:max-w-5xl sm:grid-rows-[auto_minmax(0,1fr)]">
85
+ <DialogHeader className="border-b border-border px-5 py-4">
84
86
  <DialogTitle>{title}</DialogTitle>
85
87
  <DialogDescription className={description ? undefined : 'sr-only'}>
86
88
  {description ?? title}
@@ -1,12 +1,48 @@
1
1
  import { render, screen } from '@testing-library/react';
2
- import { describe, expect, it } from 'vitest';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { t } from '@/shared/lib/i18n';
3
5
  import {
4
6
  Dialog,
5
7
  DialogContent,
8
+ DialogHeader,
9
+ DialogDescription,
10
+ DialogTrigger,
6
11
  DialogTitle,
7
12
  } from '@/shared/components/ui/dialog';
8
13
 
9
14
  describe('Dialog', () => {
15
+ it('keeps header actions separate from closing and restores trigger focus', async () => {
16
+ const onAction = vi.fn();
17
+ const user = userEvent.setup();
18
+ render(<Dialog>
19
+ <DialogTrigger>Open report</DialogTrigger>
20
+ <DialogContent>
21
+ <DialogHeader actions={<button onClick={onAction}>Next report</button>}>
22
+ <DialogTitle>A long report title</DialogTitle>
23
+ <DialogDescription>Report summary</DialogDescription>
24
+ </DialogHeader>
25
+ </DialogContent>
26
+ </Dialog>);
27
+ await user.click(screen.getByRole('button', { name: 'Open report' }));
28
+ expect(screen.getAllByRole('button', { name: t('close') })).toHaveLength(1);
29
+ await user.click(screen.getByRole('button', { name: 'Next report' }));
30
+ expect(onAction).toHaveBeenCalledOnce();
31
+ expect(screen.getByRole('dialog')).toBeTruthy();
32
+ await user.click(screen.getByRole('button', { name: t('close') }));
33
+ expect(screen.queryByRole('dialog')).toBeNull();
34
+ expect(document.activeElement).toBe(screen.getByRole('button', { name: 'Open report' }));
35
+ });
36
+
37
+ it('supports explicit confirmation-only headers', () => {
38
+ render(<Dialog open><DialogContent><DialogHeader showClose={false}>
39
+ <DialogTitle>Confirm deletion</DialogTitle>
40
+ <DialogDescription>Choose an action below.</DialogDescription>
41
+ </DialogHeader></DialogContent></Dialog>);
42
+ expect(screen.queryByRole('button', { name: t('close') })).toBeNull();
43
+ expect(screen.getByRole('heading', { name: 'Confirm deletion' })).toBeTruthy();
44
+ });
45
+
10
46
  it('renders modal layers above floating panels', () => {
11
47
  render(
12
48
  <Dialog open>
@@ -1,8 +1 @@
1
- /** Neutral actions share one theme color across icon and menu surfaces. */
2
- export const ACTION_MENU_ITEM_CLASS = 'flex min-h-8 w-full items-center gap-2 rounded-lg px-2.5 py-1 text-left text-[13px] leading-5 font-medium outline-none transition-colors disabled:pointer-events-none disabled:opacity-45';
3
-
4
- export const ACTION_FEEDBACK = {
5
- icon: 'hover:before:bg-[var(--interaction-hover)] active:before:bg-[var(--interaction-hover)] disabled:hover:before:bg-transparent disabled:active:before:bg-transparent',
6
- item: 'hover:bg-[var(--interaction-hover)] focus-visible:bg-[var(--interaction-hover)] active:bg-[var(--interaction-hover)] disabled:hover:bg-transparent disabled:active:bg-transparent',
7
- destructive: 'text-destructive hover:bg-destructive/10 focus-visible:bg-destructive/10 disabled:hover:bg-transparent',
8
- } as const;
1
+ export { ACTION_FEEDBACK, ACTION_MENU_ITEM_CLASS } from '@nextclaw/agent-chat-ui';
@@ -44,7 +44,7 @@ const IconActionButton = React.forwardRef<HTMLButtonElement, IconActionButtonPro
44
44
  size = 'md',
45
45
  tone = 'default',
46
46
  tooltip,
47
- tooltipSide = 'bottom',
47
+ tooltipSide,
48
48
  ...buttonProps
49
49
  },
50
50
  ref
@@ -48,14 +48,13 @@ export const ConfirmDialog = ({
48
48
  return (
49
49
  <Dialog open={open} onOpenChange={onOpenChange}>
50
50
  <DialogContent
51
- className="[&>:last-child]:hidden"
52
51
  onOpenAutoFocus={(event) => {
53
52
  event.preventDefault();
54
53
  confirmButtonRef.current?.focus();
55
54
  }}
56
55
  onCloseAutoFocus={(event) => event.preventDefault()}
57
56
  >
58
- <DialogHeader>
57
+ <DialogHeader showClose={false}>
59
58
  <DialogTitle>{title}</DialogTitle>
60
59
  {description ? <DialogDescription>{description}</DialogDescription> : null}
61
60
  </DialogHeader>