@nextclaw/ui 0.15.24 → 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 (312) hide show
  1. package/CHANGELOG.md +39 -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-BxPNDp30.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-DRaNWAxC.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-B4Pf5X3Q.js → dist-AYxkFx2B.js} +1 -1
  68. package/dist/assets/{dist-DHEWkGWX.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-CAFOcXNg.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-CWDp_JnN.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-Cnr71JON.js → save-CGm23Yww.js} +1 -1
  122. package/dist/assets/{search-CCX11X2m.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-BlPOuql_.js +3 -0
  125. package/dist/assets/security-config-CbDiY2xr.js +1 -0
  126. package/dist/assets/{select-DvwBu99K.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-Dmv6zMne.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-gMPvx7n_.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 +8 -8
  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 +79 -2
  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 +26 -5
  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/ncp/hooks/__tests__/use-hydrated-ncp-agent.test.tsx +40 -3
  179. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.selection.test.tsx +66 -0
  180. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +13 -1
  181. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +653 -90
  182. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-text-selection.test.tsx +12 -8
  183. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +401 -288
  184. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +54 -35
  185. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +79 -148
  186. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +156 -94
  187. package/src/features/chat/features/workspace/components/project-files/__tests__/workspace-directory-entry-menu.test.tsx +50 -0
  188. package/src/features/chat/features/workspace/components/project-files/workspace-directory-entry-menu.tsx +209 -0
  189. package/src/features/chat/features/workspace/components/project-files/workspace-directory-tree.tsx +459 -0
  190. package/src/features/chat/features/workspace/components/project-files/workspace-new-folder-tree-item.tsx +112 -0
  191. package/src/features/chat/features/workspace/components/project-files/workspace-project-files-toolbar.tsx +64 -0
  192. package/src/features/chat/features/workspace/hooks/use-workspace-explorer-layout.ts +85 -0
  193. package/src/features/chat/features/workspace/hooks/use-workspace-file-actions.ts +357 -0
  194. package/src/features/chat/features/workspace/utils/chat-workspace-file-path-mutation.utils.ts +58 -0
  195. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +23 -22
  196. package/src/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils.ts +13 -4
  197. package/src/features/chat/index.ts +1 -1
  198. package/src/features/chat/managers/__tests__/chat-composer-intent.manager.test.ts +86 -60
  199. package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +103 -99
  200. package/src/features/chat/managers/chat-composer-intent.manager.ts +37 -33
  201. package/src/features/chat/managers/chat-draft-intent.manager.ts +18 -2
  202. package/src/features/chat/managers/chat-thread.manager.ts +132 -128
  203. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +26 -40
  204. package/src/features/chat/stores/chat-thread.store.ts +53 -74
  205. package/src/features/inbox/components/inbox-reader-dialog.test.tsx +38 -5
  206. package/src/features/inbox/components/inbox-reader-dialog.tsx +5 -3
  207. package/src/features/inbox/managers/inbox.manager.test.ts +28 -3
  208. package/src/features/inbox/managers/inbox.manager.ts +14 -4
  209. package/src/features/inbox/pages/inbox-page.test.ts +121 -2
  210. package/src/features/inbox/pages/inbox-page.tsx +5 -3
  211. package/src/features/marketplace/components/__tests__/marketplace-page.test.tsx +85 -1
  212. package/src/features/marketplace/hooks/__tests__/use-marketplace.test.tsx +44 -1
  213. package/src/features/marketplace/hooks/use-marketplace-item-actions.ts +23 -2
  214. package/src/features/marketplace/hooks/use-marketplace.ts +10 -0
  215. package/src/features/marketplace/index.ts +4 -0
  216. package/src/features/panel-apps/index.ts +5 -1
  217. package/src/features/panel-apps/utils/__tests__/panel-app-doc-browser.utils.test.ts +13 -6
  218. package/src/features/panel-apps/utils/panel-app-doc-browser.utils.tsx +6 -3
  219. package/src/features/right-panel-resources/index.ts +1 -0
  220. package/src/features/right-panel-resources/utils/right-panel-resource-uri.utils.ts +7 -4
  221. package/src/features/system-status/components/__tests__/desktop-update-config.test.tsx +20 -1
  222. package/src/features/system-status/components/desktop-update-config.tsx +14 -13
  223. package/src/features/system-status/managers/__tests__/runtime-update.manager.test.ts +99 -0
  224. package/src/features/system-status/managers/runtime-update.manager.ts +22 -0
  225. package/src/features/system-status/stores/runtime-update.store.ts +1 -0
  226. package/src/shared/components/resizable-right-panel/__tests__/resizable-right-panel.test.tsx +35 -38
  227. package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +25 -19
  228. package/src/shared/components/ui/actions/__tests__/icon-action-button.test.tsx +15 -0
  229. package/src/shared/components/ui/actions/icon-action-button.tsx +4 -2
  230. package/src/shared/components/ui/context-menu/__tests__/context-menu.test.tsx +60 -34
  231. package/src/shared/components/ui/context-menu/context-menu.tsx +95 -68
  232. package/src/shared/hooks/use-system-object-references.ts +22 -0
  233. package/src/shared/lib/api/managers/client.manager.ts +31 -17
  234. package/src/shared/lib/api/server-path/server-path.types.ts +66 -0
  235. package/src/shared/lib/api/types.ts +155 -116
  236. package/src/shared/lib/api/utils/server-path.utils.ts +35 -11
  237. package/src/shared/lib/i18n/locales/en-US/chat.json +58 -9
  238. package/src/shared/lib/i18n/locales/en-US/desktop-update.json +7 -4
  239. package/src/shared/lib/i18n/locales/en-US/doc-browser.json +40 -0
  240. package/src/shared/lib/i18n/locales/en-US/marketplace.json +3 -0
  241. package/src/shared/lib/i18n/locales/zh-CN/chat.json +60 -11
  242. package/src/shared/lib/i18n/locales/zh-CN/desktop-update.json +7 -4
  243. package/src/shared/lib/i18n/locales/zh-CN/doc-browser.json +40 -0
  244. package/src/shared/lib/i18n/locales/zh-CN/marketplace.json +3 -0
  245. package/dist/assets/appearance-settings-page-DpVJjvkB.js +0 -1
  246. package/dist/assets/architecture-TIHT7OUA-Bjp9jf0h.js +0 -1
  247. package/dist/assets/channel-5T3pdR-s.js +0 -1
  248. package/dist/assets/chat-page-BuFDmG5_.js +0 -1
  249. package/dist/assets/chunk-2Q5K7J3B-DTZ3tGfE.js +0 -1
  250. package/dist/assets/chunk-VAUOI2AC-HLGIHQ6k.js +0 -1
  251. package/dist/assets/chunk-XXDRQBXY-Dl0m6Ni-.js +0 -1
  252. package/dist/assets/classDiagram-OUVF2IWQ-DcDnzGNX.js +0 -1
  253. package/dist/assets/classDiagram-v2-EOCWNBFH-BKXKMzKM.js +0 -1
  254. package/dist/assets/config-split-page-BVWVDbvG.js +0 -1
  255. package/dist/assets/confirm-dialog-mA2iVzxh.js +0 -5
  256. package/dist/assets/cynefin-VYW2F7L2-BWg7U2UD.js +0 -1
  257. package/dist/assets/desktop-update-config-DyQb1LXr.js +0 -1
  258. package/dist/assets/doc-browser-CtO_HtRy.js +0 -1
  259. package/dist/assets/doc-browser-context-CuGI6PQc.js +0 -1
  260. package/dist/assets/doc-browser-eMUagyBV.js +0 -1
  261. package/dist/assets/eventmodeling-45OFAUF4-SB-J4tpq.js +0 -1
  262. package/dist/assets/flowDiagram-23GEKE2U-BQ_u-eLM.js +0 -1
  263. package/dist/assets/form-actions-BOfIyG3O.js +0 -1
  264. package/dist/assets/gitGraph-TEB2WS4Q-DPxNwsFd.js +0 -1
  265. package/dist/assets/index-BjBdWHV1.js +0 -107
  266. package/dist/assets/index-DmpmjAGQ.css +0 -1
  267. package/dist/assets/info-DKCQHKI2-DNlNGH90.js +0 -1
  268. package/dist/assets/loader-circle-Df8wF2Pr.js +0 -1
  269. package/dist/assets/mcp-marketplace-page-DI49IKxp.js +0 -1
  270. package/dist/assets/mcp-marketplace-page-ofDqbOIF.js +0 -9
  271. package/dist/assets/model-config-page-D73Tu3jW.js +0 -1
  272. package/dist/assets/packet-7NZHBO7P-BpeiqkBZ.js +0 -1
  273. package/dist/assets/pie-RZYD4A2V-Cy1yxsPd.js +0 -1
  274. package/dist/assets/plus-DVU5RLCS.js +0 -1
  275. package/dist/assets/provider-scoped-model-input-BaJJJYMX.js +0 -1
  276. package/dist/assets/providers-config-page-BL6IRVBm.js +0 -1
  277. package/dist/assets/radar-I7S5WNFK-CEcPKCj8.js +0 -1
  278. package/dist/assets/railroad-3IZDKUUU-CW38eNDs.js +0 -1
  279. package/dist/assets/railroad-abnf-AHOZXSZD-ByrylcXf.js +0 -1
  280. package/dist/assets/railroad-ebnf-EBAXGLYW-CNB6GwP-.js +0 -1
  281. package/dist/assets/railroad-peg-LSFZ7HO6-x6hnqlBG.js +0 -1
  282. package/dist/assets/react-BC_orpAj.js +0 -8
  283. package/dist/assets/remote-T24O58lH.js +0 -1
  284. package/dist/assets/rotate-cw-BqhwSV5p.js +0 -1
  285. package/dist/assets/runtime-config-page-CXUx017t.js +0 -1
  286. package/dist/assets/search-config-page-BB6d5gT7.js +0 -1
  287. package/dist/assets/secrets-config-page-DYsDeT9K.js +0 -3
  288. package/dist/assets/security-config-CVPgqL7G.js +0 -1
  289. package/dist/assets/skeleton-C5tWata3.js +0 -1
  290. package/dist/assets/stateDiagram-v2-6OUMAXLB-ZC6dFORv.js +0 -1
  291. package/dist/assets/swimlanesDiagram-G3AALYLV-CRkh51Im.js +0 -8
  292. package/dist/assets/treeView-QDETBFTQ-Bw0DSCH7.js +0 -1
  293. package/dist/assets/treemap-6X3UGDF4-DFWBFcfh.js +0 -1
  294. package/dist/assets/use-confirm-dialog-D_3-QpZU.js +0 -1
  295. package/dist/assets/wardley-OPB4EBWU-CoWturk0.js +0 -1
  296. package/dist/assets/x-BEWSqeux.js +0 -1
  297. /package/dist/assets/{array-NADKd9aU.js → array-BQVzeGRt.js} +0 -0
  298. /package/dist/assets/{chunk-KEIR6QF5-BuyuzJJL.js → chunk-KEIR6QF5-f9psyCXK.js} +0 -0
  299. /package/dist/assets/{chunk-Y2CYZVJY-D_B2ZRNt.js → chunk-Y2CYZVJY-D1mAU_Po.js} +0 -0
  300. /package/dist/assets/{config-hints-BcfVUMij.js → config-hints-nV5HPOvq.js} +0 -0
  301. /package/dist/assets/{cytoscape.esm-BANTlgza.js → cytoscape.esm-0uDtdD0l.js} +0 -0
  302. /package/dist/assets/{defaultLocale-C4_L0aEs.js → defaultLocale-DSWXGgt0.js} +0 -0
  303. /package/dist/assets/{dist-DAPEIJbz.js → dist--ta5rX12.js} +0 -0
  304. /package/dist/assets/{graphlib-ChqXg0dI.js → graphlib-CQ6QV4yP.js} +0 -0
  305. /package/dist/assets/{host-capabilities-D9C4CBK5.js → host-capabilities-Tk038i04.js} +0 -0
  306. /package/dist/assets/{init-D8wZg9xq.js → init-Y6h9jGtZ.js} +0 -0
  307. /package/dist/assets/{jszip.min-CkbBfwAQ.js → jszip.min-8hyJpgpx.js} +0 -0
  308. /package/dist/assets/{katex-TZJFa0J_.js → katex-ARhY9PS1.js} +0 -0
  309. /package/dist/assets/{middleware-B3k-TSmZ.js → middleware-DXsbf9xI.js} +0 -0
  310. /package/dist/assets/{path-DodfxcX7.js → path-10BjdyLh.js} +0 -0
  311. /package/dist/assets/{rough.esm-CUaa1Rbe.js → rough.esm-DxgC_14r.js} +0 -0
  312. /package/dist/assets/{xlsx-CxByi7bR.js → xlsx-DrDuDNAa.js} +0 -0
@@ -1,22 +1,17 @@
1
1
  import { create } from 'zustand';
2
2
  import { createJSONStorage, persist } from 'zustand/middleware';
3
3
  import type { NcpMessage } from '@nextclaw/ncp';
4
- import type {
5
- ChatContentParams,
6
- ChatFileOperationLineViewModel,
7
- ChatFilePreviewViewer,
8
- } from '@nextclaw/agent-chat-ui';
9
- import type {
10
- SessionContextWindowView,
11
- SessionTypeIconView
12
- } from '@/shared/lib/api';
4
+ import type { ChatContentParams, ChatFileOperationLineViewModel, ChatFilePreviewViewer } from '@nextclaw/agent-chat-ui';
5
+ import type { SessionContextWindowView, SessionTypeIconView } from '@/shared/lib/api';
13
6
  import {
14
7
  normalizePersistedWorkspaceFileTab,
15
8
  retainWorkspaceFileTabs,
16
9
  toPersistedWorkspaceFileTab,
17
10
  } from '@/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils';
18
11
  import {
12
+ CHAT_WORKSPACE_EXPLORER_DEFAULT_WIDTH,
19
13
  CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
14
+ normalizeChatWorkspaceExplorerWidth,
20
15
  normalizeChatWorkspacePanelWidth,
21
16
  } from '@/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils';
22
17
  import { createWorkspaceNavigationEntryFromSnapshot } from '@/features/chat/features/workspace/utils/chat-thread-workspace-session.utils';
@@ -100,6 +95,8 @@ export type ChatThreadSnapshot = {
100
95
  closedWorkspaceTabEntries: ChatWorkspaceNavigationEntry[];
101
96
  workspaceNavigationHistory: ChatWorkspaceNavigationEntry[];
102
97
  workspaceNavigationHistoryIndex: number;
98
+ workspaceExplorerOpen: boolean;
99
+ workspaceExplorerWidth: number;
103
100
  workspacePanelWidth: number;
104
101
  contextWindow?: SessionContextWindowView | null;
105
102
  };
@@ -123,6 +120,8 @@ type PersistedChatThreadStore = {
123
120
  closedWorkspaceTabEntries?: unknown;
124
121
  workspaceNavigationHistory?: unknown;
125
122
  workspaceNavigationHistoryIndex?: unknown;
123
+ workspaceExplorerOpen?: unknown;
124
+ workspaceExplorerWidth?: unknown;
126
125
  workspacePanelWidth?: unknown;
127
126
  };
128
127
  };
@@ -137,6 +136,8 @@ type PersistedChatWorkspaceSnapshot = Pick<
137
136
  | 'closedWorkspaceTabEntries'
138
137
  | 'workspaceNavigationHistory'
139
138
  | 'workspaceNavigationHistoryIndex'
139
+ | 'workspaceExplorerOpen'
140
+ | 'workspaceExplorerWidth'
140
141
  | 'workspacePanelWidth'
141
142
  >;
142
143
 
@@ -169,8 +170,10 @@ const initialSnapshot: ChatThreadSnapshot = {
169
170
  closedWorkspaceTabEntries: [],
170
171
  workspaceNavigationHistory: [],
171
172
  workspaceNavigationHistoryIndex: 0,
173
+ workspaceExplorerOpen: false,
174
+ workspaceExplorerWidth: CHAT_WORKSPACE_EXPLORER_DEFAULT_WIDTH,
172
175
  workspacePanelWidth: CHAT_WORKSPACE_PANEL_DEFAULT_WIDTH,
173
- contextWindow: null
176
+ contextWindow: null,
174
177
  };
175
178
 
176
179
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -178,20 +181,14 @@ function isRecord(value: unknown): value is Record<string, unknown> {
178
181
  }
179
182
 
180
183
  function normalizeOptionalString(value: unknown): string | null {
181
- return typeof value === 'string' && value.trim().length > 0
182
- ? value.trim()
183
- : null;
184
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
184
185
  }
185
186
 
186
187
  function normalizeHistoryIndex(value: unknown, maxIndex: number): number {
187
- return typeof value === 'number' && Number.isInteger(value)
188
- ? Math.min(Math.max(0, value), maxIndex)
189
- : maxIndex;
188
+ return typeof value === 'number' && Number.isInteger(value) ? Math.min(Math.max(0, value), maxIndex) : maxIndex;
190
189
  }
191
190
 
192
- function isWorkspacePanelKind(
193
- value: unknown,
194
- ): value is PersistedWorkspacePanelKind {
191
+ function isWorkspacePanelKind(value: unknown): value is PersistedWorkspacePanelKind {
195
192
  return (
196
193
  value === 'overview' ||
197
194
  value === 'child-sessions' ||
@@ -202,9 +199,7 @@ function isWorkspacePanelKind(
202
199
  );
203
200
  }
204
201
 
205
- function normalizePersistedWorkspaceNavigationEntry(
206
- value: unknown,
207
- ): ChatWorkspaceNavigationEntry | null {
202
+ function normalizePersistedWorkspaceNavigationEntry(value: unknown): ChatWorkspaceNavigationEntry | null {
208
203
  if (!isRecord(value)) {
209
204
  return null;
210
205
  }
@@ -226,9 +221,7 @@ function normalizePersistedWorkspaceNavigationEntry(
226
221
  };
227
222
  }
228
223
 
229
- function normalizePersistedWorkspaceSnapshot(
230
- value: unknown,
231
- ): PersistedChatWorkspaceSnapshot | null {
224
+ function normalizePersistedWorkspaceSnapshot(value: unknown): PersistedChatWorkspaceSnapshot | null {
232
225
  if (!isRecord(value)) {
233
226
  return null;
234
227
  }
@@ -236,35 +229,29 @@ function normalizePersistedWorkspaceSnapshot(
236
229
  const activeWorkspaceFileKey = normalizeOptionalString(value.activeWorkspaceFileKey);
237
230
  const normalizedWorkspaceFileTabs = Array.isArray(value.workspaceFileTabs)
238
231
  ? value.workspaceFileTabs
239
- .map(normalizePersistedWorkspaceFileTab)
240
- .filter((tab): tab is ChatWorkspaceFileTab => tab !== null)
232
+ .map(normalizePersistedWorkspaceFileTab)
233
+ .filter((tab): tab is ChatWorkspaceFileTab => tab !== null)
241
234
  : [];
242
235
  const workspaceFileTabs = retainWorkspaceFileTabs(
243
236
  normalizedWorkspaceFileTabs,
244
237
  activeWorkspaceFileKey,
245
238
  CHAT_THREAD_MAX_PERSISTED_WORKSPACE_FILE_TABS,
246
239
  );
247
- const sessionWorkspaceFileTabs = workspaceFileTabs.filter(
248
- (tab) => tab.parentSessionKey === workspacePanelParentKey,
249
- );
240
+ const sessionWorkspaceFileTabs = workspaceFileTabs.filter((tab) => tab.parentSessionKey === workspacePanelParentKey);
250
241
  const resolvedActiveWorkspaceFileKey =
251
242
  activeWorkspaceFileKey && sessionWorkspaceFileTabs.some((tab) => tab.key === activeWorkspaceFileKey)
252
243
  ? activeWorkspaceFileKey
253
- : sessionWorkspaceFileTabs[0]?.key ?? null;
244
+ : (sessionWorkspaceFileTabs[0]?.key ?? null);
254
245
  const activeWorkspacePanelKind = isWorkspacePanelKind(value.activeWorkspacePanelKind)
255
246
  ? value.activeWorkspacePanelKind
256
247
  : null;
257
248
  const resolvedActiveWorkspacePanelKind =
258
- activeWorkspacePanelKind === 'file' && !resolvedActiveWorkspaceFileKey
259
- ? null
260
- : activeWorkspacePanelKind;
249
+ activeWorkspacePanelKind === 'file' && !resolvedActiveWorkspaceFileKey ? null : activeWorkspacePanelKind;
261
250
  const activeChildSessionKey = normalizeOptionalString(value.activeChildSessionKey);
262
251
  const closedWorkspaceTabEntries = Array.isArray(value.closedWorkspaceTabEntries)
263
252
  ? value.closedWorkspaceTabEntries
264
- .map(normalizePersistedWorkspaceNavigationEntry)
265
- .filter((entry): entry is ChatWorkspaceNavigationEntry =>
266
- entry !== null && entry.kind !== 'overview',
267
- )
253
+ .map(normalizePersistedWorkspaceNavigationEntry)
254
+ .filter((entry): entry is ChatWorkspaceNavigationEntry => entry !== null && entry.kind !== 'overview')
268
255
  : [];
269
256
  const fallbackHistoryEntry = createWorkspaceNavigationEntryFromSnapshot({
270
257
  activeWorkspacePanelKind: resolvedActiveWorkspacePanelKind,
@@ -274,11 +261,9 @@ function normalizePersistedWorkspaceSnapshot(
274
261
  });
275
262
  const normalizedNavigationHistory = Array.isArray(value.workspaceNavigationHistory)
276
263
  ? value.workspaceNavigationHistory
277
- .map(normalizePersistedWorkspaceNavigationEntry)
278
- .filter((entry): entry is ChatWorkspaceNavigationEntry => entry !== null)
279
- .filter((entry) =>
280
- entry.kind !== 'file' || workspaceFileTabs.some((tab) => tab.key === entry.key),
281
- )
264
+ .map(normalizePersistedWorkspaceNavigationEntry)
265
+ .filter((entry): entry is ChatWorkspaceNavigationEntry => entry !== null)
266
+ .filter((entry) => entry.kind !== 'file' || workspaceFileTabs.some((tab) => tab.key === entry.key))
282
267
  : [];
283
268
  const workspaceNavigationHistory =
284
269
  normalizedNavigationHistory.length > 0
@@ -288,10 +273,7 @@ function normalizePersistedWorkspaceSnapshot(
288
273
  : [];
289
274
  const workspaceNavigationHistoryIndex =
290
275
  workspaceNavigationHistory.length > 0
291
- ? normalizeHistoryIndex(
292
- value.workspaceNavigationHistoryIndex,
293
- workspaceNavigationHistory.length - 1,
294
- )
276
+ ? normalizeHistoryIndex(value.workspaceNavigationHistoryIndex, workspaceNavigationHistory.length - 1)
295
277
  : 0;
296
278
 
297
279
  return {
@@ -303,9 +285,9 @@ function normalizePersistedWorkspaceSnapshot(
303
285
  closedWorkspaceTabEntries,
304
286
  workspaceNavigationHistory,
305
287
  workspaceNavigationHistoryIndex,
306
- workspacePanelWidth: normalizeChatWorkspacePanelWidth(
307
- value.workspacePanelWidth,
308
- ),
288
+ workspaceExplorerOpen: value.workspaceExplorerOpen === true,
289
+ workspaceExplorerWidth: normalizeChatWorkspaceExplorerWidth(value.workspaceExplorerWidth),
290
+ workspacePanelWidth: normalizeChatWorkspacePanelWidth(value.workspacePanelWidth),
309
291
  };
310
292
  }
311
293
 
@@ -317,23 +299,21 @@ export const useChatThreadStore = create<ChatThreadStore>()(
317
299
  set((state) => ({
318
300
  snapshot: {
319
301
  ...state.snapshot,
320
- ...patch
321
- }
322
- }))
302
+ ...patch,
303
+ },
304
+ })),
323
305
  }),
324
306
  {
325
307
  name: CHAT_THREAD_WORKSPACE_STORAGE_KEY,
326
308
  version: CHAT_THREAD_WORKSPACE_STORAGE_VERSION,
327
309
  storage: createJSONStorage(() => window.localStorage),
328
310
  partialize: (state): PersistedChatThreadStore => {
329
- const workspaceNavigationHistory = state.snapshot.workspaceNavigationHistory
330
- .filter((entry) => entry.kind !== 'side-chat-draft');
311
+ const workspaceNavigationHistory = state.snapshot.workspaceNavigationHistory.filter(
312
+ (entry) => entry.kind !== 'side-chat-draft',
313
+ );
331
314
  const workspaceNavigationHistoryIndex =
332
315
  workspaceNavigationHistory.length > 0
333
- ? Math.min(
334
- state.snapshot.workspaceNavigationHistoryIndex,
335
- workspaceNavigationHistory.length - 1,
336
- )
316
+ ? Math.min(state.snapshot.workspaceNavigationHistoryIndex, workspaceNavigationHistory.length - 1)
337
317
  : 0;
338
318
  return {
339
319
  snapshot: {
@@ -347,23 +327,22 @@ export const useChatThreadStore = create<ChatThreadStore>()(
347
327
  state.snapshot.workspaceFileTabs,
348
328
  state.snapshot.activeWorkspaceFileKey,
349
329
  CHAT_THREAD_MAX_PERSISTED_WORKSPACE_FILE_TABS,
350
- )
351
- .map(toPersistedWorkspaceFileTab),
330
+ ).map(toPersistedWorkspaceFileTab),
352
331
  activeWorkspaceFileKey: state.snapshot.activeWorkspaceFileKey,
353
- closedWorkspaceTabEntries: state.snapshot.closedWorkspaceTabEntries
354
- .filter((entry) => entry.kind !== 'overview' && entry.kind !== 'side-chat-draft'),
332
+ closedWorkspaceTabEntries: state.snapshot.closedWorkspaceTabEntries.filter(
333
+ (entry) => entry.kind !== 'overview' && entry.kind !== 'side-chat-draft',
334
+ ),
355
335
  workspaceNavigationHistory,
356
336
  workspaceNavigationHistoryIndex,
337
+ workspaceExplorerOpen: state.snapshot.workspaceExplorerOpen,
338
+ workspaceExplorerWidth: state.snapshot.workspaceExplorerWidth,
357
339
  workspacePanelWidth: state.snapshot.workspacePanelWidth,
358
- }
340
+ },
359
341
  };
360
342
  },
361
343
  merge: (persistedState, currentState) => {
362
- const persistedSnapshot = isRecord(persistedState)
363
- ? persistedState.snapshot
364
- : null;
365
- const workspaceSnapshot =
366
- normalizePersistedWorkspaceSnapshot(persistedSnapshot);
344
+ const persistedSnapshot = isRecord(persistedState) ? persistedState.snapshot : null;
345
+ const workspaceSnapshot = normalizePersistedWorkspaceSnapshot(persistedSnapshot);
367
346
  if (!workspaceSnapshot) {
368
347
  return currentState;
369
348
  }
@@ -371,10 +350,10 @@ export const useChatThreadStore = create<ChatThreadStore>()(
371
350
  ...currentState,
372
351
  snapshot: {
373
352
  ...currentState.snapshot,
374
- ...workspaceSnapshot
375
- }
353
+ ...workspaceSnapshot,
354
+ },
376
355
  };
377
- }
378
- }
379
- )
356
+ },
357
+ },
358
+ ),
380
359
  );
@@ -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
 
@@ -6,7 +6,7 @@ import { useInboxStore } from "@/features/inbox/stores/inbox.store";
6
6
 
7
7
  const mocks = vi.hoisted(() => ({
8
8
  delete: vi.fn(),
9
- continueInChat: vi.fn(),
9
+ resolveReference: vi.fn(),
10
10
  list: vi.fn(),
11
11
  on: vi.fn(() => vi.fn()),
12
12
  updateState: vi.fn(),
@@ -17,10 +17,12 @@ vi.mock("@/shared/lib/api", () => ({
17
17
  eventBus: { on: mocks.on },
18
18
  inboxDeliveries: {
19
19
  delete: mocks.delete,
20
- continueInChat: mocks.continueInChat,
21
20
  list: mocks.list,
22
21
  updateState: mocks.updateState,
23
22
  },
23
+ systemObjectReferences: {
24
+ resolve: mocks.resolveReference,
25
+ },
24
26
  },
25
27
  }));
26
28
 
@@ -36,7 +38,6 @@ const delivery: InboxDelivery = {
36
38
  presentedAt: null,
37
39
  readAt: null,
38
40
  archivedAt: null,
39
- conversationSessionId: null,
40
41
  };
41
42
 
42
43
  describe("InboxManager", () => {
@@ -57,6 +58,19 @@ describe("InboxManager", () => {
57
58
  presentedAt: action === "present" || action === "read" ? "2026-08-06T01:00:00.000Z" : null,
58
59
  readAt: action === "read" ? "2026-08-06T01:00:00.000Z" : null,
59
60
  }));
61
+ mocks.resolveReference.mockResolvedValue({
62
+ uri: "nextclaw://objects/inbox-delivery/delivery-1",
63
+ objectType: "inbox-delivery",
64
+ objectId: "delivery-1",
65
+ label: "Brief",
66
+ description: null,
67
+ updatedAt: delivery.updatedAt,
68
+ version: "version-1",
69
+ assetUri: "asset://store/report",
70
+ fileName: "brief.md",
71
+ mimeType: "text/markdown",
72
+ sizeBytes: 7,
73
+ });
60
74
  });
61
75
 
62
76
  it("auto-opens the oldest unpresented item and only marks it presented", async () => {
@@ -83,4 +97,15 @@ describe("InboxManager", () => {
83
97
  expect(mocks.updateState).toHaveBeenCalledTimes(1);
84
98
  expect(mocks.updateState).toHaveBeenCalledWith(delivery.id, "present");
85
99
  });
100
+
101
+ it("prepares a generic immutable report reference before marking it read", async () => {
102
+ const manager = new InboxManager(new QueryClient());
103
+ const result = await manager.prepareChatReference(delivery.id);
104
+
105
+ expect(mocks.resolveReference).toHaveBeenCalledWith(
106
+ "nextclaw://objects/inbox-delivery/delivery-1",
107
+ );
108
+ expect(mocks.updateState).toHaveBeenCalledWith(delivery.id, "read");
109
+ expect(result.reference.assetUri).toBe("asset://store/report");
110
+ });
86
111
  });
@@ -5,6 +5,11 @@ import type {
5
5
  InboxDeliveryStateAction,
6
6
  } from "@nextclaw/shared";
7
7
  import { eventKeys } from "@nextclaw/shared";
8
+ import {
9
+ createSystemObjectReferenceUri,
10
+ SYSTEM_OBJECT_TYPE_INBOX_DELIVERY,
11
+ type SystemObjectResolvedReference,
12
+ } from "@nextclaw/shared";
8
13
  import { appQueryClient } from "@/app-query-client";
9
14
  import { useInboxStore } from "@/features/inbox/stores/inbox.store";
10
15
  import { nextclawClient } from "@/shared/lib/api";
@@ -104,11 +109,16 @@ export class InboxManager {
104
109
  return deleted;
105
110
  };
106
111
 
107
- continueInChat = async (deliveryId: string) => {
108
- const result = await nextclawClient.inboxDeliveries.continueInChat(deliveryId);
109
- this.replaceCachedDelivery(result.delivery);
112
+ prepareChatReference = async (deliveryId: string): Promise<{
113
+ delivery: InboxDelivery;
114
+ reference: SystemObjectResolvedReference;
115
+ }> => {
116
+ const reference = await nextclawClient.systemObjectReferences.resolve(
117
+ createSystemObjectReferenceUri(SYSTEM_OBJECT_TYPE_INBOX_DELIVERY, deliveryId),
118
+ );
119
+ const delivery = await this.updateState(deliveryId, "read");
110
120
  this.closeReader();
111
- return result;
121
+ return { delivery, reference };
112
122
  };
113
123
 
114
124
  private updateState = async (
@@ -1,5 +1,76 @@
1
- import { describe, expect, it } from "vitest";
2
- import { resolveInboxFilter } from "@/features/inbox/pages/inbox-page";
1
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2
+ import { createElement } from "react";
3
+ import { MemoryRouter, Route, Routes, useLocation } from "react-router-dom";
4
+ import { beforeEach, describe, expect, it, vi } from "vitest";
5
+ import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
6
+ import { InboxPage, resolveInboxFilter } from "@/features/inbox/pages/inbox-page";
7
+ import { t } from "@/shared/lib/i18n";
8
+
9
+ const mocks = vi.hoisted(() => ({
10
+ prepareChatReference: vi.fn(),
11
+ requestSystemObjectReference: vi.fn(),
12
+ }));
13
+
14
+ vi.mock("@/app/components/app-presenter-provider", () => ({
15
+ useAppPresenter: () => ({
16
+ chatDraftIntentManager: {
17
+ requestSystemObjectReference: mocks.requestSystemObjectReference,
18
+ },
19
+ inboxManager: {
20
+ archive: vi.fn(),
21
+ delete: vi.fn(),
22
+ markRead: vi.fn(),
23
+ markUnread: vi.fn(),
24
+ prepareChatReference: mocks.prepareChatReference,
25
+ restore: vi.fn(),
26
+ },
27
+ }),
28
+ }));
29
+
30
+ vi.mock("@/app/hooks/use-viewport-layout", () => ({
31
+ useViewportLayout: () => ({ isMobile: false }),
32
+ }));
33
+
34
+ vi.mock("@/features/inbox/hooks/use-inbox-deliveries", () => ({
35
+ useInboxDeliveries: () => ({
36
+ data: {
37
+ deliveries: [{
38
+ id: "delivery-1",
39
+ title: "A considered report",
40
+ summary: "A concise summary",
41
+ content: "# Finding",
42
+ contentType: "markdown",
43
+ source: { kind: "agent", agentId: null, sessionId: null, toolCallId: null, filePath: null },
44
+ createdAt: "2026-08-06T00:00:00.000Z",
45
+ updatedAt: "2026-08-06T00:00:00.000Z",
46
+ presentedAt: "2026-08-06T00:01:00.000Z",
47
+ readAt: "2026-08-06T00:02:00.000Z",
48
+ archivedAt: null,
49
+ }],
50
+ },
51
+ isError: false,
52
+ }),
53
+ }));
54
+
55
+ vi.mock("@/features/inbox/components/inbox-delivery-content", () => ({
56
+ InboxDeliveryContent: ({ content }: { content: string }) =>
57
+ createElement("article", null, content),
58
+ }));
59
+
60
+ vi.mock("@/shared/hooks/use-confirm-dialog", () => ({
61
+ useConfirmDialog: () => ({
62
+ confirm: vi.fn(async () => true),
63
+ ConfirmDialog: () => null,
64
+ }),
65
+ }));
66
+
67
+ function CurrentPath() {
68
+ return createElement(
69
+ "span",
70
+ { "data-testid": "current-path" },
71
+ useLocation().pathname,
72
+ );
73
+ }
3
74
 
4
75
  const readDelivery = {
5
76
  archivedAt: null,
@@ -26,3 +97,51 @@ describe("resolveInboxFilter", () => {
26
97
  expect(resolveInboxFilter([unreadDelivery], "archived")).toBe("archived");
27
98
  });
28
99
  });
100
+
101
+ describe("InboxPage", () => {
102
+ beforeEach(() => {
103
+ vi.clearAllMocks();
104
+ mocks.prepareChatReference.mockResolvedValue({
105
+ reference: {
106
+ uri: "nextclaw://objects/inbox-delivery/delivery-1",
107
+ label: "A considered report",
108
+ },
109
+ });
110
+ });
111
+
112
+ it("opens a draft with the same visible system object intent as the reader dialog", async () => {
113
+ render(
114
+ createElement(
115
+ MemoryRouter,
116
+ { initialEntries: ["/inbox/delivery-1"] },
117
+ createElement(
118
+ Routes,
119
+ null,
120
+ createElement(Route, {
121
+ path: "/inbox/:deliveryId",
122
+ element: createElement(
123
+ "div",
124
+ null,
125
+ createElement(InboxPage),
126
+ createElement(CurrentPath),
127
+ ),
128
+ }),
129
+ createElement(Route, {
130
+ path: "*",
131
+ element: createElement(CurrentPath),
132
+ }),
133
+ ),
134
+ ),
135
+ );
136
+
137
+ fireEvent.click(screen.getByRole("button", { name: t("inboxContinueChat") }));
138
+
139
+ await waitFor(() => {
140
+ expect(screen.getByTestId("current-path").textContent).toBe(CHAT_DRAFT_SESSION_PATH);
141
+ });
142
+ expect(mocks.prepareChatReference).toHaveBeenCalledWith("delivery-1");
143
+ expect(mocks.requestSystemObjectReference).toHaveBeenCalledWith(
144
+ expect.objectContaining({ uri: "nextclaw://objects/inbox-delivery/delivery-1" }),
145
+ );
146
+ });
147
+ });
@@ -5,6 +5,7 @@ import { Link, useNavigate, useParams } from "react-router-dom";
5
5
  import { useAppPresenter } from "@/app/components/app-presenter-provider";
6
6
  import { PageHeader } from "@/app/components/layout/page-layout";
7
7
  import { useViewportLayout } from "@/app/hooks/use-viewport-layout";
8
+ import { CHAT_DRAFT_SESSION_PATH } from "@/features/chat";
8
9
  import { InboxDeliveryContent } from "@/features/inbox/components/inbox-delivery-content";
9
10
  import { useInboxDeliveries } from "@/features/inbox/hooks/use-inbox-deliveries";
10
11
  import { Button } from "@/shared/components/ui/button";
@@ -246,7 +247,7 @@ export function InboxPage() {
246
247
  const navigate = useNavigate();
247
248
  const { deliveryId } = useParams<{ deliveryId?: string }>();
248
249
  const { isMobile } = useViewportLayout();
249
- const { inboxManager } = useAppPresenter();
250
+ const { chatDraftIntentManager, inboxManager } = useAppPresenter();
250
251
  const deliveriesQuery = useInboxDeliveries();
251
252
  const { confirm, ConfirmDialog } = useConfirmDialog();
252
253
  const [selectedFilter, setSelectedFilter] = useState<InboxFilter | null>(null);
@@ -287,8 +288,9 @@ export function InboxPage() {
287
288
  return;
288
289
  }
289
290
  void runAction("continue", async () => {
290
- const result = await inboxManager.continueInChat(activeDelivery.id);
291
- navigate(`/chat/${encodeURIComponent(result.sessionId)}`);
291
+ const { reference } = await inboxManager.prepareChatReference(activeDelivery.id);
292
+ chatDraftIntentManager.requestSystemObjectReference(reference);
293
+ navigate(CHAT_DRAFT_SESSION_PATH);
292
294
  });
293
295
  };
294
296