@nextclaw/ui 0.15.25 → 0.15.26

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 (288) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/assets/{abnfDiagram-VRR7QNED-DvTjgVMf.js → abnfDiagram-VRR7QNED-BcFJp_1X.js} +1 -1
  3. package/dist/assets/{aiden0z-pptx-renderer.es-C1nfBAXR.js → aiden0z-pptx-renderer.es-Dp2ezlQn.js} +1 -1
  4. package/dist/assets/{api-FK7tikI1.js → api-CK3Fro7z.js} +6 -6
  5. package/dist/assets/appearance-settings-page-zqwWO8Dy.js +1 -0
  6. package/dist/assets/{arc-BvhODBXv.js → arc-CkgyPMyW.js} +1 -1
  7. package/dist/assets/architecture-TIHT7OUA-DO2x53FK.js +1 -0
  8. package/dist/assets/{architectureDiagram-ZJ3FMSHR-BKO9RgNS.js → architectureDiagram-ZJ3FMSHR-CMd4cIjI.js} +1 -1
  9. package/dist/assets/{blockDiagram-677ZJIJ3-DHpDXy7D.js → blockDiagram-677ZJIJ3-Bz3tbhet.js} +1 -1
  10. package/dist/assets/{c4Diagram-LMCZKHZV-BG_iQnDr.js → c4Diagram-LMCZKHZV-D9hFNAGv.js} +1 -1
  11. package/dist/assets/channel-nBvMaVyP.js +1 -0
  12. package/dist/assets/{channels-list-page-CocdcIko.js → channels-list-page-CVCZBlCL.js} +2 -2
  13. package/dist/assets/chat-page-D4wehRTz.js +1 -0
  14. package/dist/assets/chunk-2Q5K7J3B-CJgqFDS4.js +1 -0
  15. package/dist/assets/{chunk-32BRIVSS-DR9M0LLx.js → chunk-32BRIVSS-7NrjEITq.js} +1 -1
  16. package/dist/assets/{chunk-52WLFC77-698iC3BB.js → chunk-52WLFC77-viIcqj9q.js} +1 -1
  17. package/dist/assets/{chunk-5FCAYU7R-DikTj9Ey.js → chunk-5FCAYU7R-Vsu4J-VM.js} +1 -1
  18. package/dist/assets/{chunk-5HE753X5-ko0o7_q0.js → chunk-5HE753X5-C-w6CQZK.js} +1 -1
  19. package/dist/assets/{chunk-5JV3BV7I-CEHufhgo.js → chunk-5JV3BV7I-CuKgJQ4W.js} +1 -1
  20. package/dist/assets/{chunk-5TONJI2A-CGgno1cu.js → chunk-5TONJI2A-CYeiWZKb.js} +1 -1
  21. package/dist/assets/{chunk-5VM5RSS4-DkiB4cUQ.js → chunk-5VM5RSS4-DRCbfwIn.js} +1 -1
  22. package/dist/assets/{chunk-7BUUIJ7U-DzptcytQ.js → chunk-7BUUIJ7U-BvydOcm3.js} +1 -1
  23. package/dist/assets/{chunk-BIQX33UG-DMRSQJvT.js → chunk-BIQX33UG-RlppOXKo.js} +1 -1
  24. package/dist/assets/{chunk-C7G6YPKG-Bw1BwwuY.js → chunk-C7G6YPKG-DAizzYwr.js} +1 -1
  25. package/dist/assets/{chunk-CQNSW5MT-C0z6eHBk.js → chunk-CQNSW5MT-5eChJHca.js} +1 -1
  26. package/dist/assets/{chunk-CYSBUYHQ-ByPyAouO.js → chunk-CYSBUYHQ-YHPr53fv.js} +1 -1
  27. package/dist/assets/{chunk-EMLP6XTP-CJlAXWZg.js → chunk-EMLP6XTP-CK4D7Hz5.js} +1 -1
  28. package/dist/assets/{chunk-EX3LRPZG-Dqq4zKJu.js → chunk-EX3LRPZG-BmlDFIRW.js} +1 -1
  29. package/dist/assets/{chunk-FWX5IMBZ-B0SNoCmi.js → chunk-FWX5IMBZ-D0ksHZZ9.js} +2 -2
  30. package/dist/assets/{chunk-HOUHSVGY-DG_GJih_.js → chunk-HOUHSVGY-DPkq8FCm.js} +1 -1
  31. package/dist/assets/{chunk-ICXQ74PX-Drxk_6bE.js → chunk-ICXQ74PX-FAatv5fC.js} +1 -1
  32. package/dist/assets/{chunk-JG7HCLWE-DdLFPpnd.js → chunk-JG7HCLWE-DLkIi4F7.js} +1 -1
  33. package/dist/assets/{chunk-JWPE2WC7-B8M4G76F.js → chunk-JWPE2WC7-DawOjNE3.js} +1 -1
  34. package/dist/assets/{chunk-MOJQB5TN-XP6FJHY_.js → chunk-MOJQB5TN-Di52TorW.js} +1 -1
  35. package/dist/assets/{chunk-MOZMSUNE-C_6x18Qw.js → chunk-MOZMSUNE-PfyK9w1-.js} +1 -1
  36. package/dist/assets/{chunk-OGEWGWER-N25BzCmG.js → chunk-OGEWGWER-C3jdH3Ty.js} +1 -1
  37. package/dist/assets/{chunk-OSBZ3O6U-ASDEm7y0.js → chunk-OSBZ3O6U-CecHo-f0.js} +1 -1
  38. package/dist/assets/{chunk-PUDLZKDR-CTlvAcn7.js → chunk-PUDLZKDR-f3IJh3sN.js} +1 -1
  39. package/dist/assets/{chunk-Q4XR5HBZ-Da9BWfB6.js → chunk-Q4XR5HBZ-DQFeUPxZ.js} +1 -1
  40. package/dist/assets/{chunk-QBLGF6JB-Bi6RpTJO.js → chunk-QBLGF6JB-BhUeG0y2.js} +1 -1
  41. package/dist/assets/{chunk-R7FJI6CG-DkMsSPvK.js → chunk-R7FJI6CG-C3XpZ-2u.js} +1 -1
  42. package/dist/assets/{chunk-RYQCIY6F-DZp0eU-j.js → chunk-RYQCIY6F-CAqa5klQ.js} +1 -1
  43. package/dist/assets/{chunk-U6XO7XAA-vfinDSrj.js → chunk-U6XO7XAA-D_WXezeD.js} +1 -1
  44. package/dist/assets/{chunk-V7JOEXUC-C9Nksccs.js → chunk-V7JOEXUC-CZ70oOtp.js} +1 -1
  45. package/dist/assets/chunk-VAUOI2AC-BGvh3yIx.js +1 -0
  46. package/dist/assets/{chunk-VR4S4FIN-Xv6zfwXs.js → chunk-VR4S4FIN-B7AHEYYk.js} +1 -1
  47. package/dist/assets/{chunk-WYO6CB5R-mOJNzbWl.js → chunk-WYO6CB5R-Dn9To_OI.js} +2 -2
  48. package/dist/assets/chunk-XXDRQBXY-DaBxG5gs.js +1 -0
  49. package/dist/assets/{chunk-YOTPTUD7-1-aKSu4o.js → chunk-YOTPTUD7-BYEgRBk3.js} +1 -1
  50. package/dist/assets/{chunk-ZGVPDNZ5-OJ8veMpK.js → chunk-ZGVPDNZ5-C6YtZDU0.js} +1 -1
  51. package/dist/assets/{chunk-ZIRB5QZD-SR_Nq_PP.js → chunk-ZIRB5QZD-DMuYtnHF.js} +1 -1
  52. package/dist/assets/classDiagram-OUVF2IWQ-P6N03G2R.js +1 -0
  53. package/dist/assets/classDiagram-v2-EOCWNBFH-B1_uLvMv.js +1 -0
  54. package/dist/assets/config-split-page-CceNFvlY.js +1 -0
  55. package/dist/assets/confirm-dialog-CWeNYWZY.js +5 -0
  56. package/dist/assets/{cose-bilkent-JH36ORCC-NjVgz2Bw.js → cose-bilkent-JH36ORCC-Bc2Ex5Y3.js} +1 -1
  57. package/dist/assets/cynefin-VYW2F7L2-B-H8Qp-n.js +1 -0
  58. package/dist/assets/{cynefinDiagram-TSTJHNR4-B_17LDqD.js → cynefinDiagram-TSTJHNR4-DVysQoGz.js} +1 -1
  59. package/dist/assets/{dagre-CMe101gk.js → dagre-CMhQ1cAG.js} +1 -1
  60. package/dist/assets/{dagre-VKFMJZFB-qo8nLb3B.js → dagre-VKFMJZFB-RYyWpPJZ.js} +1 -1
  61. package/dist/assets/desktop-update-config-Dirc3bpt.js +1 -0
  62. package/dist/assets/{diagram-FQU43EPY-Ba3XIklC.js → diagram-FQU43EPY-BD6KONdF.js} +1 -1
  63. package/dist/assets/{diagram-G47NLZAW-CG45TcUx.js → diagram-G47NLZAW-CGB2ptRR.js} +1 -1
  64. package/dist/assets/{diagram-NH7WQ7WH-2F2HrwV-.js → diagram-NH7WQ7WH-DnkOI6cU.js} +1 -1
  65. package/dist/assets/{diagram-OA4YK3LP-CXfWH9NZ.js → diagram-OA4YK3LP-DF82RZ7P.js} +1 -1
  66. package/dist/assets/{diagram-WEI45ONY-CH_4yepc.js → diagram-WEI45ONY-Be2v7Ck9.js} +1 -1
  67. package/dist/assets/{dist-BH7W5yCi.js → dist-AYxkFx2B.js} +1 -1
  68. package/dist/assets/{dist-CaYdVVeO.js → dist-D9xtGgdL.js} +1 -1
  69. package/dist/assets/doc-browser-4Sud6dWw.js +1 -0
  70. package/dist/assets/doc-browser-D4x_yH5F.js +1 -0
  71. package/dist/assets/doc-browser-context-Cb7Z0j90.js +1 -0
  72. package/dist/assets/{docx-preview-CoM4JK7_.js → docx-preview-BqwAjrj3.js} +1 -1
  73. package/dist/assets/{ebnfDiagram-CCIWWBDH-BwiG4Ea1.js → ebnfDiagram-CCIWWBDH-CP98OYk8.js} +1 -1
  74. package/dist/assets/{erDiagram-Q63AITRT-BML3hpnQ.js → erDiagram-Q63AITRT-ZLlx8xfs.js} +1 -1
  75. package/dist/assets/eventmodeling-45OFAUF4-YVtShyFA.js +1 -0
  76. package/dist/assets/flowDiagram-23GEKE2U-BeKXabVO.js +1 -0
  77. package/dist/assets/form-actions-B2q4jgjE.js +1 -0
  78. package/dist/assets/{ganttDiagram-NO4QXBWP-80enfWbD.js → ganttDiagram-NO4QXBWP-DXCDjHR2.js} +1 -1
  79. package/dist/assets/gitGraph-TEB2WS4Q-jTSiBj-p.js +1 -0
  80. package/dist/assets/{gitGraphDiagram-IHSO6WYX-CVLqXr-b.js → gitGraphDiagram-IHSO6WYX-l2HWrTJp.js} +1 -1
  81. package/dist/assets/index-CdyTsSBu.css +1 -0
  82. package/dist/assets/index-Das_bw2h.js +107 -0
  83. package/dist/assets/info-DKCQHKI2-BIporNWb.js +1 -0
  84. package/dist/assets/{infoDiagram-FWYZ7A6U-Dyvs2t0i.js → infoDiagram-FWYZ7A6U-D-DjX-bn.js} +1 -1
  85. package/dist/assets/{ishikawaDiagram-FXEZZL3T-sSnxDKfh.js → ishikawaDiagram-FXEZZL3T-y_Xy128F.js} +1 -1
  86. package/dist/assets/{journeyDiagram-5HDEW3XC-D22V71Mf.js → journeyDiagram-5HDEW3XC-DJn5xYcQ.js} +1 -1
  87. package/dist/assets/{kanban-definition-HUTT4EX6-D3ds0p-g.js → kanban-definition-HUTT4EX6-DJVIOR21.js} +1 -1
  88. package/dist/assets/{line-CbyFs065.js → line-Cos7PIOj.js} +1 -1
  89. package/dist/assets/{linear-4DKtnZBS.js → linear-BtDLqtzF.js} +1 -1
  90. package/dist/assets/loader-circle-CpmBdaon.js +1 -0
  91. package/dist/assets/{map-CcZzEoz6.js → map-BKnQyvd0.js} +1 -1
  92. package/dist/assets/mcp-marketplace-page-CdOY3Sop.js +1 -0
  93. package/dist/assets/mcp-marketplace-page-DvjrfqEt.js +9 -0
  94. package/dist/assets/{mermaid-parser.core-DPmMOjXD.js → mermaid-parser.core-XUNZhr2W.js} +2 -2
  95. package/dist/assets/{mermaid.core-BSf-ddRa.js → mermaid.core-ySrvolIe.js} +3 -3
  96. package/dist/assets/{mindmap-definition-LN4V7U3C-BUTwWPyx.js → mindmap-definition-LN4V7U3C-BypL9tei.js} +1 -1
  97. package/dist/assets/model-config-page-DfOLyQqR.js +1 -0
  98. package/dist/assets/{navigation-link-CVy0_kVl.js → navigation-link-MiiyoIjH.js} +2 -2
  99. package/dist/assets/{ordinal-BgLYtOZE.js → ordinal-CxxVWxYU.js} +1 -1
  100. package/dist/assets/packet-7NZHBO7P-CuFMADV0.js +1 -0
  101. package/dist/assets/{pegDiagram-2B236MQR-BEu_ZBjc.js → pegDiagram-2B236MQR-D-U2KBGv.js} +1 -1
  102. package/dist/assets/pie-RZYD4A2V-XUeIXhM9.js +1 -0
  103. package/dist/assets/{pieDiagram-ENE6RG2P-CAwAwuBd.js → pieDiagram-ENE6RG2P-CBi3GusJ.js} +1 -1
  104. package/dist/assets/plus-C8FkjpSZ.js +1 -0
  105. package/dist/assets/provider-scoped-model-input-DXzjr5l0.js +1 -0
  106. package/dist/assets/providers-config-page-CaO8WfZH.js +1 -0
  107. package/dist/assets/{quadrantDiagram-ABIIQ3AL-CwE6F-_2.js → quadrantDiagram-ABIIQ3AL-H0ZuvnZL.js} +1 -1
  108. package/dist/assets/radar-I7S5WNFK-D-NNGh1k.js +1 -0
  109. package/dist/assets/railroad-3IZDKUUU-C67_uDaM.js +1 -0
  110. package/dist/assets/railroad-abnf-AHOZXSZD-BZ8Yflnd.js +1 -0
  111. package/dist/assets/railroad-ebnf-EBAXGLYW-B7zO7RoK.js +1 -0
  112. package/dist/assets/railroad-peg-LSFZ7HO6-R63PTgLz.js +1 -0
  113. package/dist/assets/{railroadDiagram-RFXS5EU6-xgLekU3B.js → railroadDiagram-RFXS5EU6-D7Y2EqSd.js} +1 -1
  114. package/dist/assets/react-C8XFFvuz.js +8 -0
  115. package/dist/assets/{refresh-cw-j2bl79Ea.js → refresh-cw-a2VVeeAF.js} +1 -1
  116. package/dist/assets/remote-BJHXa4mB.js +1 -0
  117. package/dist/assets/{requirementDiagram-TGXJPOKE-CyVUzEX5.js → requirementDiagram-TGXJPOKE-BiXNX1NN.js} +1 -1
  118. package/dist/assets/rotate-cw-DJ7UF3F2.js +1 -0
  119. package/dist/assets/runtime-config-page-BuA4A02z.js +1 -0
  120. package/dist/assets/{sankeyDiagram-HTMAVEWB-JK6bFmYB.js → sankeyDiagram-HTMAVEWB-qzDeLztW.js} +1 -1
  121. package/dist/assets/{save-BKNrtK81.js → save-CGm23Yww.js} +1 -1
  122. package/dist/assets/{search-CkOm65W_.js → search-CH2t--sH.js} +1 -1
  123. package/dist/assets/search-config-page-BAmYqoAz.js +1 -0
  124. package/dist/assets/{secrets-config-page-CJjtdFAl.js → secrets-config-page-BlPOuql_.js} +2 -2
  125. package/dist/assets/security-config-CbDiY2xr.js +1 -0
  126. package/dist/assets/{select-Ea7ffKCE.js → select-DnxxDpcV.js} +2 -2
  127. package/dist/assets/{sequenceDiagram-DBY2YBRQ-BR5IokXV.js → sequenceDiagram-DBY2YBRQ-BtRbPQtL.js} +1 -1
  128. package/dist/assets/{settings-2-CtyN3m_V.js → settings-2-agnMYc8a.js} +1 -1
  129. package/dist/assets/{sizeCapture-X5ZJPWSS-SxG_YnMA.js → sizeCapture-X5ZJPWSS-CMYvM3SL.js} +1 -1
  130. package/dist/assets/skeleton-XpqeWL62.js +1 -0
  131. package/dist/assets/{src-vgz8E_-O.js → src-Bw-mzbQb.js} +1 -1
  132. package/dist/assets/{stateDiagram-2N3HPSRC-DD4OoYhn.js → stateDiagram-2N3HPSRC-BJ-mFeOz.js} +1 -1
  133. package/dist/assets/stateDiagram-v2-6OUMAXLB-BE-HqxOK.js +1 -0
  134. package/dist/assets/{swimlanes-5IMT3BWC-BWkFeyCT.js → swimlanes-5IMT3BWC-BsucVOO2.js} +2 -2
  135. package/dist/assets/swimlanesDiagram-G3AALYLV-Dr1H9LJH.js +8 -0
  136. package/dist/assets/{tag-chip-C9l4xsKp.js → tag-chip-CPOc8b2N.js} +1 -1
  137. package/dist/assets/{timeline-definition-FHXFAJF6-VTRPy6KA.js → timeline-definition-FHXFAJF6-Bicewlzo.js} +1 -1
  138. package/dist/assets/treeView-QDETBFTQ-npJ5dbqS.js +1 -0
  139. package/dist/assets/treemap-6X3UGDF4-pYrBx6oa.js +1 -0
  140. package/dist/assets/{vennDiagram-L72KCM5P-Bvk42Pek.js → vennDiagram-L72KCM5P-BxOOnO9x.js} +1 -1
  141. package/dist/assets/wardley-OPB4EBWU-CmSRKLR8.js +1 -0
  142. package/dist/assets/{wardleyDiagram-EHGQE667-DOFjx2s3.js → wardleyDiagram-EHGQE667-Cl7NltMv.js} +1 -1
  143. package/dist/assets/x-odTHAtLZ.js +1 -0
  144. package/dist/assets/{xychartDiagram-FW5EYKEG-DY5yRTUc.js → xychartDiagram-FW5EYKEG-DiMIxQ7N.js} +1 -1
  145. package/dist/index.html +21 -22
  146. package/package.json +6 -6
  147. package/src/features/apps/components/__tests__/app-packages-panel.test.tsx +234 -0
  148. package/src/features/apps/components/app-marketplace-dialog.tsx +262 -0
  149. package/src/features/apps/components/app-package-card.tsx +268 -0
  150. package/src/features/apps/components/app-packages-panel.tsx +301 -0
  151. package/src/features/apps/components/apps-panel.tsx +11 -4
  152. package/src/features/apps/hooks/use-app-marketplace.ts +95 -0
  153. package/src/features/apps/hooks/use-app-packages.ts +59 -0
  154. package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +27 -4
  155. package/src/features/chat/components/layout/__tests__/chat-sidebar-session-area.test.tsx +36 -5
  156. package/src/features/chat/components/layout/chat-sidebar-desktop-layout.tsx +12 -13
  157. package/src/features/chat/features/conversation/components/__tests__/session-conversation-area.test.tsx +49 -1
  158. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +4 -4
  159. package/src/features/chat/features/conversation/components/session-conversation-area.tsx +25 -4
  160. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +3 -0
  161. package/src/features/chat/features/conversation/hooks/use-system-object-reference-select.ts +27 -0
  162. package/src/features/chat/features/conversation/utils/session-message-composer.utils.ts +5 -0
  163. package/src/features/chat/features/input/hooks/__tests__/use-chat-input-surface-state.test.tsx +102 -0
  164. package/src/features/chat/features/input/hooks/use-chat-input-surface-state.ts +71 -120
  165. package/src/features/chat/features/input/input-surface-plugins/__tests__/context-reference-plugin.test.ts +265 -18
  166. package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.types.ts +7 -2
  167. package/src/features/chat/features/input/input-surface-plugins/chat-input-product-plugin-adapters.utils.ts +124 -0
  168. package/src/features/chat/features/input/input-surface-plugins/context-reference-items.utils.ts +99 -15
  169. package/src/features/chat/features/input/input-surface-plugins/context-reference-plugin.utils.ts +143 -139
  170. package/src/features/chat/features/input/input-surface-plugins/panel-app-input-surface-items.utils.ts +116 -0
  171. package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +1 -1
  172. package/src/features/chat/features/input/utils/__tests__/chat-inline-token.utils.test.ts +53 -1
  173. package/src/features/chat/features/input/utils/chat-composer-token-protocol.utils.ts +5 -0
  174. package/src/features/chat/features/input/utils/chat-inline-token-composer.utils.ts +134 -0
  175. package/src/features/chat/features/input/utils/chat-inline-token.utils.ts +30 -101
  176. package/src/features/chat/features/input/utils/chat-system-object-reference.utils.test.ts +44 -0
  177. package/src/features/chat/features/input/utils/chat-system-object-reference.utils.ts +46 -0
  178. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +82 -2
  179. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-text-selection.test.tsx +12 -8
  180. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +24 -12
  181. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +9 -2
  182. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +52 -4
  183. package/src/features/chat/features/workspace/hooks/use-workspace-explorer-layout.ts +8 -11
  184. package/src/features/chat/features/workspace/hooks/use-workspace-file-actions.ts +68 -46
  185. package/src/features/chat/index.ts +1 -1
  186. package/src/features/chat/managers/chat-draft-intent.manager.ts +18 -2
  187. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +6 -0
  188. package/src/features/chat/stores/chat-thread.store.ts +6 -0
  189. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +38 -5
  190. package/src/features/inbox/components/inbox-reader-dialog.tsx +5 -3
  191. package/src/features/inbox/managers/inbox.manager.test.ts +28 -3
  192. package/src/features/inbox/managers/inbox.manager.ts +14 -4
  193. package/src/features/inbox/pages/inbox-page.test.ts +121 -2
  194. package/src/features/inbox/pages/inbox-page.tsx +5 -3
  195. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +85 -1
  196. package/src/features/marketplace/hooks/__tests__/use-marketplace.test.tsx +44 -1
  197. package/src/features/marketplace/hooks/use-marketplace-item-actions.ts +23 -2
  198. package/src/features/marketplace/hooks/use-marketplace.ts +10 -0
  199. package/src/features/marketplace/index.ts +4 -0
  200. package/src/features/panel-apps/index.ts +5 -1
  201. package/src/features/panel-apps/utils/__tests__/panel-app-doc-browser.utils.test.ts +13 -6
  202. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +6 -3
  203. package/src/features/right-panel-resources/index.ts +1 -0
  204. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +7 -4
  205. package/src/features/system-status/components/__tests__/desktop-update-config.test.tsx +20 -1
  206. package/src/features/system-status/components/desktop-update-config.tsx +14 -13
  207. package/src/features/system-status/managers/__tests__/runtime-update.manager.test.ts +99 -0
  208. package/src/features/system-status/managers/runtime-update.manager.ts +22 -0
  209. package/src/features/system-status/stores/runtime-update.store.ts +1 -0
  210. package/src/shared/components/ui/actions/__tests__/icon-action-button.test.tsx +15 -0
  211. package/src/shared/components/ui/actions/icon-action-button.tsx +4 -2
  212. package/src/shared/hooks/use-system-object-references.ts +22 -0
  213. package/src/shared/lib/api/types.ts +10 -0
  214. package/src/shared/lib/i18n/locales/en-US/chat.json +16 -9
  215. package/src/shared/lib/i18n/locales/en-US/desktop-update.json +7 -4
  216. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +40 -0
  217. package/src/shared/lib/i18n/locales/en-US/marketplace.json +3 -0
  218. package/src/shared/lib/i18n/locales/zh-CN/chat.json +18 -11
  219. package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +7 -4
  220. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +40 -0
  221. package/src/shared/lib/i18n/locales/zh-CN/marketplace.json +3 -0
  222. package/dist/assets/appearance-settings-page-BYbvl2wj.js +0 -1
  223. package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +0 -1
  224. package/dist/assets/channel-5T3pdR-s.js +0 -1
  225. package/dist/assets/chat-page-C5E-LLVd.js +0 -1
  226. package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +0 -1
  227. package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +0 -1
  228. package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +0 -1
  229. package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +0 -1
  230. package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +0 -1
  231. package/dist/assets/config-split-page-CA_a0AJ5.js +0 -1
  232. package/dist/assets/confirm-dialog-CxZfenjK.js +0 -5
  233. package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +0 -1
  234. package/dist/assets/desktop-update-config-BEKC8Ly9.js +0 -1
  235. package/dist/assets/doc-browser-Cl2ldE3f.js +0 -1
  236. package/dist/assets/doc-browser-DXCSd63E.js +0 -1
  237. package/dist/assets/doc-browser-context-FDPs3gJf.js +0 -1
  238. package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +0 -1
  239. package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +0 -1
  240. package/dist/assets/form-actions-0c0aw_bl.js +0 -1
  241. package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +0 -1
  242. package/dist/assets/i18n-provider-DkITJNz8.js +0 -1
  243. package/dist/assets/index-CQ2LcI2p.css +0 -1
  244. package/dist/assets/index-CrdfvBVg.js +0 -107
  245. package/dist/assets/info-DKCQHKI2-DNlNGH90.js +0 -1
  246. package/dist/assets/loader-circle-DHtUxCIA.js +0 -1
  247. package/dist/assets/mcp-marketplace-page-Bc_jI5iH.js +0 -9
  248. package/dist/assets/mcp-marketplace-page-CzCieD9r.js +0 -1
  249. package/dist/assets/model-config-page-C4jw-pcj.js +0 -1
  250. package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +0 -1
  251. package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +0 -1
  252. package/dist/assets/plus-CG1RwZQq.js +0 -1
  253. package/dist/assets/provider-scoped-model-input-CmH4BFvc.js +0 -1
  254. package/dist/assets/providers-config-page-CJQjwzaw.js +0 -1
  255. package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +0 -1
  256. package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +0 -1
  257. package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +0 -1
  258. package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +0 -1
  259. package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +0 -1
  260. package/dist/assets/react-DjFBVA0n.js +0 -8
  261. package/dist/assets/remote-BIlpD3yL.js +0 -1
  262. package/dist/assets/rotate-cw-bKG8zH8M.js +0 -1
  263. package/dist/assets/runtime-config-page-B_x2Glz5.js +0 -1
  264. package/dist/assets/search-config-page-BaIijtmO.js +0 -1
  265. package/dist/assets/security-config-DB8apj09.js +0 -1
  266. package/dist/assets/skeleton-Bt6zxcAB.js +0 -1
  267. package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +0 -1
  268. package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +0 -8
  269. package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +0 -1
  270. package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +0 -1
  271. package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +0 -1
  272. package/dist/assets/x-CowtCu9Z.js +0 -1
  273. /package/dist/assets/{array-NADKd9aU.js → array-BQVzeGRt.js} +0 -0
  274. /package/dist/assets/{chunk-KEIR6QF5-BuyuzJJL.js → chunk-KEIR6QF5-f9psyCXK.js} +0 -0
  275. /package/dist/assets/{chunk-Y2CYZVJY-D_B2ZRNt.js → chunk-Y2CYZVJY-D1mAU_Po.js} +0 -0
  276. /package/dist/assets/{config-hints-BcfVUMij.js → config-hints-nV5HPOvq.js} +0 -0
  277. /package/dist/assets/{cytoscape.esm-BANTlgza.js → cytoscape.esm-0uDtdD0l.js} +0 -0
  278. /package/dist/assets/{defaultLocale-C4_L0aEs.js → defaultLocale-DSWXGgt0.js} +0 -0
  279. /package/dist/assets/{dist-DAPEIJbz.js → dist--ta5rX12.js} +0 -0
  280. /package/dist/assets/{graphlib-ChqXg0dI.js → graphlib-CQ6QV4yP.js} +0 -0
  281. /package/dist/assets/{host-capabilities-D9C4CBK5.js → host-capabilities-Tk038i04.js} +0 -0
  282. /package/dist/assets/{init-D8wZg9xq.js → init-Y6h9jGtZ.js} +0 -0
  283. /package/dist/assets/{jszip.min-CkbBfwAQ.js → jszip.min-8hyJpgpx.js} +0 -0
  284. /package/dist/assets/{katex-TZJFa0J_.js → katex-ARhY9PS1.js} +0 -0
  285. /package/dist/assets/{middleware-B3k-TSmZ.js → middleware-DXsbf9xI.js} +0 -0
  286. /package/dist/assets/{path-DodfxcX7.js → path-10BjdyLh.js} +0 -0
  287. /package/dist/assets/{rough.esm-CUaa1Rbe.js → rough.esm-DxgC_14r.js} +0 -0
  288. /package/dist/assets/{xlsx-CxByi7bR.js → xlsx-DrDuDNAa.js} +0 -0
@@ -24,6 +24,7 @@ import {
24
24
  } from '@/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils';
25
25
  import { useWorkspaceExplorerLayout } from '@/features/chat/features/workspace/hooks/use-workspace-explorer-layout';
26
26
  import { t } from '@/shared/lib/i18n';
27
+ import { resolveWorkspaceRelativePath } from '@/shared/lib/session-project';
27
28
  import { cn } from '@/shared/lib/utils';
28
29
  import { IconActionButton } from '@/shared/components/ui/actions/icon-action-button';
29
30
 
@@ -175,11 +176,13 @@ function WorkspaceChildSessions({ childSessionTabs }: { childSessionTabs: readon
175
176
  }
176
177
 
177
178
  function WorkspaceProjectFiles({
179
+ activePath,
178
180
  onFileOpen,
179
181
  projectRoot,
180
182
  sessionKey,
181
183
  workingDir,
182
184
  }: {
185
+ activePath: string | null;
183
186
  onFileOpen?: (action: ChatFileOpenActionViewModel) => void;
184
187
  projectRoot: string | null;
185
188
  sessionKey: string | null;
@@ -203,6 +206,9 @@ function WorkspaceProjectFiles({
203
206
 
204
207
  return (
205
208
  <ChatSessionWorkspaceDirectoryBrowser
209
+ activeRelativePath={
210
+ activePath ? resolveWorkspaceRelativePath({ path: activePath, sessionProjectRoot: rootPath }) : null
211
+ }
206
212
  key={rootPath}
207
213
  browseQuery={browseQuery}
208
214
  onFileOpen={onFileOpen ?? presenter.chatThreadManager.openFilePreview}
@@ -384,7 +390,7 @@ export function ChatSessionWorkspacePanelContent({
384
390
  onResizeStart,
385
391
  setExplorerOpen,
386
392
  showExplorer,
387
- } = useWorkspaceExplorerLayout({ fileActive, projectFilesActive, sessionProjectRoot, sessionWorkingDir });
393
+ } = useWorkspaceExplorerLayout({ fileActive, projectFilesActive });
388
394
 
389
395
  return (
390
396
  <div
@@ -414,6 +420,7 @@ export function ChatSessionWorkspacePanelContent({
414
420
  aria-hidden={!showExplorer}
415
421
  >
416
422
  <WorkspaceProjectFiles
423
+ activePath={fileActive ? activeSelection.file.path : null}
417
424
  onFileOpen={(action) => {
418
425
  if (compact) setExplorerOpen(false);
419
426
  presenter.chatThreadManager.openFilePreview(action);
@@ -445,7 +452,7 @@ export function ChatSessionWorkspacePanelContent({
445
452
  fileActive
446
453
  ? {
447
454
  open: explorerOpen,
448
- onToggle: () => setExplorerOpen((value) => !value),
455
+ onToggle: () => setExplorerOpen(!explorerOpen),
449
456
  }
450
457
  : undefined
451
458
  }
@@ -30,6 +30,7 @@ import { buildWorkspaceEntryContextMenuGroups } from '@/features/chat/features/w
30
30
  export { copyWorkspacePath } from '@/features/chat/features/workspace/components/project-files/workspace-directory-entry-menu';
31
31
 
32
32
  type WorkspaceDirectoryTreeActionProps = {
33
+ activeRelativePath: string | null;
33
34
  busy: boolean;
34
35
  collapseVersion: number;
35
36
  createTarget: WorkspaceDirectoryActionTarget | null;
@@ -182,7 +183,31 @@ function useWorkspaceEntryRename({
182
183
  return { active, cancel, error, name, start, submit, updateName };
183
184
  }
184
185
 
186
+ function readWorkspaceTreeEntrySelection(
187
+ activeRelativePath: string | null,
188
+ relativePath: string | null,
189
+ selectedPath: string | null,
190
+ entryPath: string,
191
+ ): readonly [active: boolean, selected: boolean] {
192
+ const active = !selectedPath && activeRelativePath !== null && activeRelativePath === relativePath;
193
+ return [active, selectedPath === null ? active : selectedPath === entryPath];
194
+ }
195
+
196
+ function isWorkspaceTreeEntryExpanded(
197
+ manuallyExpanded: boolean,
198
+ isDirectory: boolean,
199
+ activeRelativePath: string | null,
200
+ relativePath: string | null,
201
+ selectedPath: string | null,
202
+ ): boolean {
203
+ return (
204
+ manuallyExpanded ||
205
+ Boolean(!selectedPath && isDirectory && relativePath && activeRelativePath?.startsWith(`${relativePath}/`))
206
+ );
207
+ }
208
+
185
209
  export function WorkspaceDirectoryTreeEntry({
210
+ activeRelativePath,
186
211
  browseParentRefresh,
187
212
  busy,
188
213
  collapseVersion,
@@ -216,7 +241,14 @@ export function WorkspaceDirectoryTreeEntry({
216
241
  const rowRef = useRef<HTMLDivElement | null>(null);
217
242
  const entryButtonRef = useRef<HTMLButtonElement | null>(null);
218
243
  const isDirectory = entry.kind === 'directory';
219
- const [isExpanded, setIsExpanded] = useState(false);
244
+ const [manuallyExpanded, setIsExpanded] = useState(false);
245
+ const isExpanded = isWorkspaceTreeEntryExpanded(
246
+ manuallyExpanded,
247
+ isDirectory,
248
+ activeRelativePath,
249
+ relativePath,
250
+ selectedPath,
251
+ );
220
252
  const rename = useWorkspaceEntryRename({
221
253
  entry,
222
254
  onRename,
@@ -248,6 +280,16 @@ export function WorkspaceDirectoryTreeEntry({
248
280
  () => ({ path: entry.path, createTarget: ownCreateTarget }),
249
281
  [entry.path, ownCreateTarget],
250
282
  );
283
+ const [activeSelected, selected] = readWorkspaceTreeEntrySelection(
284
+ activeRelativePath,
285
+ relativePath,
286
+ selectedPath,
287
+ entry.path,
288
+ );
289
+
290
+ useLayoutEffect(() => {
291
+ if (activeSelected) rowRef.current?.scrollIntoView?.({ block: 'nearest' });
292
+ }, [activeSelected]);
251
293
 
252
294
  useLayoutEffect(() => {
253
295
  if (revealPath !== entry.path) return;
@@ -259,7 +301,7 @@ export function WorkspaceDirectoryTreeEntry({
259
301
 
260
302
  const activateEntry = () => {
261
303
  onSelect(selection);
262
- if (isDirectory) setIsExpanded((value) => !value);
304
+ if (isDirectory) setIsExpanded(!isExpanded);
263
305
  else onFileOpen({ path: entry.path, label: entry.name, viewMode: 'preview' });
264
306
  };
265
307
 
@@ -280,14 +322,19 @@ export function WorkspaceDirectoryTreeEntry({
280
322
  relativePath,
281
323
  });
282
324
  return (
283
- <div role="treeitem" aria-expanded={isDirectory ? isExpanded : undefined} aria-label={buildEntryLabel(entry)}>
325
+ <div
326
+ role="treeitem"
327
+ aria-expanded={isDirectory ? isExpanded : undefined}
328
+ aria-label={buildEntryLabel(entry)}
329
+ aria-selected={selected}
330
+ >
284
331
  <ContextMenu groups={contextMenuGroups} label={t('chatWorkspaceFileContextMenu')}>
285
332
  <div
286
333
  ref={rowRef}
287
334
  data-workspace-tree-entry=""
288
335
  className={cn(
289
336
  'group flex h-[26px] w-full min-w-0 items-center text-gray-700 transition-colors hover:bg-gray-100 focus-within:bg-gray-100',
290
- selectedPath === entry.path ? 'bg-primary/10' : null,
337
+ selected ? 'bg-primary/10' : null,
291
338
  entry.hidden ? 'opacity-65' : null,
292
339
  )}
293
340
  style={{ paddingLeft: `${6 + level * 12}px` }}
@@ -383,6 +430,7 @@ export function WorkspaceDirectoryTreeEntry({
383
430
  <div role="group">
384
431
  {createTarget?.path === entry.path ? renderCreateFolder(level + 1) : null}
385
432
  <WorkspaceDirectoryTreeChildren
433
+ activeRelativePath={activeRelativePath}
386
434
  browseQuery={browseQuery}
387
435
  busy={busy}
388
436
  collapseVersion={collapseVersion}
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from 'react';
1
+ import { useCallback, useEffect, useRef, useState, type PointerEvent as ReactPointerEvent } from 'react';
2
2
  import { usePresenter } from '@/features/chat/components/providers/chat-presenter.provider';
3
3
  import { useChatThreadStore } from '@/features/chat/stores/chat-thread.store';
4
4
  import {
@@ -9,22 +9,23 @@ import {
9
9
  export function useWorkspaceExplorerLayout({
10
10
  fileActive,
11
11
  projectFilesActive,
12
- sessionProjectRoot,
13
- sessionWorkingDir,
14
12
  }: {
15
13
  fileActive: boolean;
16
14
  projectFilesActive: boolean;
17
- sessionProjectRoot: string | null;
18
- sessionWorkingDir: string | null;
19
15
  }) {
20
16
  const presenter = usePresenter();
21
17
  const containerRef = useRef<HTMLDivElement | null>(null);
22
18
  const resizeRef = useRef<{ startX: number; startWidth: number; width: number } | null>(null);
19
+ const explorerOpen = useChatThreadStore((state) => state.snapshot.workspaceExplorerOpen);
23
20
  const persistedExplorerWidth = useChatThreadStore((state) => state.snapshot.workspaceExplorerWidth);
21
+ const setSnapshot = useChatThreadStore((state) => state.setSnapshot);
24
22
  const [compact, setCompact] = useState(false);
25
23
  const [explorerDragWidth, setExplorerDragWidth] = useState<number | null>(null);
26
- const [explorerOpen, setExplorerOpen] = useState(true);
27
24
  const explorerWidth = explorerDragWidth ?? persistedExplorerWidth;
25
+ const setExplorerOpen = useCallback(
26
+ (open: boolean) => setSnapshot({ workspaceExplorerOpen: open }),
27
+ [setSnapshot],
28
+ );
28
29
 
29
30
  useEffect(() => {
30
31
  const node = containerRef.current;
@@ -36,10 +37,6 @@ export function useWorkspaceExplorerLayout({
36
37
  return () => observer.disconnect();
37
38
  }, []);
38
39
 
39
- useEffect(() => {
40
- setExplorerOpen(true);
41
- }, [sessionProjectRoot, sessionWorkingDir]);
42
-
43
40
  useEffect(() => {
44
41
  if (!fileActive || !compact || !explorerOpen) return;
45
42
  const closeOnEscape = (event: KeyboardEvent) => {
@@ -47,7 +44,7 @@ export function useWorkspaceExplorerLayout({
47
44
  };
48
45
  window.addEventListener('keydown', closeOnEscape);
49
46
  return () => window.removeEventListener('keydown', closeOnEscape);
50
- }, [compact, explorerOpen, fileActive]);
47
+ }, [compact, explorerOpen, fileActive, setExplorerOpen]);
51
48
 
52
49
  const onResizeStart = (event: ReactPointerEvent<HTMLDivElement>) => {
53
50
  if (compact || !fileActive) return;
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import { useRef, useState } from 'react';
2
2
  import { NextClawClientError } from '@nextclaw/client-sdk';
3
3
  import { toast } from 'sonner';
4
4
  import type { useConfirmDialog } from '@/shared/hooks/use-confirm-dialog';
@@ -29,6 +29,11 @@ export type WorkspaceTreeSelection = {
29
29
  createTarget: WorkspaceDirectoryActionTarget;
30
30
  };
31
31
 
32
+ type WorkspaceTreeSelectionState = {
33
+ activeRelativePath: string | null;
34
+ selection: WorkspaceTreeSelection;
35
+ };
36
+
32
37
  function readErrorMessage(error: unknown): string {
33
38
  return error instanceof Error ? error.message : String(error);
34
39
  }
@@ -193,6 +198,7 @@ async function createWorkspaceEntry({
193
198
  }
194
199
 
195
200
  type WorkspaceProjectFilesControllerOptions = {
201
+ activeRelativePath: string | null;
196
202
  confirm: Confirm;
197
203
  onEntryDeleted?: (path: string) => void;
198
204
  onEntryRenamed?: (params: { previousPath: string; path: string; label: string }) => void;
@@ -200,6 +206,7 @@ type WorkspaceProjectFilesControllerOptions = {
200
206
  };
201
207
 
202
208
  export function useWorkspaceProjectFilesController({
209
+ activeRelativePath,
203
210
  confirm,
204
211
  onEntryDeleted,
205
212
  onEntryRenamed,
@@ -211,18 +218,11 @@ export function useWorkspaceProjectFilesController({
211
218
  const [createName, setCreateName] = useState('');
212
219
  const [createKind, setCreateKind] = useState<'directory' | 'file'>('directory');
213
220
  const [createError, setCreateError] = useState<string | null>(null);
214
- const [selectedPath, setSelectedPath] = useState<string | null>(null);
215
- const [selectedCreateTarget, setSelectedCreateTarget] = useState<WorkspaceDirectoryActionTarget | null>(null);
221
+ const [selectionState, setSelectionState] = useState<WorkspaceTreeSelectionState | null>(null);
216
222
  const [revealPath, setRevealPath] = useState<string | null>(null);
217
223
  const [uploadTarget, setUploadTarget] = useState<WorkspaceDirectoryActionTarget | null>(null);
218
-
219
- useEffect(() => {
220
- setCreateTarget(null);
221
- setSelectedPath(null);
222
- setSelectedCreateTarget(null);
223
- setRevealPath(null);
224
- setUploadTarget(null);
225
- }, [rootPath]);
224
+ const selectedEntry =
225
+ selectionState?.activeRelativePath === activeRelativePath ? selectionState.selection : null;
226
226
 
227
227
  const requestUpload = (target: WorkspaceDirectoryActionTarget) => {
228
228
  setUploadTarget(target);
@@ -231,8 +231,7 @@ export function useWorkspaceProjectFilesController({
231
231
  fileInputRef.current.click();
232
232
  };
233
233
  const selectEntry = (selection: WorkspaceTreeSelection) => {
234
- setSelectedPath(selection.path);
235
- setSelectedCreateTarget(selection.createTarget);
234
+ setSelectionState({ activeRelativePath, selection });
236
235
  };
237
236
  const openCreate = (kind: 'directory' | 'file', target: WorkspaceDirectoryActionTarget) => {
238
237
  target.expand?.();
@@ -275,7 +274,20 @@ export function useWorkspaceProjectFilesController({
275
274
  label: renamed.name,
276
275
  });
277
276
  await refresh();
278
- setSelectedPath(renamed.path);
277
+ setSelectionState((state) =>
278
+ state?.activeRelativePath === activeRelativePath
279
+ ? {
280
+ activeRelativePath,
281
+ selection: {
282
+ path: renamed.path,
283
+ createTarget:
284
+ state.selection.createTarget.path === entry.path
285
+ ? { ...state.selection.createTarget, label: renamed.name, path: renamed.path }
286
+ : state.selection.createTarget,
287
+ },
288
+ }
289
+ : null,
290
+ );
279
291
  setRevealPath(renamed.path);
280
292
  toast.success(t('chatWorkspaceRenameSucceeded').replace('{name}', renamed.name));
281
293
  return renamed;
@@ -292,44 +304,54 @@ export function useWorkspaceProjectFilesController({
292
304
  });
293
305
  if (!created) return;
294
306
  setCreateTarget(null);
295
- setSelectedPath(created.path);
296
- setSelectedCreateTarget({
297
- label: createName.trim(),
298
- path: created.path,
299
- refresh: createTarget.refresh,
307
+ setSelectionState({
308
+ activeRelativePath,
309
+ selection: {
310
+ path: created.path,
311
+ createTarget: {
312
+ label: createName.trim(),
313
+ path: created.path,
314
+ refresh: createTarget.refresh,
315
+ },
316
+ },
300
317
  });
301
318
  setRevealPath(created.path);
302
319
  };
303
320
 
304
321
  return {
305
- actions,
306
- cancelCreateFolder: () => {
307
- setCreateTarget(null);
308
- setCreateName('');
309
- setCreateError(null);
322
+ actions: {
323
+ cancelCreateFolder: () => {
324
+ setCreateTarget(null);
325
+ setCreateName('');
326
+ setCreateError(null);
327
+ },
328
+ clearSelection: () => {
329
+ setSelectionState(null);
330
+ },
331
+ completeReveal: () => setRevealPath(null),
332
+ deleteEntry,
333
+ openCreateFile: (target: WorkspaceDirectoryActionTarget) => openCreate('file', target),
334
+ openCreateFolder: (target: WorkspaceDirectoryActionTarget) => openCreate('directory', target),
335
+ renameEntry,
336
+ requestUpload,
337
+ selectEntry,
338
+ setCreateError,
339
+ setCreateName,
340
+ submitCreate,
341
+ uploadFiles,
342
+ },
343
+ refs: {
344
+ fileInputRef,
310
345
  },
311
- clearSelection: () => {
312
- setSelectedPath(null);
313
- setSelectedCreateTarget(null);
346
+ state: {
347
+ createError,
348
+ createKind,
349
+ createName,
350
+ createTarget,
351
+ pendingAction: actions.pendingAction,
352
+ revealPath,
353
+ selectedCreateTarget: selectedEntry?.createTarget ?? null,
354
+ selectedPath: selectedEntry?.path ?? null,
314
355
  },
315
- completeReveal: () => setRevealPath(null),
316
- submitCreate,
317
- createError,
318
- createName,
319
- createKind,
320
- createTarget,
321
- deleteEntry,
322
- fileInputRef,
323
- openCreateFile: (target: WorkspaceDirectoryActionTarget) => openCreate('file', target),
324
- openCreateFolder: (target: WorkspaceDirectoryActionTarget) => openCreate('directory', target),
325
- requestUpload,
326
- renameEntry,
327
- revealPath,
328
- selectEntry,
329
- selectedCreateTarget,
330
- selectedPath,
331
- setCreateError,
332
- setCreateName,
333
- uploadFiles,
334
356
  };
335
357
  }
@@ -5,7 +5,7 @@ export { usePresenter } from "./components/providers/chat-presenter.provider";
5
5
  export { ChatPresenter } from "./presenters/chat.presenter";
6
6
  export { ChatDraftIntentManager } from "./managers/chat-draft-intent.manager";
7
7
  export { ChatCompletionNotificationManager } from "./managers/chat-completion-notification.manager";
8
- export { buildSessionPath } from "./features/session/utils/chat-session-route.utils";
8
+ export { buildSessionPath, CHAT_DRAFT_SESSION_PATH } from "./features/session/utils/chat-session-route.utils";
9
9
  export { useChatSessionListStore } from "./stores/chat-session-list.store";
10
10
  export { useChatThreadStore } from "./stores/chat-thread.store";
11
11
  export { useChatMessageLayoutStore } from "./stores/chat-message-layout.store";
@@ -1,7 +1,11 @@
1
+ import type { SystemObjectResolvedReference } from '@nextclaw/shared';
2
+
1
3
  export type ChatDraftIntent = {
2
4
  id: number;
3
- prompt: string;
4
- };
5
+ } & (
6
+ | { kind: 'prompt'; prompt: string }
7
+ | { kind: 'system-object-reference'; reference: SystemObjectResolvedReference }
8
+ );
5
9
 
6
10
  type ChatDraftIntentListener = (intent: ChatDraftIntent) => void;
7
11
 
@@ -17,6 +21,7 @@ export class ChatDraftIntentManager {
17
21
  }
18
22
  const intent: ChatDraftIntent = {
19
23
  id: this.nextId + 1,
24
+ kind: 'prompt',
20
25
  prompt: normalizedPrompt,
21
26
  };
22
27
  this.nextId = intent.id;
@@ -24,6 +29,17 @@ export class ChatDraftIntentManager {
24
29
  this.listeners.forEach((listener) => listener(intent));
25
30
  };
26
31
 
32
+ requestSystemObjectReference = (reference: SystemObjectResolvedReference) => {
33
+ const intent: ChatDraftIntent = {
34
+ id: this.nextId + 1,
35
+ kind: 'system-object-reference',
36
+ reference: structuredClone(reference),
37
+ };
38
+ this.nextId = intent.id;
39
+ this.pendingIntent = intent;
40
+ this.listeners.forEach((listener) => listener(intent));
41
+ };
42
+
27
43
  consumePending = (): ChatDraftIntent | null => {
28
44
  const intent = this.pendingIntent;
29
45
  this.pendingIntent = null;
@@ -32,6 +32,7 @@ function resetChatThreadStore() {
32
32
  closedWorkspaceTabEntries: [],
33
33
  workspaceNavigationHistory: [],
34
34
  workspaceNavigationHistoryIndex: 0,
35
+ workspaceExplorerOpen: false,
35
36
  workspaceExplorerWidth: CHAT_WORKSPACE_EXPLORER_DEFAULT_WIDTH,
36
37
  workspacePanelWidth: CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
37
38
  },
@@ -74,6 +75,7 @@ describe('chat thread workspace panel persistence', () => {
74
75
  { kind: 'file', key: 'session-1::preview::README.md' },
75
76
  ],
76
77
  workspaceNavigationHistoryIndex: 1,
78
+ workspaceExplorerOpen: true,
77
79
  });
78
80
 
79
81
  const persisted = JSON.parse(window.localStorage.getItem(chatThreadWorkspaceStorageKey) ?? '{}');
@@ -88,6 +90,7 @@ describe('chat thread workspace panel persistence', () => {
88
90
  { kind: 'file', key: 'session-1::preview::README.md' },
89
91
  ],
90
92
  workspaceNavigationHistoryIndex: 1,
93
+ workspaceExplorerOpen: true,
91
94
  });
92
95
  expect(persisted.state.snapshot.sessionKey).toBeUndefined();
93
96
  expect(persisted.state.snapshot.isSending).toBeUndefined();
@@ -131,6 +134,7 @@ describe('chat thread workspace panel persistence', () => {
131
134
  activeWorkspacePanelKind: 'project-files',
132
135
  workspaceNavigationHistory: [{ kind: 'overview' }, { kind: 'child-sessions' }, { kind: 'project-files' }],
133
136
  workspaceNavigationHistoryIndex: 2,
137
+ workspaceExplorerOpen: true,
134
138
  workspaceExplorerWidth: 318,
135
139
  workspacePanelWidth: 620,
136
140
  });
@@ -147,6 +151,7 @@ describe('chat thread workspace panel persistence', () => {
147
151
  activeWorkspacePanelKind: 'project-files',
148
152
  workspaceNavigationHistory: [{ kind: 'overview' }, { kind: 'child-sessions' }, { kind: 'project-files' }],
149
153
  workspaceNavigationHistoryIndex: 2,
154
+ workspaceExplorerOpen: true,
150
155
  workspaceExplorerWidth: 318,
151
156
  workspacePanelWidth: 620,
152
157
  });
@@ -234,6 +239,7 @@ describe('chat thread workspace panel persistence', () => {
234
239
  activeWorkspacePanelKind: 'file',
235
240
  activeWorkspaceFileKey: 'session-1::preview::README.md',
236
241
  workspaceExplorerWidth: 400,
242
+ workspaceExplorerOpen: false,
237
243
  activeChildSessionKey: 'child-session-1',
238
244
  workspaceNavigationHistory: [{ kind: 'file', key: 'session-1::preview::README.md' }],
239
245
  workspaceNavigationHistoryIndex: 0,
@@ -95,6 +95,7 @@ export type ChatThreadSnapshot = {
95
95
  closedWorkspaceTabEntries: ChatWorkspaceNavigationEntry[];
96
96
  workspaceNavigationHistory: ChatWorkspaceNavigationEntry[];
97
97
  workspaceNavigationHistoryIndex: number;
98
+ workspaceExplorerOpen: boolean;
98
99
  workspaceExplorerWidth: number;
99
100
  workspacePanelWidth: number;
100
101
  contextWindow?: SessionContextWindowView | null;
@@ -119,6 +120,7 @@ type PersistedChatThreadStore = {
119
120
  closedWorkspaceTabEntries?: unknown;
120
121
  workspaceNavigationHistory?: unknown;
121
122
  workspaceNavigationHistoryIndex?: unknown;
123
+ workspaceExplorerOpen?: unknown;
122
124
  workspaceExplorerWidth?: unknown;
123
125
  workspacePanelWidth?: unknown;
124
126
  };
@@ -134,6 +136,7 @@ type PersistedChatWorkspaceSnapshot = Pick<
134
136
  | 'closedWorkspaceTabEntries'
135
137
  | 'workspaceNavigationHistory'
136
138
  | 'workspaceNavigationHistoryIndex'
139
+ | 'workspaceExplorerOpen'
137
140
  | 'workspaceExplorerWidth'
138
141
  | 'workspacePanelWidth'
139
142
  >;
@@ -167,6 +170,7 @@ const initialSnapshot: ChatThreadSnapshot = {
167
170
  closedWorkspaceTabEntries: [],
168
171
  workspaceNavigationHistory: [],
169
172
  workspaceNavigationHistoryIndex: 0,
173
+ workspaceExplorerOpen: false,
170
174
  workspaceExplorerWidth: CHAT_WORKSPACE_EXPLORER_DEFAULT_WIDTH,
171
175
  workspacePanelWidth: CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
172
176
  contextWindow: null,
@@ -281,6 +285,7 @@ function normalizePersistedWorkspaceSnapshot(value: unknown): PersistedChatWorks
281
285
  closedWorkspaceTabEntries,
282
286
  workspaceNavigationHistory,
283
287
  workspaceNavigationHistoryIndex,
288
+ workspaceExplorerOpen: value.workspaceExplorerOpen === true,
284
289
  workspaceExplorerWidth: normalizeChatWorkspaceExplorerWidth(value.workspaceExplorerWidth),
285
290
  workspacePanelWidth: normalizeChatWorkspacePanelWidth(value.workspacePanelWidth),
286
291
  };
@@ -329,6 +334,7 @@ export const useChatThreadStore = create<ChatThreadStore>()(
329
334
  ),
330
335
  workspaceNavigationHistory,
331
336
  workspaceNavigationHistoryIndex,
337
+ workspaceExplorerOpen: state.snapshot.workspaceExplorerOpen,
332
338
  workspaceExplorerWidth: state.snapshot.workspaceExplorerWidth,
333
339
  workspacePanelWidth: state.snapshot.workspacePanelWidth,
334
340
  },
@@ -1,6 +1,7 @@
1
- import { render, screen } from "@testing-library/react";
2
- import { MemoryRouter } from "react-router-dom";
1
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2
+ import { MemoryRouter, useLocation } from "react-router-dom";
3
3
  import { beforeEach, describe, expect, it, vi } from "vitest";
4
+ import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
4
5
  import { InboxReaderDialog } from "@/features/inbox/components/inbox-reader-dialog";
5
6
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
6
7
  import { t } from "@/shared/lib/i18n";
@@ -8,13 +9,17 @@ import { t } from "@/shared/lib/i18n";
8
9
  const mocks = vi.hoisted(() => ({
9
10
  closeReader: vi.fn(),
10
11
  contentType: "markdown",
11
- continueInChat: vi.fn(),
12
+ prepareChatReference: vi.fn(),
13
+ requestSystemObjectReference: vi.fn(),
12
14
  markRead: vi.fn(),
13
15
  selectInReader: vi.fn(),
14
16
  }));
15
17
 
16
18
  vi.mock("@/app/components/app-presenter-provider", () => ({
17
- useAppPresenter: () => ({ inboxManager: mocks }),
19
+ useAppPresenter: () => ({
20
+ inboxManager: mocks,
21
+ chatDraftIntentManager: { requestSystemObjectReference: mocks.requestSystemObjectReference },
22
+ }),
18
23
  }));
19
24
 
20
25
  vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
@@ -34,7 +39,6 @@ vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
34
39
  presentedAt: "2026-08-06T00:01:00.000Z",
35
40
  readAt: null,
36
41
  archivedAt: null,
37
- conversationSessionId: null,
38
42
  }],
39
43
  },
40
44
  }),
@@ -46,10 +50,20 @@ vi.mock("@nextclaw/agent-chat-ui", () => ({
46
50
  ),
47
51
  }));
48
52
 
53
+ function CurrentPath() {
54
+ return <span data-testid="current-path">{useLocation().pathname}</span>;
55
+ }
56
+
49
57
  describe("InboxReaderDialog", () => {
50
58
  beforeEach(() => {
51
59
  vi.clearAllMocks();
52
60
  mocks.contentType = "markdown";
61
+ mocks.prepareChatReference.mockResolvedValue({
62
+ reference: {
63
+ uri: "nextclaw://objects/inbox-delivery/delivery-1",
64
+ label: "A considered report",
65
+ },
66
+ });
53
67
  useInboxStore.setState({
54
68
  snapshot: { readerOpen: true, activeDeliveryId: "delivery-1" },
55
69
  });
@@ -80,4 +94,23 @@ describe("InboxReaderDialog", () => {
80
94
  .find((element) => element.tagName === "IFRAME");
81
95
  expect(htmlPreview?.className).toContain("h-full");
82
96
  });
97
+
98
+ it("opens a draft with a visible system object reference intent", async () => {
99
+ render(
100
+ <MemoryRouter initialEntries={["/inbox"]}>
101
+ <InboxReaderDialog />
102
+ <CurrentPath />
103
+ </MemoryRouter>,
104
+ );
105
+
106
+ fireEvent.click(screen.getByRole("button", { name: t("inboxContinueChat") }));
107
+
108
+ await waitFor(() => {
109
+ expect(screen.getByTestId("current-path").textContent).toBe(CHAT_DRAFT_SESSION_PATH);
110
+ });
111
+ expect(mocks.prepareChatReference).toHaveBeenCalledWith("delivery-1");
112
+ expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith(
113
+ expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }),
114
+ );
115
+ });
83
116
  });
@@ -2,6 +2,7 @@ import { useRef, useState } from "react";
2
2
  import { ChevronLeft, ChevronRight, Inbox } from "lucide-react";
3
3
  import { useNavigate } from "react-router-dom";
4
4
  import { useAppPresenter } from "@/app/components/app-presenter-provider";
5
+ import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
5
6
  import { InboxDeliveryContent } from "@/features/inbox/components/inbox-delivery-content";
6
7
  import { useInboxDeliveries } from "@/features/inbox/hooks/use-inbox-deliveries";
7
8
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
@@ -25,7 +26,7 @@ function formatPosition(current: number, total: number): string {
25
26
  export function InboxReaderDialog() {
26
27
  const titleRef = useRef<HTMLHeadingElement>(null);
27
28
  const navigate = useNavigate();
28
- const { inboxManager } = useAppPresenter();
29
+ const { chatDraftIntentManager, inboxManager } = useAppPresenter();
29
30
  const { data } = useInboxDeliveries();
30
31
  const { activeDeliveryId, readerOpen } = useInboxStore((state) => state.snapshot);
31
32
  const [pendingAction, setPendingAction] = useState<string | null>(null);
@@ -74,8 +75,9 @@ export function InboxReaderDialog() {
74
75
  return;
75
76
  }
76
77
  void runAction("continue", async () => {
77
- const result = await inboxManager.continueInChat(activeDelivery.id);
78
- navigate(`/chat/${encodeURIComponent(result.sessionId)}`);
78
+ const { reference } = await inboxManager.prepareChatReference(activeDelivery.id);
79
+ chatDraftIntentManager.requestSystemObjectReference(reference);
80
+ navigate(CHAT_DRAFT_SESSION_PATH);
79
81
  });
80
82
  };
81
83