@nextclaw/ui 0.25.4 → 0.26.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 (492) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/dist/.vite/manifest.json +1158 -1392
  3. package/dist/assets/{abnfDiagram-VRR7QNED-DX_u5BBX.js → abnfDiagram-VRR7QNED-Dcw10Yt1.js} +1 -1
  4. package/dist/assets/account-panel-ZM2qzKF4.js +1 -0
  5. package/dist/assets/{aiden0z-pptx-renderer.es-C-E9e5yB.js → aiden0z-pptx-renderer.es--oNqetPA.js} +1 -1
  6. package/dist/assets/api-Cjq-o1VN.js +20 -0
  7. package/dist/assets/app-presenter-provider-C02YPoMr.js +124 -0
  8. package/dist/assets/appearance-settings-page-B4zouKzg.js +1 -0
  9. package/dist/assets/{arc-Cxwa624o.js → arc-DBRedCax.js} +1 -1
  10. package/dist/assets/architecture-TIHT7OUA-CvnC-LeA.js +1 -0
  11. package/dist/assets/{architectureDiagram-ZJ3FMSHR-D8mCj0H1.js → architectureDiagram-ZJ3FMSHR-Dufhtuv-.js} +1 -1
  12. package/dist/assets/{blockDiagram-677ZJIJ3-CbGC1IHl.js → blockDiagram-677ZJIJ3-BUk0vtJ7.js} +1 -1
  13. package/dist/assets/{book-open-xqEj1OLE.js → book-open-AteA89HX.js} +1 -1
  14. package/dist/assets/{c4Diagram-LMCZKHZV-BQhGC1Vc.js → c4Diagram-LMCZKHZV-CxDcVE9p.js} +1 -1
  15. package/dist/assets/card-BLXvBstA.js +1 -0
  16. package/dist/assets/channel-CpMstUPF.js +1 -0
  17. package/dist/assets/channels-list-page-fj8kMo-T.js +8 -0
  18. package/dist/assets/chunk-2Q5K7J3B-Djp3VF0s.js +1 -0
  19. package/dist/assets/{chunk-32BRIVSS-B74ZZwYG.js → chunk-32BRIVSS-DSF3KElA.js} +1 -1
  20. package/dist/assets/{chunk-52WLFC77-BvmxW_f_.js → chunk-52WLFC77-Costxzr3.js} +1 -1
  21. package/dist/assets/{chunk-5FCAYU7R-DQvBRnwL.js → chunk-5FCAYU7R-rhqzGGZo.js} +1 -1
  22. package/dist/assets/{chunk-5HE753X5-CDIH0_y3.js → chunk-5HE753X5-BsEsmIao.js} +1 -1
  23. package/dist/assets/{chunk-5JV3BV7I-CcevlKd-.js → chunk-5JV3BV7I-Dqw_DCoN.js} +1 -1
  24. package/dist/assets/{chunk-5TONJI2A-_3dxVdnY.js → chunk-5TONJI2A-Cft82fp8.js} +1 -1
  25. package/dist/assets/{chunk-5VM5RSS4-pGO5vvo-.js → chunk-5VM5RSS4-DqNHn9Dl.js} +1 -1
  26. package/dist/assets/{chunk-7BUUIJ7U-DEKF5uAN.js → chunk-7BUUIJ7U-A5SBEMYY.js} +1 -1
  27. package/dist/assets/{chunk-BIQX33UG-CjBFgq2r.js → chunk-BIQX33UG-1Ng3mTrH.js} +1 -1
  28. package/dist/assets/{chunk-C7G6YPKG-e_K9OGTz.js → chunk-C7G6YPKG-DRJEy8ZI.js} +1 -1
  29. package/dist/assets/{chunk-CQNSW5MT-C2IiHyHz.js → chunk-CQNSW5MT-Bydv_J3J.js} +1 -1
  30. package/dist/assets/{chunk-CYSBUYHQ-DCC6KmGp.js → chunk-CYSBUYHQ-HkMIg12u.js} +1 -1
  31. package/dist/assets/{chunk-EMLP6XTP-BYGgekQ0.js → chunk-EMLP6XTP-C5ndDvm3.js} +1 -1
  32. package/dist/assets/{chunk-EX3LRPZG-FGcwuVsA.js → chunk-EX3LRPZG-DzeloZRo.js} +1 -1
  33. package/dist/assets/{chunk-FWX5IMBZ-CV3Ih_Os.js → chunk-FWX5IMBZ-n_2_CLTQ.js} +2 -2
  34. package/dist/assets/{chunk-HOUHSVGY-CXpq_hfV.js → chunk-HOUHSVGY-kx_slvu3.js} +1 -1
  35. package/dist/assets/{chunk-ICXQ74PX-CZIpjupq.js → chunk-ICXQ74PX-sQLMURqL.js} +1 -1
  36. package/dist/assets/{chunk-JG7HCLWE-CdgwBpW7.js → chunk-JG7HCLWE-CMUn5Elc.js} +1 -1
  37. package/dist/assets/{chunk-JWPE2WC7-BPjAZpOQ.js → chunk-JWPE2WC7-Cra3s-Uk.js} +1 -1
  38. package/dist/assets/{chunk-MOJQB5TN-DbJDm8to.js → chunk-MOJQB5TN-umcrg5Bi.js} +1 -1
  39. package/dist/assets/{chunk-MOZMSUNE-BUa1fqKn.js → chunk-MOZMSUNE-BnljD1ig.js} +1 -1
  40. package/dist/assets/{chunk-OGEWGWER-CtnzLgRu.js → chunk-OGEWGWER-BXx5pQjU.js} +1 -1
  41. package/dist/assets/{chunk-OSBZ3O6U-fUgdpTUM.js → chunk-OSBZ3O6U-D-1qfdWu.js} +1 -1
  42. package/dist/assets/{chunk-PUDLZKDR-CtDWZT9-.js → chunk-PUDLZKDR-DLzX78LC.js} +1 -1
  43. package/dist/assets/{chunk-Q4XR5HBZ-BxnK2qxr.js → chunk-Q4XR5HBZ-DTK-rtW6.js} +1 -1
  44. package/dist/assets/{chunk-QBLGF6JB-CH4UKoCF.js → chunk-QBLGF6JB-CsFeIGfr.js} +1 -1
  45. package/dist/assets/{chunk-R7FJI6CG-BxwFoF1v.js → chunk-R7FJI6CG-4xNYUeng.js} +1 -1
  46. package/dist/assets/{chunk-RYQCIY6F-DpHAmq7O.js → chunk-RYQCIY6F-DJiHiTE5.js} +1 -1
  47. package/dist/assets/{chunk-U6XO7XAA-BjH2VUHU.js → chunk-U6XO7XAA-BVYkauHz.js} +1 -1
  48. package/dist/assets/{chunk-V7JOEXUC-DKJZ3HGj.js → chunk-V7JOEXUC-BsazE8cS.js} +1 -1
  49. package/dist/assets/chunk-VAUOI2AC-BrbiIC1Q.js +1 -0
  50. package/dist/assets/{chunk-VR4S4FIN-Cf-o2GtI.js → chunk-VR4S4FIN-7RoZQffO.js} +1 -1
  51. package/dist/assets/{chunk-WYO6CB5R-zeNXGm20.js → chunk-WYO6CB5R-DEuS6N1R.js} +3 -3
  52. package/dist/assets/chunk-XXDRQBXY-Cx9N40wF.js +1 -0
  53. package/dist/assets/{chunk-YOTPTUD7-Ck87Kqxe.js → chunk-YOTPTUD7-9KBrosZL.js} +1 -1
  54. package/dist/assets/{chunk-ZGVPDNZ5-BbfK6Bfd.js → chunk-ZGVPDNZ5-IYgN9f5A.js} +1 -1
  55. package/dist/assets/{chunk-ZIRB5QZD-BDpzh4Yl.js → chunk-ZIRB5QZD-BUo0-zcp.js} +1 -1
  56. package/dist/assets/{circle-dashed-CU3yApvP.js → circle-dashed-LSYZTzM7.js} +1 -1
  57. package/dist/assets/classDiagram-OUVF2IWQ-DFN1v3PQ.js +1 -0
  58. package/dist/assets/classDiagram-v2-EOCWNBFH-DRvglADa.js +1 -0
  59. package/dist/assets/client-DudCRJw4.js +1 -0
  60. package/dist/assets/config-split-page-G7Kt2BnV.js +1 -0
  61. package/dist/assets/confirm-dialog-DShT64F6.js +1 -0
  62. package/dist/assets/context-menu-rd7b_kVD.js +1 -0
  63. package/dist/assets/{cose-bilkent-JH36ORCC-CQfMxKCT.js → cose-bilkent-JH36ORCC-DhqbC1fR.js} +1 -1
  64. package/dist/assets/createLucideIcon-D7hvIHV-.js +1 -0
  65. package/dist/assets/cynefin-VYW2F7L2-DXUGnpJH.js +1 -0
  66. package/dist/assets/{cynefinDiagram-TSTJHNR4-CxFTiC-p.js → cynefinDiagram-TSTJHNR4-C-TBRi5V.js} +1 -1
  67. package/dist/assets/{dagre-CaBNMcB1.js → dagre-CrgsRasE.js} +1 -1
  68. package/dist/assets/{dagre-VKFMJZFB-S_7Hc7bI.js → dagre-VKFMJZFB-BmafJymp.js} +1 -1
  69. package/dist/assets/desktop-capabilities-page-CzqzFZUY.js +1 -0
  70. package/dist/assets/desktop-update-config-CgeQ0Ffo.js +1 -0
  71. package/dist/assets/{diagram-FQU43EPY-C7zENvFb.js → diagram-FQU43EPY-BoOMwa6D.js} +1 -1
  72. package/dist/assets/{diagram-G47NLZAW-DqYTCqZA.js → diagram-G47NLZAW-Le7N6Uym.js} +1 -1
  73. package/dist/assets/{diagram-NH7WQ7WH-BfSJtXRc.js → diagram-NH7WQ7WH-Fbpj3-MO.js} +1 -1
  74. package/dist/assets/{diagram-OA4YK3LP-CFO-j67H.js → diagram-OA4YK3LP-D3QuGGuu.js} +1 -1
  75. package/dist/assets/{diagram-WEI45ONY-DBQDbTaJ.js → diagram-WEI45ONY-Cxu1uiN6.js} +1 -1
  76. package/dist/assets/dialog-C7glmAQJ.js +5 -0
  77. package/dist/assets/doc-browser-context-BlhBAOLH.js +1 -0
  78. package/dist/assets/doc-browser-dBiR9Qi0.js +1 -0
  79. package/dist/assets/{docx-preview-B4-aDfvO.js → docx-preview-CkU2psnd.js} +1 -1
  80. package/dist/assets/download-BYgECE0n.js +1 -0
  81. package/dist/assets/{ebnfDiagram-CCIWWBDH-CfDNIXFN.js → ebnfDiagram-CCIWWBDH-CCAjuQM6.js} +1 -1
  82. package/dist/assets/{erDiagram-Q63AITRT-D95rFXMM.js → erDiagram-Q63AITRT-BuzUAq-d.js} +1 -1
  83. package/dist/assets/es2015-CsjAAQ6X.js +41 -0
  84. package/dist/assets/eventmodeling-45OFAUF4-ZBfVS3ZC.js +1 -0
  85. package/dist/assets/extensions-qYL-NpL3.js +1 -0
  86. package/dist/assets/{eye-C84inPcV.js → eye-BBuTzJ53.js} +1 -1
  87. package/dist/assets/flowDiagram-23GEKE2U-CqdsKk6x.js +1 -0
  88. package/dist/assets/form-actions-CLGWO52v.js +1 -0
  89. package/dist/assets/{ganttDiagram-NO4QXBWP-Bawg0P0r.js → ganttDiagram-NO4QXBWP-cJmWVY8F.js} +1 -1
  90. package/dist/assets/gitGraph-TEB2WS4Q-fHYFd9Es.js +1 -0
  91. package/dist/assets/{gitGraphDiagram-IHSO6WYX-BbKh9nbL.js → gitGraphDiagram-IHSO6WYX-F58o-vtP.js} +1 -1
  92. package/dist/assets/{i18n-20rSH40D.js → i18n-qBGEbcW6.js} +2 -2
  93. package/dist/assets/info-DKCQHKI2-CSaOL_bb.js +1 -0
  94. package/dist/assets/{infoDiagram-FWYZ7A6U-DPffZXYh.js → infoDiagram-FWYZ7A6U-Gt59b83C.js} +1 -1
  95. package/dist/assets/{ishikawaDiagram-FXEZZL3T-CBMsLwZ2.js → ishikawaDiagram-FXEZZL3T-1u4IAj1I.js} +1 -1
  96. package/dist/assets/{journeyDiagram-5HDEW3XC-Mz5U4OzU.js → journeyDiagram-5HDEW3XC-CCQsfV-5.js} +1 -1
  97. package/dist/assets/{kanban-definition-HUTT4EX6-FXZq2k19.js → kanban-definition-HUTT4EX6-vlB6O_Zn.js} +1 -1
  98. package/dist/assets/katex-B4FQSo9k.js +1 -0
  99. package/dist/assets/keyboard-shortcuts-settings-page-B-wK_6zG.js +1 -0
  100. package/dist/assets/{line-BZwCgT9K.js → line-D_bHubTL.js} +1 -1
  101. package/dist/assets/{linear-CTe9mKUw.js → linear-ChlwuS5y.js} +1 -1
  102. package/dist/assets/loader-circle-BA7EMkih.js +1 -0
  103. package/dist/assets/login-page-Cd84lpVV.js +1 -0
  104. package/dist/assets/login-page-VdMyNkFf.js +1 -0
  105. package/dist/assets/main-CR0SrTBf.js +2 -0
  106. package/dist/assets/main-DXH6EdXI.css +1 -0
  107. package/dist/assets/main-i18n-catalog.config-Btp_OowF.js +1 -0
  108. package/dist/assets/{map-Ci48ZwAp.js → map-oGHTsIu8.js} +1 -1
  109. package/dist/assets/mcp-marketplace-page-jacRwiI-.js +1 -0
  110. package/dist/assets/{mermaid-parser.core-CzPD3U_z.js → mermaid-parser.core-CuRe1ZG4.js} +2 -2
  111. package/dist/assets/{mermaid.core-geIMNPbV.js → mermaid.core-u4YCFKRf.js} +3 -3
  112. package/dist/assets/{mindmap-definition-LN4V7U3C-xqlKxsr_.js → mindmap-definition-LN4V7U3C-DeJAQYTu.js} +1 -1
  113. package/dist/assets/model-config-page-D0DQlSDa.js +1 -0
  114. package/dist/assets/navigation-history-CzErJuPG.js +1 -0
  115. package/dist/assets/navigation-link-32iM1-e6.js +3 -0
  116. package/dist/assets/{ordinal-MxnX8yhv.js → ordinal-C6JFfkKN.js} +1 -1
  117. package/dist/assets/packet-7NZHBO7P-D-YFTczs.js +1 -0
  118. package/dist/assets/panel-app-CC0bVSu4.js +1 -0
  119. package/dist/assets/panel-app-i18n-catalog.config-LUSBp5Ce.js +1 -0
  120. package/dist/assets/panelStandalone-C9EKaApN.js +2 -0
  121. package/dist/assets/{pegDiagram-2B236MQR-D50MFTN1.js → pegDiagram-2B236MQR-nVMkxShH.js} +1 -1
  122. package/dist/assets/pie-RZYD4A2V-VEnYu9s5.js +1 -0
  123. package/dist/assets/{pieDiagram-ENE6RG2P-CpA13oiC.js → pieDiagram-ENE6RG2P-8aUH44QZ.js} +1 -1
  124. package/dist/assets/privacy-settings-page-Bxxx12OO.js +1 -0
  125. package/dist/assets/projects-D56yAPNT.js +1 -0
  126. package/dist/assets/provider-models-C3frdXeW.js +1 -0
  127. package/dist/assets/provider-scoped-model-input-CYetrPYZ.js +1 -0
  128. package/dist/assets/providers-config-page-DESB1h8g.js +1 -0
  129. package/dist/assets/{puzzle-D6gulz7u.js → puzzle-CWHfFyYN.js} +1 -1
  130. package/dist/assets/pwa-CiGUjpcd.js +1 -0
  131. package/dist/assets/{quadrantDiagram-ABIIQ3AL-CYCgaj4l.js → quadrantDiagram-ABIIQ3AL-EY8hpFv8.js} +1 -1
  132. package/dist/assets/radar-I7S5WNFK-BFNIekC1.js +1 -0
  133. package/dist/assets/railroad-3IZDKUUU-lVqJ3Hak.js +1 -0
  134. package/dist/assets/railroad-abnf-AHOZXSZD-DYaefdFC.js +1 -0
  135. package/dist/assets/railroad-ebnf-EBAXGLYW-CTAk6lVq.js +1 -0
  136. package/dist/assets/railroad-peg-LSFZ7HO6-Cob294tg.js +1 -0
  137. package/dist/assets/{railroadDiagram-RFXS5EU6-4LKDGlXN.js → railroadDiagram-RFXS5EU6-CNhcIeji.js} +1 -1
  138. package/dist/assets/{refresh-cw-h9Xq3LY3.js → refresh-cw-y3L6PyLt.js} +1 -1
  139. package/dist/assets/remote-DiGFV8nP.js +1 -0
  140. package/dist/assets/{requirementDiagram-TGXJPOKE-CxNOU0JH.js → requirementDiagram-TGXJPOKE-D8Dcs-Rt.js} +1 -1
  141. package/dist/assets/{rotate-cw-B6xm41Wn.js → rotate-cw-CNE9qSHi.js} +1 -1
  142. package/dist/assets/runtime-config-page-5o98T-TD.js +1 -0
  143. package/dist/assets/{sankeyDiagram-HTMAVEWB-DbCBDe2S.js → sankeyDiagram-HTMAVEWB-HTrb6aa-.js} +1 -1
  144. package/dist/assets/{save-fff_WpY2.js → save-B0p5a0ET.js} +1 -1
  145. package/dist/assets/search-config-page-CpGcnIzi.js +1 -0
  146. package/dist/assets/secrets-config-page-C4VTiW3r.js +3 -0
  147. package/dist/assets/security-config-C5-RQVpS.js +1 -0
  148. package/dist/assets/select-CctTN205.js +1 -0
  149. package/dist/assets/{sequenceDiagram-DBY2YBRQ-DA6W2BS_.js → sequenceDiagram-DBY2YBRQ-6f_4X16Y.js} +1 -1
  150. package/dist/assets/service-apps-panel-CKE5HKNY.js +1 -0
  151. package/dist/assets/{settings-2-CE3ELQyk.js → settings-2-EPflrNk6.js} +1 -1
  152. package/dist/assets/{sizeCapture-X5ZJPWSS-T_q_d_VW.js → sizeCapture-X5ZJPWSS-Ck9rsuwL.js} +1 -1
  153. package/dist/assets/{src-CYpUlx-4.js → src-C8AUg09O.js} +1 -1
  154. package/dist/assets/{stateDiagram-2N3HPSRC-mi8z2G0a.js → stateDiagram-2N3HPSRC-Cm33MLHu.js} +1 -1
  155. package/dist/assets/stateDiagram-v2-6OUMAXLB-BrNv-raG.js +1 -0
  156. package/dist/assets/status-dot-CensgJZC.js +1 -0
  157. package/dist/assets/{swimlanes-5IMT3BWC-DkBEhWE4.js → swimlanes-5IMT3BWC-B107vmvM.js} +2 -2
  158. package/dist/assets/swimlanesDiagram-G3AALYLV-ntcxaPXp.js +8 -0
  159. package/dist/assets/tag-chip-Bjzb4-qW.js +1 -0
  160. package/dist/assets/theme-provider-hlle7Skk.js +1 -0
  161. package/dist/assets/{timeline-definition-FHXFAJF6-BoFmqBw1.js → timeline-definition-FHXFAJF6-CJEoAj33.js} +1 -1
  162. package/dist/assets/trash-2-C5KH5Rw9.js +1 -0
  163. package/dist/assets/treeView-QDETBFTQ-DbFmr-gw.js +1 -0
  164. package/dist/assets/treemap-6X3UGDF4-C8aY96pi.js +1 -0
  165. package/dist/assets/use-config-CPl_F79t.js +1 -0
  166. package/dist/assets/use-desktop-capabilities-CEg9-DrQ.js +1 -0
  167. package/dist/assets/use-viewport-layout-CPZUmTPi.js +1 -0
  168. package/dist/assets/{vennDiagram-L72KCM5P-BlZ3Or5U.js → vennDiagram-L72KCM5P-DzsUHk5I.js} +1 -1
  169. package/dist/assets/wardley-OPB4EBWU-D8d6DbbJ.js +1 -0
  170. package/dist/assets/{wardleyDiagram-EHGQE667-yDfr33i3.js → wardleyDiagram-EHGQE667-1NfFs5ua.js} +1 -1
  171. package/dist/assets/x--xxUvHKW.js +1 -0
  172. package/dist/assets/{xychartDiagram-FW5EYKEG-mIXwIGAQ.js → xychartDiagram-FW5EYKEG-Ci8AI3Qo.js} +1 -1
  173. package/dist/index.html +38 -54
  174. package/dist/panel-standalone.html +11 -15
  175. package/package.json +8 -8
  176. package/src/app/components/layout/__tests__/app-layout.test.tsx +7 -0
  177. package/src/app/components/layout/__tests__/sidebar.layout.test.tsx +36 -16
  178. package/src/app/components/layout/app-layout.tsx +18 -46
  179. package/src/app/components/layout/sidebar-items.tsx +27 -18
  180. package/src/app/components/layout/sidebar-rail.styles.ts +11 -2
  181. package/src/app/components/layout/sidebar.tsx +3 -2
  182. package/src/app/configs/__tests__/app-navigation.config.test.ts +4 -0
  183. package/src/app/configs/app-navigation.config.ts +41 -86
  184. package/src/app/configs/page-resource-renderers.config.ts +13 -0
  185. package/src/app/index.tsx +4 -0
  186. package/src/app/presenters/app.presenter.ts +13 -2
  187. package/src/features/agents/components/__tests__/agents-page.test.tsx +4 -0
  188. package/src/features/agents/components/agent-details-dialog.tsx +5 -2
  189. package/src/features/agents/components/agents-page.tsx +9 -4
  190. package/src/features/apps/components/app-package-card.tsx +2 -2
  191. package/src/features/chat/components/conversation/chat-conversation-content.tsx +32 -19
  192. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +1 -0
  193. package/src/features/chat/components/conversation/chat-conversation-header.tsx +1 -1
  194. package/src/features/chat/components/conversation/chat-conversation-panel.tsx +2 -2
  195. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +1 -0
  196. package/src/features/chat/components/layout/__tests__/chat-page-shell.test.tsx +5 -6
  197. package/src/features/chat/components/layout/__tests__/chat-sidebar-toolbar.test.tsx +14 -12
  198. package/src/features/chat/components/layout/chat-page-shell.tsx +31 -64
  199. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +8 -5
  200. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +64 -256
  201. package/src/features/chat/components/layout/chat-sidebar.tsx +8 -30
  202. package/src/features/chat/components/providers/chat-runtime.provider.tsx +62 -0
  203. package/src/features/chat/features/conversation/components/__tests__/floating-session-conversation.test.tsx +70 -0
  204. package/src/features/chat/features/conversation/components/chat-voice-input-panel.tsx +3 -2
  205. package/src/features/chat/features/conversation/components/floating-session-conversation.tsx +27 -0
  206. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +1 -0
  207. package/src/features/chat/features/conversation/components/session-conversation-panel-tab.tsx +25 -0
  208. package/src/features/chat/features/conversation/hooks/__tests__/use-chat-voice-input.test.tsx +4 -0
  209. package/src/features/chat/features/conversation/hooks/use-chat-composer-reference-intent.ts +2 -1
  210. package/src/features/chat/features/message/components/__tests__/chat-inline-panel-app-card.test.tsx +2 -1
  211. package/src/features/chat/features/message/components/__tests__/chat-message-assistant-header.container.test.tsx +3 -0
  212. package/src/features/chat/features/message/components/__tests__/chat-message-list-skill-preview.container.test.tsx +3 -0
  213. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +35 -47
  214. package/src/features/chat/features/message/components/chat-message-list.container.tsx +6 -10
  215. package/src/features/chat/features/message/hooks/use-chat-inline-token-actions.ts +7 -3
  216. package/src/features/chat/features/message/utils/__tests__/chat-message-process-summary.utils.test.ts +52 -6
  217. package/src/features/chat/features/message/utils/chat-message-process-summary.utils.ts +22 -37
  218. package/src/features/chat/features/session/components/__tests__/chat-sidebar-project-groups.test.tsx +1 -1
  219. package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +21 -0
  220. package/src/features/chat/features/session/components/chat-mobile-session-row.tsx +61 -0
  221. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +4 -37
  222. package/src/features/chat/features/session/components/chat-sidebar-session-entry.tsx +2 -0
  223. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +18 -7
  224. package/src/features/chat/features/session/components/chat-sidebar-session-list.tsx +5 -3
  225. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +10 -2
  226. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +20 -17
  227. package/src/features/chat/features/session/components/session-header/chat-session-header-menu-item.tsx +4 -4
  228. package/src/features/chat/features/session/components/session-header/chat-session-more-actions-menu.tsx +18 -5
  229. package/src/features/chat/features/session/utils/chat-session-route.utils.ts +12 -0
  230. package/src/features/chat/features/workspace/components/__tests__/chat-session-child-sessions.test.tsx +28 -0
  231. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +9 -0
  232. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +6 -2
  233. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +49 -12
  234. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +13 -6
  235. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +6 -0
  236. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +21 -36
  237. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +40 -31
  238. package/src/features/chat/features/workspace/components/child-sessions/chat-session-child-sessions.tsx +6 -1
  239. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +2 -2
  240. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +2 -2
  241. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +27 -0
  242. package/src/features/chat/features/workspace/utils/__tests__/workspace-file-panel-route.utils.test.ts +94 -0
  243. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +2 -0
  244. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +15 -0
  245. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +11 -0
  246. package/src/features/chat/features/workspace/utils/workspace-file-panel-route.utils.ts +147 -0
  247. package/src/features/chat/index.ts +20 -4
  248. package/src/features/chat/managers/__tests__/chat-completion-notification.manager.test.ts +8 -0
  249. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +7 -2
  250. package/src/features/chat/managers/__tests__/session-surface.manager.test.ts +45 -0
  251. package/src/features/chat/managers/chat-completion-notification.manager.ts +5 -0
  252. package/src/features/chat/managers/chat-composer-intent.manager.ts +16 -0
  253. package/src/features/chat/managers/chat-thread.manager.ts +18 -27
  254. package/src/features/chat/managers/chat-voice-input.manager.ts +5 -3
  255. package/src/features/chat/managers/session-surface.manager.ts +46 -0
  256. package/src/features/chat/pages/__tests__/ncp-chat-page.test.tsx +23 -5
  257. package/src/features/chat/pages/ncp-chat-page.tsx +6 -86
  258. package/src/features/chat/presenters/chat.presenter.ts +2 -1
  259. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +2 -2
  260. package/src/features/chat/stores/chat-thread.store.ts +7 -1
  261. package/src/features/chat/stores/floating-session.store.ts +11 -0
  262. package/src/features/chat/utils/chat-voice-permissions.utils.test.ts +12 -1
  263. package/src/features/chat/utils/chat-voice-permissions.utils.ts +6 -1
  264. package/src/features/cron/components/__tests__/cron-config.test.tsx +4 -0
  265. package/src/features/cron/components/cron-job-detail-dialog.tsx +3 -1
  266. package/src/features/cron/components/cron-job-row.tsx +14 -8
  267. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +3 -0
  268. package/src/features/inbox/components/inbox-reader-dialog.tsx +6 -1
  269. package/src/features/inbox/pages/inbox-page.test.ts +3 -0
  270. package/src/features/inbox/pages/inbox-page.tsx +12 -4
  271. package/src/features/marketplace/components/__tests__/marketplace-page-detail.test.tsx +5 -1
  272. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +3 -0
  273. package/src/features/marketplace/components/curated-shelves/__tests__/marketplace-curated-scene-route.test.tsx +2 -0
  274. package/src/features/marketplace/components/marketplace-list-card.tsx +4 -0
  275. package/src/features/marketplace/components/mcp/__tests__/mcp-marketplace-page.test.tsx +2 -0
  276. package/src/features/marketplace/components/mcp/mcp-marketplace-card.tsx +3 -0
  277. package/src/features/notifications/components/__tests__/app-notification-toast.test.tsx +19 -0
  278. package/src/features/notifications/components/app-notification-toast.tsx +33 -15
  279. package/src/features/notifications/managers/app-notification.manager.ts +2 -0
  280. package/src/features/panel-apps/components/__tests__/panel-app-list-item.test.tsx +13 -4
  281. package/src/features/panel-apps/components/__tests__/panel-app-toolbar.test.tsx +13 -5
  282. package/src/features/panel-apps/components/panel-app-list-item.tsx +1 -1
  283. package/src/features/panel-apps/components/panel-app-main-sidebar-menu-item.tsx +5 -38
  284. package/src/features/panel-apps/components/panel-app-toolbar.tsx +7 -7
  285. package/src/features/panel-apps/index.ts +1 -1
  286. package/src/features/projects/components/project-materials.test.tsx +2 -0
  287. package/src/features/projects/components/project-skills.tsx +7 -3
  288. package/src/features/projects/components/work/project-work-item-drawer.test.tsx +2 -0
  289. package/src/features/projects/components/work/project-work-item-drawer.tsx +3 -1
  290. package/src/features/right-panel-resources/components/__tests__/page-resource-icon.test.tsx +67 -0
  291. package/src/features/right-panel-resources/components/__tests__/page-resource-sidebar-nav.test.tsx +183 -0
  292. package/src/features/right-panel-resources/components/__tests__/system-object-resource.test.tsx +42 -0
  293. package/src/features/right-panel-resources/components/page-resource-actions-menu.tsx +53 -0
  294. package/src/features/right-panel-resources/components/page-resource-icon.tsx +245 -0
  295. package/src/features/right-panel-resources/components/page-resource-sidebar-nav.tsx +119 -0
  296. package/src/features/right-panel-resources/components/system-object-resource.tsx +100 -0
  297. package/src/features/right-panel-resources/components/workspace-file-resource.tsx +56 -0
  298. package/src/features/right-panel-resources/configs/right-panel-resource-routes.config.ts +46 -3
  299. package/src/features/right-panel-resources/hooks/use-page-resource-actions.ts +190 -0
  300. package/src/features/right-panel-resources/index.ts +21 -8
  301. package/src/features/right-panel-resources/managers/__tests__/page-resource.manager.test.ts +149 -0
  302. package/src/features/right-panel-resources/managers/page-resource.manager.ts +342 -0
  303. package/src/features/right-panel-resources/pages/resource-page.tsx +114 -0
  304. package/src/features/right-panel-resources/stores/page-navigation.store.ts +55 -0
  305. package/src/features/right-panel-resources/types/page-resource.types.ts +11 -0
  306. package/src/features/right-panel-resources/utils/__tests__/right-panel-resource-route-resolver.utils.test.ts +10 -0
  307. package/src/features/right-panel-resources/utils/page-resource-identity.utils.ts +61 -0
  308. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +2 -6
  309. package/src/features/service-apps/components/__tests__/service-apps-panel.test.tsx +2 -0
  310. package/src/features/service-apps/components/service-app-list-item.tsx +6 -1
  311. package/src/features/settings/pages/providers-config-page.tsx +2 -2
  312. package/src/features/side-dock/components/__tests__/side-dock.test.tsx +9 -8
  313. package/src/features/side-dock/components/side-dock.tsx +14 -47
  314. package/src/features/side-dock/managers/side-dock.manager.ts +2 -0
  315. package/src/features/system-status/components/__tests__/desktop-update-config.test.tsx +40 -0
  316. package/src/features/system-status/components/desktop-update-config.tsx +19 -1
  317. package/src/platforms/desktop/components/__tests__/desktop-app-shell.test.tsx +2 -0
  318. package/src/platforms/desktop/components/desktop-app-shell.tsx +3 -14
  319. package/src/platforms/mobile/components/__tests__/mobile-app-shell.test.tsx +1 -0
  320. package/src/platforms/mobile/components/__tests__/mobile-bottom-nav.test.tsx +3 -2
  321. package/src/platforms/mobile/components/mobile-app-shell.tsx +3 -4
  322. package/src/platforms/mobile/components/mobile-bottom-nav.tsx +7 -7
  323. package/src/platforms/mobile/components/mobile-settings-shell.tsx +8 -3
  324. package/src/platforms/mobile/components/mobile-topbar.tsx +4 -4
  325. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +4 -3
  326. package/src/shared/components/doc-browser/__tests__/doc-browser-tab-strip.test.tsx +0 -5
  327. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +57 -73
  328. package/src/shared/components/doc-browser/__tests__/resource-link-interceptor.test.tsx +104 -0
  329. package/src/shared/components/doc-browser/doc-browser-context.tsx +5 -1
  330. package/src/shared/components/doc-browser/doc-browser-panel-parts.tsx +1 -1
  331. package/src/shared/components/doc-browser/doc-browser-tab-strip.tsx +6 -118
  332. package/src/shared/components/doc-browser/doc-browser.tsx +30 -194
  333. package/src/shared/components/doc-browser/hooks/use-doc-browser-scroll-restoration.ts +1 -1
  334. package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +11 -1
  335. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +3 -7
  336. package/src/shared/components/doc-browser/types/doc-browser.types.ts +8 -1
  337. package/src/shared/components/doc-browser/use-doc-link-interceptor.ts +30 -32
  338. package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +6 -6
  339. package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +105 -1
  340. package/src/shared/components/ui/context-menu/context-menu-items.tsx +173 -0
  341. package/src/shared/components/ui/context-menu/context-menu.tsx +99 -112
  342. package/src/shared/components/ui/dialog.tsx +4 -0
  343. package/src/shared/components/ui/overlays/sheet.tsx +4 -0
  344. package/src/shared/components/ui/popover.tsx +10 -4
  345. package/src/shared/components/workbench/__tests__/workbench-surface.manager.test.ts +70 -0
  346. package/src/shared/components/workbench/__tests__/workbench-surface.test.tsx +111 -0
  347. package/src/shared/components/workbench/managers/workbench-surface.manager.ts +120 -0
  348. package/src/shared/components/workbench/stores/workbench-surface.store.ts +83 -0
  349. package/src/shared/components/workbench/types/workbench-surface.types.ts +32 -0
  350. package/src/shared/components/workbench/utils/workbench-surface-geometry.utils.ts +46 -0
  351. package/src/shared/components/workbench/workbench-surface-toolbar.tsx +102 -0
  352. package/src/shared/components/workbench/workbench-surface.tsx +401 -0
  353. package/src/shared/hooks/use-panel-app-scroll-restoration.test.tsx +19 -0
  354. package/src/shared/hooks/use-panel-app-scroll-restoration.ts +8 -6
  355. package/src/shared/hooks/use-scroll-restoration.test.tsx +39 -2
  356. package/src/shared/hooks/use-scroll-restoration.ts +33 -33
  357. package/src/shared/lib/api/marketplace.types.ts +1 -0
  358. package/src/shared/lib/i18n/locales/en-US/chat.json +46 -1
  359. package/src/shared/lib/i18n/locales/en-US/core.json +3 -1
  360. package/src/shared/lib/i18n/locales/en-US/desktop-update.json +1 -0
  361. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +1 -1
  362. package/src/shared/lib/i18n/locales/zh-CN/chat.json +46 -1
  363. package/src/shared/lib/i18n/locales/zh-CN/core.json +11 -9
  364. package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +1 -0
  365. package/src/shared/lib/navigation-history/index.ts +1 -0
  366. package/src/shared/lib/navigation-history/navigation-history.utils.ts +1 -1
  367. package/src/shared/lib/navigation-history/scroll-restoration.manager.test.ts +11 -0
  368. package/src/shared/lib/navigation-history/scroll-restoration.manager.ts +36 -7
  369. package/src/shared/lib/navigation-history/view-memory-storage.store.test.ts +37 -0
  370. package/src/shared/lib/navigation-history/view-memory-storage.store.ts +21 -0
  371. package/src/shared/lib/transport/__tests__/browser-realtime-recovery.service.test.ts +27 -2
  372. package/src/shared/lib/transport/__tests__/local-transport.service.test.ts +20 -0
  373. package/src/shared/lib/transport/__tests__/remote.transport.test.ts +26 -0
  374. package/src/shared/lib/transport/browser-realtime-recovery.service.ts +32 -5
  375. package/src/shared/lib/transport/local-transport.service.ts +1 -6
  376. package/src/shared/lib/transport/remote-transport.service.ts +22 -1
  377. package/src/shared/lib/ui-document-title/index.ts +1 -0
  378. package/dist/assets/account-panel-BW4GbzQd.js +0 -1
  379. package/dist/assets/api-DqzQ-_3w.js +0 -13
  380. package/dist/assets/app-data-C54N2p8b.js +0 -1
  381. package/dist/assets/app-presenter-provider-CBZ_-ewx.js +0 -115
  382. package/dist/assets/appearance-settings-page-C-uZ2Wkf.js +0 -1
  383. package/dist/assets/architecture-TIHT7OUA-DEt0Abz9.js +0 -1
  384. package/dist/assets/boxes-D6uPnkGo.js +0 -1
  385. package/dist/assets/card-BhfAZv5L.js +0 -1
  386. package/dist/assets/channel-CxQkbwRD.js +0 -1
  387. package/dist/assets/channels-list-page-Bv7CVSqV.js +0 -8
  388. package/dist/assets/chevron-down-BL-yMYcX.js +0 -1
  389. package/dist/assets/chunk-2Q5K7J3B-ClVhziok.js +0 -1
  390. package/dist/assets/chunk-VAUOI2AC-DZQxkIsv.js +0 -1
  391. package/dist/assets/chunk-XXDRQBXY-BkExtw5C.js +0 -1
  392. package/dist/assets/circle-alert-lSa3LRvS.js +0 -1
  393. package/dist/assets/classDiagram-OUVF2IWQ-Bd6apBb-.js +0 -1
  394. package/dist/assets/classDiagram-v2-EOCWNBFH-CYxUZGCI.js +0 -1
  395. package/dist/assets/client-BtGBwLTs.js +0 -1
  396. package/dist/assets/config-split-page-DqAXKLmG.js +0 -1
  397. package/dist/assets/confirm-dialog-BTKCWMn6.js +0 -1
  398. package/dist/assets/createLucideIcon-BNKf0_kc.js +0 -1
  399. package/dist/assets/cynefin-VYW2F7L2-CV0bFLH9.js +0 -1
  400. package/dist/assets/desktop-capabilities-page-zLzCSB7A.js +0 -1
  401. package/dist/assets/desktop-update-config-PmofcFf6.js +0 -1
  402. package/dist/assets/dialog-Xe73hpQz.js +0 -5
  403. package/dist/assets/dist-BiIcnf9j.js +0 -1
  404. package/dist/assets/dist-C5I0v8Qn.js +0 -1
  405. package/dist/assets/dist-czPa8xFO.js +0 -1
  406. package/dist/assets/doc-browser-BJrre2S_.js +0 -1
  407. package/dist/assets/doc-browser-BPqA-zQx.js +0 -1
  408. package/dist/assets/doc-browser-context-TILuCY5c.js +0 -1
  409. package/dist/assets/ellipsis-C5YXdOUx.js +0 -1
  410. package/dist/assets/es2015-cuwbYI-l.js +0 -41
  411. package/dist/assets/eventmodeling-45OFAUF4-BzkLWWdP.js +0 -1
  412. package/dist/assets/extensions-CVUFK6Jj.js +0 -1
  413. package/dist/assets/flowDiagram-23GEKE2U-ukkCsB0j.js +0 -1
  414. package/dist/assets/form-actions-BRESe-m_.js +0 -1
  415. package/dist/assets/gitGraph-TEB2WS4Q-BYFhT0Q5.js +0 -1
  416. package/dist/assets/i18n-provider-BPRq6S7O.js +0 -1
  417. package/dist/assets/info-DKCQHKI2-CTmlJdcH.js +0 -1
  418. package/dist/assets/katex-DbZC06Q5.js +0 -1
  419. package/dist/assets/keyboard-shortcuts-settings-page-CScSXYS4.js +0 -1
  420. package/dist/assets/loader-circle-K1BDdHR5.js +0 -1
  421. package/dist/assets/login-page-Dlyvp-81.js +0 -1
  422. package/dist/assets/login-page-f8qQ4xKY.js +0 -1
  423. package/dist/assets/logo-badge-C-5-zim6.js +0 -1
  424. package/dist/assets/main-D2dWy8fM.css +0 -1
  425. package/dist/assets/main-DMNmwcJE.js +0 -2
  426. package/dist/assets/main-i18n-catalog.config-DZ-5ollN.js +0 -1
  427. package/dist/assets/mcp-marketplace-page-FfIfEo6w.js +0 -10
  428. package/dist/assets/mcp-marketplace-page-sH7VptN_.js +0 -1
  429. package/dist/assets/model-config-page-Bcm6-pCX.js +0 -1
  430. package/dist/assets/navigation-link-BAQjgx2F.js +0 -3
  431. package/dist/assets/packet-7NZHBO7P-BbrI0ZlN.js +0 -1
  432. package/dist/assets/panel-app-B39rJPj8.js +0 -1
  433. package/dist/assets/panel-app-i18n-catalog.config-p3qAY_Eq.js +0 -1
  434. package/dist/assets/panelStandalone-By-6dDXS.js +0 -2
  435. package/dist/assets/pie-RZYD4A2V-B7zE1ZIr.js +0 -1
  436. package/dist/assets/plus-LA8-jpxP.js +0 -1
  437. package/dist/assets/popover-NkrFlWHp.js +0 -1
  438. package/dist/assets/privacy-settings-page-B1sHLAc1.js +0 -1
  439. package/dist/assets/projects-Voql-cvx.js +0 -1
  440. package/dist/assets/provider-models-hrHMcHqg.js +0 -1
  441. package/dist/assets/provider-scoped-model-input-BQsugx1v.js +0 -1
  442. package/dist/assets/providers-config-page-BDEdHJbw.js +0 -1
  443. package/dist/assets/pwa-CzqfYjFx.js +0 -1
  444. package/dist/assets/radar-I7S5WNFK-1X_q11Ed.js +0 -1
  445. package/dist/assets/railroad-3IZDKUUU-CIXnuFyE.js +0 -1
  446. package/dist/assets/railroad-abnf-AHOZXSZD-D6ImKl2r.js +0 -1
  447. package/dist/assets/railroad-ebnf-EBAXGLYW-2j9d3twU.js +0 -1
  448. package/dist/assets/railroad-peg-LSFZ7HO6-DMVaJGbm.js +0 -1
  449. package/dist/assets/remote-BekqL5nA.js +0 -1
  450. package/dist/assets/runtime-config-page-BH9uF4u_.js +0 -1
  451. package/dist/assets/search-CUe41wjm.js +0 -1
  452. package/dist/assets/search-config-page-DWKlMHgH.js +0 -1
  453. package/dist/assets/secrets-config-page-DiQL088Y.js +0 -3
  454. package/dist/assets/security-config-DmTDKKY4.js +0 -1
  455. package/dist/assets/select-CG5YWnwe.js +0 -1
  456. package/dist/assets/service-apps-panel-CEnyYsQp.js +0 -1
  457. package/dist/assets/skeleton-Drvn83YW.js +0 -1
  458. package/dist/assets/stateDiagram-v2-6OUMAXLB-OlIMT57r.js +0 -1
  459. package/dist/assets/swimlanesDiagram-G3AALYLV-sLThrh07.js +0 -8
  460. package/dist/assets/tabs-BuE0qKMh.js +0 -1
  461. package/dist/assets/tag-chip-B1AYPOKL.js +0 -1
  462. package/dist/assets/theme-provider-DzvAi3pe.js +0 -1
  463. package/dist/assets/tooltip-DYcuWhuP.js +0 -1
  464. package/dist/assets/trash-2-BPPYt2NV.js +0 -1
  465. package/dist/assets/treeView-QDETBFTQ-CCFyazDE.js +0 -1
  466. package/dist/assets/treemap-6X3UGDF4-D6wvq1Hz.js +0 -1
  467. package/dist/assets/use-config-BEdbtpD4.js +0 -1
  468. package/dist/assets/use-desktop-capabilities-BkuRd2cY.js +0 -1
  469. package/dist/assets/use-panel-app-scroll-restoration-ZnicIfo3.js +0 -1
  470. package/dist/assets/use-viewport-layout-BS18drMT.js +0 -1
  471. package/dist/assets/utils-CBZPzC_b.js +0 -8
  472. package/dist/assets/wardley-OPB4EBWU-BRzaRyFf.js +0 -1
  473. package/dist/assets/x-DdXOqLnX.js +0 -1
  474. package/src/features/panel-apps/components/__tests__/panel-app-main-sidebar-nav.test.tsx +0 -219
  475. package/src/features/panel-apps/components/panel-app-main-sidebar-nav.tsx +0 -258
  476. package/src/shared/components/doc-browser/utils/doc-browser-floating-panel.utils.ts +0 -83
  477. /package/dist/assets/{array-D0DyKZdT.js → array-BV9OtnO8.js} +0 -0
  478. /package/dist/assets/{chunk-KEIR6QF5-CuZFOa6q.js → chunk-KEIR6QF5-Cx-8EJ4_.js} +0 -0
  479. /package/dist/assets/{chunk-Y2CYZVJY-Frut-1TF.js → chunk-Y2CYZVJY-Dy1ufvjf.js} +0 -0
  480. /package/dist/assets/{config-hints-B_C9DAp5.js → config-hints-DbmiyTKg.js} +0 -0
  481. /package/dist/assets/{cytoscape.esm-BibuhnZD.js → cytoscape.esm-CSCjuT4Z.js} +0 -0
  482. /package/dist/assets/{defaultLocale-q7sRUXPc.js → defaultLocale-DWTiNsbT.js} +0 -0
  483. /package/dist/assets/{dist-DhMddrrH.js → dist-BVCSkfWY.js} +0 -0
  484. /package/dist/assets/{graphlib-BM63WsW3.js → graphlib-B1yb1Wl8.js} +0 -0
  485. /package/dist/assets/{host-capabilities-B107nwS3.js → host-capabilities-DuIFVsvM.js} +0 -0
  486. /package/dist/assets/{init-CRMkf9sL.js → init-BF6GH5oe.js} +0 -0
  487. /package/dist/assets/{jszip.min-6thm2J_a.js → jszip.min-D12teKzP.js} +0 -0
  488. /package/dist/assets/{katex-B26hhTOT.js → katex-CsAM73R9.js} +0 -0
  489. /package/dist/assets/{middleware-0o3JF3tS.js → middleware-B--6mAUM.js} +0 -0
  490. /package/dist/assets/{path-BFMmafCM.js → path-C56XkznJ.js} +0 -0
  491. /package/dist/assets/{rough.esm-5Tjchx1D.js → rough.esm-CGfeEbtE.js} +0 -0
  492. /package/dist/assets/{xlsx-BC8ibjXK.js → xlsx-sds5nUpL.js} +0 -0
@@ -13,7 +13,9 @@
13
13
  "advanced": "Advanced",
14
14
  "settings": "Settings",
15
15
  "settingsGroupBasic": "Basic Configuration",
16
- "settingsGroupAdvanced": "Advanced Configuration",
16
+ "settingsGroupCommon": "Common Settings",
17
+ "settingsGroupSecurity": "Security & Privacy",
18
+ "settingsGroupSystem": "System & Extensions",
17
19
  "appearance": "Appearance",
18
20
  "keyboardShortcuts": "Keyboard shortcuts",
19
21
  "keyboardShortcutsDesktopOnly": "Keyboard shortcuts can be configured on desktop. Use the microphone button on mobile.",
@@ -63,6 +63,7 @@
63
63
  "desktopUpdatesDownloadProgressUnknown": "Downloading",
64
64
  "desktopUpdatesBlockedTitle": "Update Blocked",
65
65
  "desktopUpdatesBlockedDescription": "Resolve the current installation requirement before continuing the update.",
66
+ "desktopUpdatesManualPortableDownload": "Download Latest Portable Edition",
66
67
  "desktopUpdatesBlockedRootCause.signature-verification-unavailable": "Root cause: missing update public key; install a configured build or ask the maintainer to set the key.",
67
68
  "desktopUpdatesBlockedRootCause.host-too-old": "Root cause: the host is too old for this runtime bundle; upgrade the NextClaw launcher first.",
68
69
  "desktopUpdatesBlockedRootCause.unsupported-installation": "Root cause: this installation or update source does not support auto-update; use a configured build.",
@@ -18,7 +18,7 @@
18
18
  "docBrowserCloseTab": "Close Tab",
19
19
  "docBrowserTabUntitled": "Untitled",
20
20
  "docBrowserTabMoreActions": "More tab actions",
21
- "docBrowserAddToChat": "Add to Chat",
21
+ "docBrowserAddToChat": "Add to chat",
22
22
  "sideDockPinCurrent": "Pin to SideDock",
23
23
  "sideDockUnpinCurrent": "Remove from SideDock",
24
24
  "sideDockBuiltInDocked": "Built-in shortcut",
@@ -1,4 +1,34 @@
1
1
  {
2
+ "pageLayoutActions": "布局与位置",
3
+ "pagePinLeft": "固定到左侧页面",
4
+ "pageUnpinLeft": "从左侧页面移除",
5
+ "pageCopyUri": "复制资源链接",
6
+ "pageCopyFailed": "无法复制链接,请重试",
7
+ "pageActions": "页面操作",
8
+ "pageSidebar": "页面",
9
+ "resourcePageTitle": "资源",
10
+ "resourceRetry": "重试",
11
+ "resourceNotFound": "资源已删除或不存在",
12
+ "resourceInvalid": "此资源类型尚未接入,或 URI 格式不正确",
13
+ "resourceLoadFailed": "资源暂时加载失败,请重试",
14
+ "pageUnavailable": "页面不可用或链接不受支持",
15
+ "workbenchOpenMain": "在主区域打开",
16
+ "workbenchDock": "停靠到侧栏",
17
+ "workbenchFloatGroup": "悬浮此视图组",
18
+ "workbenchExpand": "展开视图",
19
+ "workbenchCollapse": "收起视图",
20
+ "workbenchRestoreSize": "还原大小",
21
+ "workbenchMaximize": "最大化",
22
+ "workbenchCloseView": "关闭视图",
23
+ "workbenchHideGroup": "隐藏视图组",
24
+ "workbenchResize": "调整侧栏宽度",
25
+ "workbenchGlobalGroup": "全局工作区",
26
+ "workbenchSessionGroup": "会话工作台",
27
+ "workbenchMoveGlobal": "移动到全局右侧栏",
28
+ "workbenchFloatView": "在悬浮窗中打开",
29
+ "workbenchCloseTab": "关闭标签",
30
+ "workbenchFileUnavailable": "此文件视图不可用,请从原会话重新打开。",
31
+ "chatSidebarCloseSearch": "关闭搜索",
2
32
  "chatPageTitle": "Agent 对话",
3
33
  "chatPageDescription": "在 UI 内直接与 Agent 交互,支持多会话与多 Agent 切换。",
4
34
  "chatRefresh": "刷新",
@@ -252,7 +282,12 @@
252
282
  "chatHistoryLoadFailed": "较早消息加载失败",
253
283
  "chatHistoryRetry": "重试",
254
284
  "chatProcessSummaryProcessed": "已处理",
255
- "chatProcessSummaryToolCalls": "{count} 次工具调用",
285
+ "chatProcessSummaryError": "处理失败",
286
+ "chatProcessSummaryStopped": "已停止",
287
+ "chatProcessDurationHoursMinutes": "{hours}小时{minutes}分钟",
288
+ "chatProcessDurationHours": "{hours}小时",
289
+ "chatProcessDurationMinutesSeconds": "{minutes}分钟{seconds}秒",
290
+ "chatProcessDurationSeconds": "{seconds}秒",
256
291
  "chatToolPayloadLoading": "正在加载详情",
257
292
  "chatToolPayloadLoadFailed": "详情加载失败,点击重试",
258
293
  "chatToolActivityShowMore": "继续显示 {count} 项(剩余 {remaining} 项)",
@@ -610,6 +645,15 @@
610
645
  "chatBackgroundReplyFallbackTitle": "有新回复",
611
646
  "chatBackgroundReplyFallbackPreview": "回复已完成,点击查看。",
612
647
  "chatBackgroundReplyOpenAriaLabel": "打开“{title}”的新回复",
648
+ "chatFloatingExpand": "在悬浮窗中对话",
649
+ "chatFloatingConversation": "悬浮会话",
650
+ "chatFloatingMinimize": "收起会话",
651
+ "chatFloatingRestore": "展开会话",
652
+ "chatFloatingOpenMain": "转到主会话",
653
+ "chatFloatingClose": "关闭悬浮会话",
654
+ "chatPanelDock": "停靠到右侧栏",
655
+ "chatPanelOpen": "在右侧栏中对话",
656
+ "chatPanelUnavailable": "无法打开此会话,请从会话列表重新打开。",
613
657
  "chatWelcomeTitle": "今天想完成什么?",
614
658
  "chatWelcomeContextLabel": "任务上下文",
615
659
  "chatWelcomeProjectPickerLabel": "选择工作目录",
@@ -654,6 +698,7 @@
654
698
  "chatInputVoiceNoDevice": "没有检测到麦克风。请连接或启用输入设备,再检测重试。",
655
699
  "chatInputVoiceDeviceBusy": "麦克风无法读取,可能被其他应用占用或被系统限制。请关闭其他录音应用,检查输入设备后重试。",
656
700
  "chatInputVoiceServiceDenied": "浏览器拒绝了语音识别服务。请检查浏览器的语音服务设置或组织策略,或使用支持语音识别的浏览器。",
701
+ "chatInputVoiceInsecureContext": "当前页面通过不安全的 HTTP 地址打开,浏览器会禁用麦克风。请为 VPS 配置 HTTPS;仅在本机访问时可使用 localhost 或 127.0.0.1。",
657
702
  "chatInputVoiceUnsupported": "当前浏览器不支持语音输入。",
658
703
  "chatInputVoiceNoSpeech": "没有听清,请再试一次。",
659
704
  "chatInputVoiceFailed": "语音输入失败,请重试。",
@@ -3,7 +3,7 @@
3
3
  "model": "模型",
4
4
  "searchChannels": "搜索渠道",
5
5
  "providers": "提供商",
6
- "extensions": "Extensions",
6
+ "extensions": "扩展",
7
7
  "channels": "渠道",
8
8
  "cron": "定时任务",
9
9
  "secrets": "密钥管理",
@@ -13,7 +13,9 @@
13
13
  "advanced": "高级",
14
14
  "settings": "设置",
15
15
  "settingsGroupBasic": "基础配置",
16
- "settingsGroupAdvanced": "高级配置",
16
+ "settingsGroupCommon": "常用设置",
17
+ "settingsGroupSecurity": "安全与隐私",
18
+ "settingsGroupSystem": "系统与扩展",
17
19
  "appearance": "外观",
18
20
  "keyboardShortcuts": "快捷键",
19
21
  "keyboardShortcutsDesktopOnly": "请在桌面端配置键盘快捷键。手机可使用麦克风按钮输入。",
@@ -139,15 +141,15 @@
139
141
  "providersDefaultDescription": "为你的智能体配置 AI 服务",
140
142
  "providersEmptyTitle": "尚未配置提供商",
141
143
  "providersEmptyDescription": "添加一个 AI 提供商后即可开始使用。",
142
- "extensionsPageTitle": "Extensions 管理",
143
- "extensionsPageDescription": "查看已发现的 Extension、能力和当前运行状态。",
144
+ "extensionsPageTitle": "扩展管理",
145
+ "extensionsPageDescription": "查看已发现的扩展、能力和当前运行状态。",
144
146
  "extensionsRefresh": "刷新",
145
- "extensionsLifecycleDescription": "Extension 由运行时按渠道和会话持续关注关系按需启停;这里集中查看全局能力和运行状态。",
146
- "extensionsLoading": "正在加载 Extensions…",
147
- "extensionsLoadFailed": "Extensions 加载失败。",
147
+ "extensionsLifecycleDescription": "扩展由运行时按渠道和会话持续关注关系按需启停;这里集中查看全局能力和运行状态。",
148
+ "extensionsLoading": "正在加载扩展…",
149
+ "extensionsLoadFailed": "扩展加载失败。",
148
150
  "extensionsRetry": "重试",
149
- "extensionsEmpty": "暂无已发现的 Extension",
150
- "extensionsEmptyDescription": "安装或放置 Extension 后,重新刷新此页面。",
151
+ "extensionsEmpty": "暂无已发现的扩展",
152
+ "extensionsEmptyDescription": "安装或放置扩展后,重新刷新此页面。",
151
153
  "extensionsTotal": "全部",
152
154
  "extensionsRunning": "运行中",
153
155
  "extensionsWithObservations": "支持持续关注",
@@ -63,6 +63,7 @@
63
63
  "desktopUpdatesDownloadProgressUnknown": "正在下载",
64
64
  "desktopUpdatesBlockedTitle": "更新暂时无法继续",
65
65
  "desktopUpdatesBlockedDescription": "当前安装环境需要先处理阻塞项,之后才能继续更新。",
66
+ "desktopUpdatesManualPortableDownload": "下载最新 Portable Edition",
66
67
  "desktopUpdatesBlockedRootCause.signature-verification-unavailable": "根因:缺少更新签名公钥,无法验证更新包来源;请安装包含正确更新配置的新版本,或由维护者配置更新公钥。",
67
68
  "desktopUpdatesBlockedRootCause.host-too-old": "根因:当前宿主版本太旧,不满足新运行包的最低宿主版本要求;请先升级 NextClaw 启动器。",
68
69
  "desktopUpdatesBlockedRootCause.unsupported-installation": "根因:当前安装形态或更新源配置不支持自动更新;请安装支持自动更新的版本,或由维护者补齐更新源配置。",
@@ -1,2 +1,3 @@
1
1
  export * from './navigation-history.utils';
2
2
  export * from './scroll-restoration.manager';
3
+ export { ViewMemoryStorage } from './view-memory-storage.store';
@@ -40,7 +40,7 @@ export function pushNavigationHistoryEntry<Entry>(
40
40
  index: normalizedIndex,
41
41
  };
42
42
  }
43
- const entries = [...history.entries.slice(0, normalizedIndex + 1), entry];
43
+ const entries = [...history.entries.slice(0, normalizedIndex + 1), entry].slice(-100);
44
44
  return {
45
45
  entries,
46
46
  index: entries.length - 1,
@@ -35,3 +35,14 @@ describe("ScrollRestorationManager", () => {
35
35
  expect(manager.read("second")).toBeNull();
36
36
  });
37
37
  });
38
+
39
+ it("restores reading memory after reload without reviving deleted entries", () => {
40
+ sessionStorage.clear();
41
+ const first = new ScrollRestorationManager(2, sessionStorage);
42
+ first.save('file:one', { x: 2, y: 200 });
43
+ first.save('file:two', { x: 0, y: 300 });
44
+ const reloaded = new ScrollRestorationManager(2, sessionStorage);
45
+ expect(reloaded.read('file:one')).toEqual({ x: 2, y: 200 });
46
+ reloaded.delete('file:one');
47
+ expect(new ScrollRestorationManager(2, sessionStorage).read('file:one')).toBeNull();
48
+ });
@@ -15,15 +15,37 @@ function normalizeKey(key: string): string | null {
15
15
  return normalized ? normalized : null;
16
16
  }
17
17
 
18
- /** Owns bounded, in-memory scroll positions for app-internal return navigation. */
18
+ /** Shared, bounded reading memory; optional session storage survives a page reload. */
19
19
  export class ScrollRestorationManager {
20
20
  private readonly positions = new Map<string, ScrollRestorationPosition>();
21
21
 
22
22
  public constructor(
23
23
  private readonly capacity = DEFAULT_SCROLL_RESTORATION_CAPACITY,
24
- ) {}
24
+ private readonly storage?: Storage,
25
+ ) {
26
+ try {
27
+ const saved: unknown = JSON.parse(storage?.getItem('nextclaw.view-memory.v1') ?? 'null');
28
+ if (Array.isArray(saved)) for (const entry of saved.slice(-capacity)) {
29
+ if (!Array.isArray(entry) || typeof entry[0] !== 'string') continue;
30
+ const value = entry[1];
31
+ if (value && typeof value.x === 'number' && typeof value.y === 'number' && Number.isFinite(value.x) && Number.isFinite(value.y)) this.positions.set(entry[0], value);
32
+ }
33
+ } catch { /* Private mode, stale data or quota cannot block navigation. */ }
34
+ }
35
+
36
+ private persist = (): void => {
37
+ try {
38
+ const entries = [...this.positions];
39
+ let json = JSON.stringify(entries);
40
+ while (json.length > 512_000 && entries.length > 0) {
41
+ entries.shift();
42
+ json = JSON.stringify(entries);
43
+ }
44
+ this.storage?.setItem('nextclaw.view-memory.v1', json);
45
+ } catch { /* Keep the in-memory position when browser storage is unavailable. */ }
46
+ }
25
47
 
26
- public save(key: string, position: ScrollRestorationPosition): void {
48
+ public save = (key: string, position: ScrollRestorationPosition): void => {
27
49
  const normalizedKey = normalizeKey(key);
28
50
  if (!normalizedKey) return;
29
51
 
@@ -38,23 +60,30 @@ export class ScrollRestorationManager {
38
60
  if (!oldestKey) return;
39
61
  this.positions.delete(oldestKey);
40
62
  }
63
+ this.persist();
41
64
  }
42
65
 
43
- public read(key: string): ScrollRestorationPosition | null {
66
+ public read = (key: string): ScrollRestorationPosition | null => {
44
67
  const normalizedKey = normalizeKey(key);
45
68
  if (!normalizedKey) return null;
46
69
  const position = this.positions.get(normalizedKey);
47
70
  return position ? { ...position } : null;
48
71
  }
49
72
 
50
- public delete(key: string): void {
73
+ public delete = (key: string): void => {
51
74
  const normalizedKey = normalizeKey(key);
52
75
  if (normalizedKey) this.positions.delete(normalizedKey);
76
+ this.persist();
53
77
  }
54
78
 
55
- public clear(): void {
79
+ public clear = (): void => {
56
80
  this.positions.clear();
81
+ this.persist();
57
82
  }
58
83
  }
59
84
 
60
- export const scrollRestorationManager = new ScrollRestorationManager();
85
+ function getReadingMemoryStorage(): Storage | undefined {
86
+ try { return typeof window === 'undefined' ? undefined : window.sessionStorage; } catch { return undefined; }
87
+ }
88
+
89
+ export const scrollRestorationManager = new ScrollRestorationManager(DEFAULT_SCROLL_RESTORATION_CAPACITY, getReadingMemoryStorage());
@@ -0,0 +1,37 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { ViewMemoryStorage } from "./view-memory-storage.store";
3
+
4
+ describe("best-effort view memory", () => {
5
+ it("tolerates access denial and quota failures without breaking view actions", () => {
6
+ const unavailable = new ViewMemoryStorage(() => {
7
+ throw new Error("denied");
8
+ });
9
+ expect(unavailable.getItem("view")).toBeNull();
10
+ expect(() => unavailable.setItem("view", "{}")).not.toThrow();
11
+ expect(() => unavailable.removeItem("view")).not.toThrow();
12
+ const quota = new ViewMemoryStorage(
13
+ () =>
14
+ ({
15
+ getItem: () => null,
16
+ setItem: () => {
17
+ throw new Error("quota");
18
+ },
19
+ removeItem: vi.fn(),
20
+ }) as unknown as Storage,
21
+ );
22
+ expect(() => quota.setItem("view", "{}")).not.toThrow();
23
+ });
24
+ it("preserves the existing storage key and serialized state", () => {
25
+ const storage = {
26
+ getItem: vi.fn(() => '{"version":1}'),
27
+ setItem: vi.fn(),
28
+ removeItem: vi.fn(),
29
+ };
30
+ const memory = new ViewMemoryStorage(() => storage as unknown as Storage);
31
+ expect(memory.getItem("view")).toBe('{"version":1}');
32
+ memory.setItem("view", "snapshot");
33
+ memory.removeItem("view");
34
+ expect(storage.setItem).toHaveBeenCalledWith("view", "snapshot");
35
+ expect(storage.removeItem).toHaveBeenCalledWith("view");
36
+ });
37
+ });
@@ -0,0 +1,21 @@
1
+ import type { StateStorage } from 'zustand/middleware';
2
+
3
+ /** Owns best-effort browser IO; denied storage never blocks view navigation. */
4
+ export class ViewMemoryStorage implements StateStorage {
5
+ constructor(private readonly resolveStorage: () => Storage = () => window.localStorage) {}
6
+
7
+ getItem = (key: string): string | null => {
8
+ try { return this.resolveStorage().getItem(key); }
9
+ catch { return null; }
10
+ };
11
+
12
+ setItem = (key: string, value: string): void => {
13
+ try { this.resolveStorage().setItem(key, value); }
14
+ catch { /* Keep the active in-memory view usable. */ }
15
+ };
16
+
17
+ removeItem = (key: string): void => {
18
+ try { this.resolveStorage().removeItem(key); }
19
+ catch { /* Storage may be blocked or full. */ }
20
+ };
21
+ }
@@ -1,12 +1,17 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
2
2
  import { BrowserRealtimeRecoveryService } from '@/shared/lib/transport/browser-realtime-recovery.service';
3
3
 
4
4
  describe('BrowserRealtimeRecoveryService', () => {
5
+ beforeEach(() => {
6
+ vi.useFakeTimers();
7
+ });
8
+
5
9
  afterEach(() => {
6
10
  vi.restoreAllMocks();
11
+ vi.useRealTimers();
7
12
  });
8
13
 
9
- it('requests recovery only when the page can actively reconnect', () => {
14
+ it('requests recovery for every supported foreground lifecycle signal', () => {
10
15
  let visibilityState: DocumentVisibilityState = 'hidden';
11
16
  vi.spyOn(document, 'visibilityState', 'get').mockImplementation(() => visibilityState);
12
17
  const requestRecovery = vi.fn();
@@ -18,11 +23,19 @@ describe('BrowserRealtimeRecoveryService', () => {
18
23
 
19
24
  visibilityState = 'visible';
20
25
  document.dispatchEvent(new Event('visibilitychange'));
26
+ window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: true }));
27
+ window.dispatchEvent(new Event('focus'));
21
28
  window.dispatchEvent(new Event('online'));
29
+ expect(requestRecovery).toHaveBeenCalledTimes(1);
30
+
31
+ vi.advanceTimersByTime(250);
32
+ window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: true }));
22
33
  expect(requestRecovery).toHaveBeenCalledTimes(2);
23
34
 
24
35
  recovery.stop();
25
36
  document.dispatchEvent(new Event('visibilitychange'));
37
+ window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: true }));
38
+ window.dispatchEvent(new Event('focus'));
26
39
  expect(requestRecovery).toHaveBeenCalledTimes(2);
27
40
  });
28
41
 
@@ -39,4 +52,16 @@ describe('BrowserRealtimeRecoveryService', () => {
39
52
  recovery.stop();
40
53
  recovery.stop();
41
54
  });
55
+
56
+ it('does not replace the first connection for an ordinary initial pageshow', () => {
57
+ vi.spyOn(document, 'visibilityState', 'get').mockReturnValue('visible');
58
+ const requestRecovery = vi.fn();
59
+ const recovery = new BrowserRealtimeRecoveryService(requestRecovery);
60
+
61
+ recovery.start();
62
+ window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: false }));
63
+
64
+ expect(requestRecovery).not.toHaveBeenCalled();
65
+ recovery.stop();
66
+ });
42
67
  });
@@ -38,11 +38,13 @@ class MockWebSocket {
38
38
  describe('LocalAppTransport browser connection recovery', () => {
39
39
  beforeEach(() => {
40
40
  MockWebSocket.instances = [];
41
+ vi.useFakeTimers();
41
42
  vi.stubGlobal('WebSocket', MockWebSocket as unknown as typeof WebSocket);
42
43
  });
43
44
 
44
45
  afterEach(() => {
45
46
  vi.restoreAllMocks();
47
+ vi.useRealTimers();
46
48
  vi.unstubAllGlobals();
47
49
  });
48
50
 
@@ -70,6 +72,7 @@ describe('LocalAppTransport browser connection recovery', () => {
70
72
 
71
73
  expect(MockWebSocket.instances).toHaveLength(2);
72
74
  expect(handler).toHaveBeenLastCalledWith({ type: 'connection.open', payload: {} });
75
+ vi.advanceTimersByTime(250);
73
76
  window.dispatchEvent(new Event('online'));
74
77
  const secondReplacement = MockWebSocket.instances[2];
75
78
  secondReplacement?.open();
@@ -82,4 +85,21 @@ describe('LocalAppTransport browser connection recovery', () => {
82
85
  window.dispatchEvent(new Event('online'));
83
86
  expect(MockWebSocket.instances).toHaveLength(3);
84
87
  });
88
+
89
+ it('replaces a frozen connecting socket when the page regains focus', () => {
90
+ vi.spyOn(document, 'visibilityState', 'get').mockReturnValue('visible');
91
+ const transport = new LocalAppTransport({ apiBase: 'https://vps.example.com' });
92
+ const handler = vi.fn();
93
+ const unsubscribe = transport.subscribe(handler);
94
+ const frozenSocket = MockWebSocket.instances[0];
95
+
96
+ window.dispatchEvent(new Event('focus'));
97
+
98
+ expect(frozenSocket?.close).toHaveBeenCalledTimes(1);
99
+ expect(MockWebSocket.instances).toHaveLength(2);
100
+ expect(handler).toHaveBeenCalledWith({ type: 'connection.close', payload: {} });
101
+ MockWebSocket.instances[1]?.open();
102
+ expect(handler).toHaveBeenLastCalledWith({ type: 'connection.open', payload: {} });
103
+ unsubscribe();
104
+ });
85
105
  });
@@ -185,6 +185,7 @@ describe('RemoteSessionMultiplexTransport request path', () => {
185
185
  await pendingFailure;
186
186
  await Promise.resolve();
187
187
  expect(replacementSocket?.sent).toHaveLength(0);
188
+ vi.advanceTimersByTime(250);
188
189
  window.dispatchEvent(new Event('online'));
189
190
  const secondReplacement = MockWebSocket.instances[2];
190
191
  secondReplacement?.open();
@@ -197,4 +198,29 @@ describe('RemoteSessionMultiplexTransport request path', () => {
197
198
  expect(MockWebSocket.instances).toHaveLength(3);
198
199
  unsubscribe();
199
200
  });
201
+
202
+ it('abandons a frozen connecting socket immediately when the page is shown again', async () => {
203
+ vi.spyOn(document, 'visibilityState', 'get').mockReturnValue('visible');
204
+ const transport = new RemoteSessionMultiplexTransport({
205
+ mode: 'remote',
206
+ protocolVersion: 1,
207
+ wsPath: '/_remote/ws'
208
+ }, 'https://remote.claw.cool');
209
+
210
+ const handler = vi.fn();
211
+ const unsubscribe = transport.subscribe(handler);
212
+ const frozenSocket = MockWebSocket.instances[0];
213
+
214
+ window.dispatchEvent(new PageTransitionEvent('pageshow', { persisted: true }));
215
+ await Promise.resolve();
216
+
217
+ expect(frozenSocket?.readyState).toBe(MockWebSocket.CLOSED);
218
+ expect(MockWebSocket.instances).toHaveLength(2);
219
+ expect(handler).toHaveBeenCalledWith({ type: 'connection.close', payload: {} });
220
+
221
+ MockWebSocket.instances[1]?.open();
222
+ await Promise.resolve();
223
+ expect(handler).toHaveBeenLastCalledWith({ type: 'connection.open', payload: {} });
224
+ unsubscribe();
225
+ });
200
226
  });
@@ -1,5 +1,8 @@
1
+ const RECOVERY_SIGNAL_COOLDOWN_MS = 250;
2
+
1
3
  export class BrowserRealtimeRecoveryService {
2
4
  private started = false;
5
+ private recoveryCooldownId: number | null = null;
3
6
 
4
7
  constructor(private readonly requestRecovery: () => void) {}
5
8
 
@@ -10,6 +13,8 @@ export class BrowserRealtimeRecoveryService {
10
13
  this.started = true;
11
14
  document.addEventListener('visibilitychange', this.handleVisibilityChange);
12
15
  window.addEventListener('online', this.handleOnline);
16
+ window.addEventListener('pageshow', this.handlePageShow);
17
+ window.addEventListener('focus', this.handleForegroundSignal);
13
18
  };
14
19
 
15
20
  stop = (): void => {
@@ -19,17 +24,39 @@ export class BrowserRealtimeRecoveryService {
19
24
  this.started = false;
20
25
  document.removeEventListener('visibilitychange', this.handleVisibilityChange);
21
26
  window.removeEventListener('online', this.handleOnline);
27
+ window.removeEventListener('pageshow', this.handlePageShow);
28
+ window.removeEventListener('focus', this.handleForegroundSignal);
29
+ if (this.recoveryCooldownId !== null) {
30
+ window.clearTimeout(this.recoveryCooldownId);
31
+ this.recoveryCooldownId = null;
32
+ }
22
33
  };
23
34
 
24
35
  private readonly handleVisibilityChange = (): void => {
25
- if (document.visibilityState === 'visible') {
26
- this.requestRecovery();
27
- }
36
+ this.requestRecoveryIfVisible();
28
37
  };
29
38
 
30
39
  private readonly handleOnline = (): void => {
31
- if (document.visibilityState === 'visible') {
32
- this.requestRecovery();
40
+ this.requestRecoveryIfVisible();
41
+ };
42
+
43
+ private readonly handleForegroundSignal = (): void => {
44
+ this.requestRecoveryIfVisible();
45
+ };
46
+
47
+ private readonly handlePageShow = (event: PageTransitionEvent): void => {
48
+ if (event.persisted) {
49
+ this.requestRecoveryIfVisible();
50
+ }
51
+ };
52
+
53
+ private readonly requestRecoveryIfVisible = (): void => {
54
+ if (document.visibilityState !== 'visible' || this.recoveryCooldownId !== null) {
55
+ return;
33
56
  }
57
+ this.requestRecovery();
58
+ this.recoveryCooldownId = window.setTimeout(() => {
59
+ this.recoveryCooldownId = null;
60
+ }, RECOVERY_SIGNAL_COOLDOWN_MS);
34
61
  };
35
62
  }
@@ -54,7 +54,6 @@ class LocalRealtimeGateway {
54
54
  private socket: WebSocket | null = null;
55
55
  private reconnectTimer: number | null = null;
56
56
  private manualClose = false;
57
- private replacingAfterBrowserRecovery = false;
58
57
  private subscribers = new Set<EventHandler>();
59
58
  private readonly browserRecovery = new BrowserRealtimeRecoveryService(() => {
60
59
  this.replaceSocket();
@@ -95,7 +94,6 @@ class LocalRealtimeGateway {
95
94
  this.socket = socket;
96
95
 
97
96
  socket.onopen = () => {
98
- this.replacingAfterBrowserRecovery = false;
99
97
  this.emit({ type: 'connection.open', payload: {} });
100
98
  };
101
99
 
@@ -113,7 +111,6 @@ class LocalRealtimeGateway {
113
111
  };
114
112
 
115
113
  socket.onclose = () => {
116
- this.replacingAfterBrowserRecovery = false;
117
114
  this.emit({ type: 'connection.close', payload: {} });
118
115
  this.socket = null;
119
116
  if (!this.manualClose && this.subscribers.size > 0) {
@@ -133,10 +130,9 @@ class LocalRealtimeGateway {
133
130
  };
134
131
 
135
132
  private replaceSocket = (): void => {
136
- if (this.subscribers.size === 0 || this.replacingAfterBrowserRecovery) {
133
+ if (this.subscribers.size === 0) {
137
134
  return;
138
135
  }
139
- this.replacingAfterBrowserRecovery = true;
140
136
  if (this.reconnectTimer !== null) {
141
137
  window.clearTimeout(this.reconnectTimer);
142
138
  this.reconnectTimer = null;
@@ -156,7 +152,6 @@ class LocalRealtimeGateway {
156
152
 
157
153
  private disconnect = (): void => {
158
154
  this.manualClose = true;
159
- this.replacingAfterBrowserRecovery = false;
160
155
  if (this.reconnectTimer !== null) {
161
156
  window.clearTimeout(this.reconnectTimer);
162
157
  this.reconnectTimer = null;
@@ -87,9 +87,16 @@ function createId(prefix: string): string {
87
87
 
88
88
  const REMOTE_REQUEST_TIMEOUT_MS = 15_000;
89
89
 
90
+ class RemoteBrowserRecoveryReplacementError extends Error {
91
+ constructor() {
92
+ super('Remote transport connection replaced after browser recovery.');
93
+ }
94
+ }
95
+
90
96
  export class RemoteSessionMultiplexTransport implements AppTransport {
91
97
  private socket: WebSocket | null = null;
92
98
  private connectPromise: Promise<void> | null = null;
99
+ private rejectConnect: ((error: Error) => void) | null = null;
93
100
  private connectTimeoutId: number | null = null;
94
101
  private reconnectTimer: number | null = null;
95
102
  private manualClose = false;
@@ -221,6 +228,9 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
221
228
  this.subscribers.add(handler);
222
229
  this.browserRecovery.start();
223
230
  void this.ensureSocket().catch((error) => {
231
+ if (error instanceof RemoteBrowserRecoveryReplacementError) {
232
+ return;
233
+ }
224
234
  handler({
225
235
  type: 'connection.error',
226
236
  payload: { message: error instanceof Error ? error.message : String(error) }
@@ -258,6 +268,7 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
258
268
  const wsUrl = resolveTransportWebSocketUrl(this.apiBase, this.runtime.wsPath);
259
269
  this.manualClose = false;
260
270
  this.connectPromise = new Promise<void>((innerResolve, innerReject) => {
271
+ this.rejectConnect = innerReject;
261
272
  const socket = new WebSocket(wsUrl);
262
273
  this.socket = socket;
263
274
  let connectionOpened = false;
@@ -279,6 +290,7 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
279
290
  connectionOpened = true;
280
291
  clearConnectTimeout();
281
292
  this.connectPromise = null;
293
+ this.rejectConnect = null;
282
294
  innerResolve();
283
295
  this.emit({ type: 'connection.open', payload: {} });
284
296
  };
@@ -304,6 +316,7 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
304
316
  const wasConnecting = this.connectPromise !== null;
305
317
  this.socket = null;
306
318
  this.connectPromise = null;
319
+ this.rejectConnect = null;
307
320
  this.failPendingWork(new Error('Remote transport connection closed.'));
308
321
  this.emit({ type: 'connection.close', payload: {} });
309
322
  if (wasConnecting && !connectionOpened) {
@@ -330,21 +343,29 @@ export class RemoteSessionMultiplexTransport implements AppTransport {
330
343
  }
331
344
 
332
345
  private replaceSocket = (): void => {
333
- if (this.subscribers.size === 0 || this.connectPromise !== null) {
346
+ if (this.subscribers.size === 0) {
334
347
  return;
335
348
  }
336
349
  if (this.reconnectTimer !== null) {
337
350
  window.clearTimeout(this.reconnectTimer);
338
351
  this.reconnectTimer = null;
339
352
  }
353
+ if (this.connectTimeoutId !== null) {
354
+ window.clearTimeout(this.connectTimeoutId);
355
+ this.connectTimeoutId = null;
356
+ }
340
357
  const staleSocket = this.socket;
358
+ const rejectStaleConnect = this.rejectConnect;
341
359
  this.socket = null;
360
+ this.connectPromise = null;
361
+ this.rejectConnect = null;
342
362
  if (staleSocket) {
343
363
  staleSocket.onopen = null;
344
364
  staleSocket.onmessage = null;
345
365
  staleSocket.onerror = null;
346
366
  staleSocket.onclose = null;
347
367
  staleSocket.close();
368
+ rejectStaleConnect?.(new RemoteBrowserRecoveryReplacementError());
348
369
  this.failPendingWork(new Error('Remote transport connection replaced after browser recovery.'));
349
370
  this.emit({ type: 'connection.close', payload: {} });
350
371
  }