@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
@@ -0,0 +1,134 @@
1
+ import type { ChatComposerNode } from '@nextclaw/agent-chat-ui';
2
+ import {
3
+ CHAT_CONVERSATION_EXCERPT_TOKEN_KIND,
4
+ CHAT_PROJECT_TOKEN_KIND,
5
+ CHAT_SYSTEM_OBJECT_TOKEN_KIND,
6
+ CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND,
7
+ CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
8
+ CHAT_WORKSPACE_FILE_TOKEN_KIND,
9
+ type ChatInlineTokenMetadata,
10
+ type ChatSkillSource,
11
+ } from '@nextclaw/shared';
12
+
13
+ import { serializeChatComposerTokenText } from './chat-composer-token-protocol.utils';
14
+ import { buildConversationExcerptInlineToken } from './chat-conversation-excerpt-token.utils';
15
+ import { readSystemObjectResolvedReference } from './chat-system-object-reference.utils';
16
+
17
+ export type ChatSkillReferenceSnapshot = {
18
+ ref: string;
19
+ name: string;
20
+ source: ChatSkillSource;
21
+ path: string;
22
+ };
23
+
24
+ function readOptionalString(value: unknown): string | null {
25
+ return typeof value === 'string' && value.trim() ? value.trim() : null;
26
+ }
27
+
28
+ function readOptionalLine(value: unknown): number | null {
29
+ return typeof value === 'number' && Number.isInteger(value) && value > 0
30
+ ? value
31
+ : null;
32
+ }
33
+
34
+ function dedupeInlineTokens(tokens: readonly ChatInlineTokenMetadata[]): ChatInlineTokenMetadata[] {
35
+ const seen = new Set<string>();
36
+ return tokens.filter((token) => {
37
+ const identity = 'ref' in token ? token.ref : token.key;
38
+ const dedupeKey = `${token.kind}:${identity}:${token.rawText}`;
39
+ if (seen.has(dedupeKey)) return false;
40
+ seen.add(dedupeKey);
41
+ return true;
42
+ });
43
+ }
44
+
45
+ function buildWorkspaceExcerptToken(
46
+ node: Extract<ChatComposerNode, { type: 'token' }>,
47
+ rawText: string,
48
+ ): ChatInlineTokenMetadata | null {
49
+ const path = readOptionalString(node.data?.path);
50
+ const excerpt = readOptionalString(node.data?.excerpt);
51
+ if (!path || !excerpt) return null;
52
+ return {
53
+ kind: CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
54
+ key: node.tokenKey,
55
+ path,
56
+ label: node.label,
57
+ excerpt,
58
+ startLine: readOptionalLine(node.data?.startLine),
59
+ endLine: readOptionalLine(node.data?.endLine),
60
+ rawText,
61
+ };
62
+ }
63
+
64
+ function buildStructuredReferenceToken(
65
+ node: Extract<ChatComposerNode, { type: 'token' }>,
66
+ rawText: string,
67
+ ): ChatInlineTokenMetadata | null | undefined {
68
+ if (node.tokenKind === CHAT_WORKSPACE_EXCERPT_TOKEN_KIND) {
69
+ return buildWorkspaceExcerptToken(node, rawText);
70
+ }
71
+ if (node.tokenKind === CHAT_CONVERSATION_EXCERPT_TOKEN_KIND) {
72
+ return buildConversationExcerptInlineToken(node, rawText);
73
+ }
74
+ if (node.tokenKind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) {
75
+ const reference = readSystemObjectResolvedReference(node.data?.reference);
76
+ return reference?.uri === node.tokenKey
77
+ ? {
78
+ kind: CHAT_SYSTEM_OBJECT_TOKEN_KIND,
79
+ key: node.tokenKey,
80
+ label: node.label,
81
+ rawText,
82
+ reference,
83
+ }
84
+ : null;
85
+ }
86
+ return undefined;
87
+ }
88
+
89
+ export function buildInlineTokensFromComposer(
90
+ nodes: readonly ChatComposerNode[],
91
+ skillRecords: readonly ChatSkillReferenceSnapshot[] = [],
92
+ ): ChatInlineTokenMetadata[] {
93
+ const skillByRef = new Map(skillRecords.map((record) => [record.ref, record]));
94
+ const tokens: ChatInlineTokenMetadata[] = [];
95
+ for (const node of nodes) {
96
+ if (node.type !== 'token') continue;
97
+ const rawText = serializeChatComposerTokenText(node);
98
+ if (!rawText) continue;
99
+ if (node.tokenKind === 'skill') {
100
+ const skill = skillByRef.get(node.tokenKey);
101
+ if (skill?.path.trim()) {
102
+ tokens.push({
103
+ kind: 'skill',
104
+ ref: skill.ref,
105
+ name: skill.name,
106
+ source: skill.source,
107
+ path: skill.path,
108
+ label: node.label,
109
+ rawText,
110
+ });
111
+ }
112
+ continue;
113
+ }
114
+ if (node.tokenKind === CHAT_PROJECT_TOKEN_KIND) {
115
+ tokens.push({ kind: CHAT_PROJECT_TOKEN_KIND, key: node.tokenKey, label: node.label, rawText });
116
+ continue;
117
+ }
118
+ const structuredReference = buildStructuredReferenceToken(node, rawText);
119
+ if (structuredReference !== undefined) {
120
+ if (structuredReference) tokens.push(structuredReference);
121
+ continue;
122
+ }
123
+ if (
124
+ node.tokenKind === CHAT_WORKSPACE_FILE_TOKEN_KIND ||
125
+ node.tokenKind === CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND
126
+ ) {
127
+ const workspaceKind = node.tokenKind === CHAT_WORKSPACE_FILE_TOKEN_KIND
128
+ ? CHAT_WORKSPACE_FILE_TOKEN_KIND
129
+ : CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND;
130
+ tokens.push({ kind: workspaceKind, key: node.tokenKey, label: node.label, rawText });
131
+ }
132
+ }
133
+ return dedupeInlineTokens(tokens);
134
+ }
@@ -1,18 +1,23 @@
1
- import type { ChatComposerNode } from '@nextclaw/agent-chat-ui';
2
1
  import {
3
2
  CHAT_CONVERSATION_EXCERPT_TOKEN_KIND,
4
3
  CHAT_INLINE_TOKENS_METADATA_KEY,
5
4
  CHAT_INLINE_TOKENS_SCHEMA_VERSION,
6
5
  CHAT_PROJECT_TOKEN_KIND,
6
+ CHAT_SYSTEM_OBJECT_TOKEN_KIND,
7
7
  CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND,
8
8
  CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
9
9
  CHAT_WORKSPACE_FILE_TOKEN_KIND,
10
10
  type ChatInlineTokenMetadata,
11
11
  type ChatInlineTokensMetadata,
12
12
  type ChatSkillSource,
13
+ type SystemObjectResolvedReference,
13
14
  } from '@nextclaw/shared';
14
- import { serializeChatComposerTokenText } from './chat-composer-token-protocol.utils';
15
- import { buildConversationExcerptInlineToken, readConversationExcerptInlineToken } from './chat-conversation-excerpt-token.utils';
15
+ import { readConversationExcerptInlineToken } from './chat-conversation-excerpt-token.utils';
16
+ import { readSystemObjectResolvedReference } from './chat-system-object-reference.utils';
17
+ export {
18
+ buildInlineTokensFromComposer,
19
+ type ChatSkillReferenceSnapshot,
20
+ } from './chat-inline-token-composer.utils';
16
21
 
17
22
  export { CHAT_INLINE_TOKENS_METADATA_KEY };
18
23
  const CHAT_PANEL_APP_TOKEN_PREFIX = '@panel-app:';
@@ -20,13 +25,7 @@ const CHAT_PANEL_APP_TOKEN_PATTERN = /@panel-app:([A-Za-z0-9_-]+)/g;
20
25
  const CHAT_PROJECT_TOKEN_PATTERN = /@project:([^\s]+)/g;
21
26
  const CHAT_WORKSPACE_FILE_TOKEN_PATTERN = /@file:([^\s]+)/g;
22
27
  const CHAT_WORKSPACE_DIRECTORY_TOKEN_PATTERN = /@folder:([^\s]+)/g;
23
-
24
- export type ChatSkillReferenceSnapshot = {
25
- ref: string;
26
- name: string;
27
- source: ChatSkillSource;
28
- path: string;
29
- };
28
+ const CHAT_SYSTEM_OBJECT_TOKEN_PATTERN = /@object:([^\s]+)/g;
30
29
 
31
30
  export type ChatInlineTokenSource =
32
31
  | {
@@ -62,6 +61,13 @@ export type ChatInlineTokenSource =
62
61
  key: string;
63
62
  label: string;
64
63
  rawText: string;
64
+ }
65
+ | {
66
+ kind: typeof CHAT_SYSTEM_OBJECT_TOKEN_KIND;
67
+ key: string;
68
+ label: string;
69
+ rawText: string;
70
+ reference: SystemObjectResolvedReference;
65
71
  };
66
72
 
67
73
  export function resolveWorkspaceReferencePath(params: {
@@ -114,100 +120,10 @@ function dedupeInlineTokens<T extends ChatInlineTokenSource>(tokens: readonly T[
114
120
  return output;
115
121
  }
116
122
 
117
- function appendWorkspaceExcerptToken(
118
- tokens: ChatInlineTokenMetadata[],
119
- node: Extract<ChatComposerNode, { type: 'token' }>,
120
- rawText: string,
121
- ): void {
122
- const path = readOptionalString(node.data?.path);
123
- const excerpt = readOptionalString(node.data?.excerpt);
124
- if (!path || !excerpt) return;
125
- tokens.push({
126
- kind: CHAT_WORKSPACE_EXCERPT_TOKEN_KIND,
127
- key: node.tokenKey,
128
- path,
129
- label: node.label,
130
- excerpt,
131
- startLine: readOptionalLine(node.data?.startLine),
132
- endLine: readOptionalLine(node.data?.endLine),
133
- rawText,
134
- });
135
- }
136
-
137
- export function buildInlineTokensFromComposer(
138
- nodes: readonly ChatComposerNode[],
139
- skillRecords: readonly ChatSkillReferenceSnapshot[] = [],
140
- ): ChatInlineTokenMetadata[] {
141
- const skillByRef = new Map(skillRecords.map((record) => [record.ref, record]));
142
- const tokens: ChatInlineTokenMetadata[] = [];
143
- for (const node of nodes) {
144
- if (node.type !== 'token') {
145
- continue;
146
- }
147
- if (
148
- node.tokenKind !== 'skill' &&
149
- node.tokenKind !== CHAT_PROJECT_TOKEN_KIND &&
150
- node.tokenKind !== CHAT_WORKSPACE_FILE_TOKEN_KIND &&
151
- node.tokenKind !== CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND &&
152
- node.tokenKind !== CHAT_WORKSPACE_EXCERPT_TOKEN_KIND &&
153
- node.tokenKind !== CHAT_CONVERSATION_EXCERPT_TOKEN_KIND
154
- ) {
155
- continue;
156
- }
157
- const rawText = serializeChatComposerTokenText(node);
158
- if (!rawText) {
159
- continue;
160
- }
161
- if (node.tokenKind === 'skill') {
162
- const skill = skillByRef.get(node.tokenKey);
163
- if (!skill?.path.trim()) {
164
- continue;
165
- }
166
- tokens.push({
167
- kind: 'skill',
168
- ref: skill.ref,
169
- name: skill.name,
170
- source: skill.source,
171
- path: skill.path,
172
- label: node.label,
173
- rawText,
174
- });
175
- continue;
176
- }
177
- if (node.tokenKind === CHAT_PROJECT_TOKEN_KIND) {
178
- tokens.push({
179
- kind: CHAT_PROJECT_TOKEN_KIND,
180
- key: node.tokenKey,
181
- label: node.label,
182
- rawText,
183
- });
184
- continue;
185
- }
186
- if (node.tokenKind === CHAT_WORKSPACE_EXCERPT_TOKEN_KIND) {
187
- appendWorkspaceExcerptToken(tokens, node, rawText);
188
- continue;
189
- }
190
- if (node.tokenKind === CHAT_CONVERSATION_EXCERPT_TOKEN_KIND) {
191
- const token = buildConversationExcerptInlineToken(node, rawText);
192
- if (token) tokens.push(token);
193
- continue;
194
- }
195
- const workspaceKind = node.tokenKind === CHAT_WORKSPACE_FILE_TOKEN_KIND
196
- ? CHAT_WORKSPACE_FILE_TOKEN_KIND
197
- : CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND;
198
- tokens.push({
199
- kind: workspaceKind,
200
- key: node.tokenKey,
201
- label: node.label,
202
- rawText,
203
- });
204
- }
205
- return dedupeInlineTokens(tokens);
206
- }
207
-
208
123
  function appendEncodedKeyTokens(params: {
209
124
  kind:
210
125
  | typeof CHAT_PROJECT_TOKEN_KIND
126
+ | typeof CHAT_SYSTEM_OBJECT_TOKEN_KIND
211
127
  | typeof CHAT_WORKSPACE_FILE_TOKEN_KIND
212
128
  | typeof CHAT_WORKSPACE_DIRECTORY_TOKEN_KIND;
213
129
  pattern: RegExp;
@@ -255,6 +171,12 @@ export function buildInlineTokensFromTextProtocol(text: string): ChatInlineToken
255
171
  text,
256
172
  tokens,
257
173
  });
174
+ appendEncodedKeyTokens({
175
+ kind: CHAT_SYSTEM_OBJECT_TOKEN_KIND,
176
+ pattern: CHAT_SYSTEM_OBJECT_TOKEN_PATTERN,
177
+ text,
178
+ tokens,
179
+ });
258
180
  appendEncodedKeyTokens({
259
181
  kind: CHAT_WORKSPACE_FILE_TOKEN_KIND,
260
182
  pattern: CHAT_WORKSPACE_FILE_TOKEN_PATTERN,
@@ -340,6 +262,13 @@ function readInlineTokenEntry(entry: unknown): ChatInlineTokenSource | null {
340
262
  if (kind === CHAT_CONVERSATION_EXCERPT_TOKEN_KIND) {
341
263
  return readConversationExcerptInlineToken({ entry, label, rawText });
342
264
  }
265
+ if (kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND) {
266
+ const key = readOptionalString(entry.key);
267
+ const reference = readSystemObjectResolvedReference(entry.reference);
268
+ return key && reference && reference.uri === key
269
+ ? { kind, key, label, rawText, reference }
270
+ : null;
271
+ }
343
272
  const key = readOptionalString(entry.key);
344
273
  return key ? { kind, key, rawText, label } : null;
345
274
  }
@@ -0,0 +1,44 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { CHAT_SYSTEM_OBJECT_TOKEN_KIND, type SystemObjectResolvedReference } from '@nextclaw/shared';
3
+ import {
4
+ appendSystemObjectReferenceToken,
5
+ readSystemObjectReferenceFromToken,
6
+ } from './chat-system-object-reference.utils';
7
+
8
+ const reference: SystemObjectResolvedReference = {
9
+ uri: 'nextclaw://objects/cron-job/cron-1',
10
+ objectType: 'cron-job',
11
+ objectId: 'cron-1',
12
+ label: 'Daily review',
13
+ description: 'Review reports',
14
+ updatedAt: '2026-08-11T00:00:00.000Z',
15
+ version: 'a'.repeat(64),
16
+ assetUri: 'asset://store/cron-1',
17
+ fileName: 'daily-review.md',
18
+ mimeType: 'text/markdown',
19
+ sizeBytes: 42,
20
+ };
21
+
22
+ describe('system object reference composer utilities', () => {
23
+ it('creates one visible generic token and deduplicates the same snapshot', () => {
24
+ const first = appendSystemObjectReferenceToken([], reference);
25
+ const second = appendSystemObjectReferenceToken(first, reference);
26
+
27
+ expect(second).toHaveLength(first.length);
28
+ expect(second.find((node) => node.type === 'token')).toMatchObject({
29
+ tokenKind: CHAT_SYSTEM_OBJECT_TOKEN_KIND,
30
+ tokenKey: reference.uri,
31
+ label: reference.label,
32
+ });
33
+ expect(readSystemObjectReferenceFromToken(second[0]!)).toEqual(reference);
34
+ });
35
+
36
+ it('rejects metadata whose URI identity disagrees with its object fields', () => {
37
+ const [node] = appendSystemObjectReferenceToken([], {
38
+ ...reference,
39
+ objectId: 'different-cron',
40
+ });
41
+
42
+ expect(readSystemObjectReferenceFromToken(node!)).toBeNull();
43
+ });
44
+ });
@@ -0,0 +1,46 @@
1
+ import {
2
+ createChatComposerTokenNode,
3
+ normalizeChatComposerNodes,
4
+ type ChatComposerNode,
5
+ } from '@nextclaw/agent-chat-ui';
6
+ import {
7
+ CHAT_SYSTEM_OBJECT_TOKEN_KIND,
8
+ readSystemObjectResolvedReference,
9
+ type SystemObjectResolvedReference,
10
+ } from '@nextclaw/shared';
11
+
12
+ export { readSystemObjectResolvedReference } from '@nextclaw/shared';
13
+
14
+ export function createSystemObjectReferenceTokenNode(
15
+ reference: SystemObjectResolvedReference,
16
+ ): ChatComposerNode {
17
+ return createChatComposerTokenNode({
18
+ tokenKind: CHAT_SYSTEM_OBJECT_TOKEN_KIND,
19
+ tokenKey: reference.uri,
20
+ label: reference.label,
21
+ data: { reference },
22
+ });
23
+ }
24
+
25
+ export function appendSystemObjectReferenceToken(
26
+ nodes: readonly ChatComposerNode[],
27
+ reference: SystemObjectResolvedReference,
28
+ ): ChatComposerNode[] {
29
+ const exists = nodes.some((node) =>
30
+ node.type === 'token' &&
31
+ node.tokenKind === CHAT_SYSTEM_OBJECT_TOKEN_KIND &&
32
+ node.tokenKey === reference.uri &&
33
+ readSystemObjectResolvedReference(node.data?.reference)?.version === reference.version
34
+ );
35
+ return exists
36
+ ? normalizeChatComposerNodes([...nodes])
37
+ : normalizeChatComposerNodes([...nodes, createSystemObjectReferenceTokenNode(reference)]);
38
+ }
39
+
40
+ export function readSystemObjectReferenceFromToken(
41
+ node: ChatComposerNode,
42
+ ): SystemObjectResolvedReference | null {
43
+ return node.type === 'token' && node.tokenKind === CHAT_SYSTEM_OBJECT_TOKEN_KIND
44
+ ? readSystemObjectResolvedReference(node.data?.reference)
45
+ : null;
46
+ }
@@ -248,10 +248,9 @@ describe("useHydratedNcpAgent", () => {
248
248
  );
249
249
 
250
250
  await vi.waitFor(() => {
251
- expect(result.current.hydrateError?.message).toBe(
252
- "stream disconnected",
253
- );
251
+ expect(mocks.stream).toHaveBeenCalledTimes(1);
254
252
  });
253
+ expect(result.current.hydrateError).toBeNull();
255
254
  await act(async () => {
256
255
  await vi.runOnlyPendingTimersAsync();
257
256
  });
@@ -268,4 +267,42 @@ describe("useHydratedNcpAgent", () => {
268
267
  vi.useRealTimers();
269
268
  }
270
269
  });
270
+
271
+ it("reports a stream error only after repeated immediate recovery failures", async () => {
272
+ vi.useFakeTimers();
273
+ try {
274
+ const client = {
275
+ stop: mocks.stop.mockResolvedValue(undefined),
276
+ stream: mocks.stream.mockRejectedValue(new Error("stream unavailable")),
277
+ subscribe: vi.fn(() => () => {}),
278
+ send: mocks.send,
279
+ } as unknown as NcpAgentClientEndpoint;
280
+ const loadSeed = vi.fn().mockResolvedValue({ messages: [], status: "idle" });
281
+ const { result } = renderHook(() =>
282
+ useHydratedNcpAgent({
283
+ sessionId: "session-offline",
284
+ client: client as never,
285
+ loadSeed,
286
+ }),
287
+ );
288
+
289
+ await vi.waitFor(() => expect(mocks.stream).toHaveBeenCalledTimes(1));
290
+ expect(result.current.hydrateError).toBeNull();
291
+
292
+ await act(async () => {
293
+ await vi.runOnlyPendingTimersAsync();
294
+ });
295
+ await vi.waitFor(() => expect(mocks.stream).toHaveBeenCalledTimes(2));
296
+ expect(result.current.hydrateError).toBeNull();
297
+
298
+ await act(async () => {
299
+ await vi.runOnlyPendingTimersAsync();
300
+ });
301
+ await vi.waitFor(() => {
302
+ expect(result.current.hydrateError?.message).toBe("stream unavailable");
303
+ });
304
+ } finally {
305
+ vi.useRealTimers();
306
+ }
307
+ });
271
308
  });
@@ -0,0 +1,66 @@
1
+ import type { ReactNode } from "react";
2
+ import { fireEvent, render, screen } from "@testing-library/react";
3
+ import { describe, expect, it, vi } from "vitest";
4
+ import { ChatSessionWorkspaceFilePreview } from "@/features/chat/features/workspace/components/chat-session-workspace-file-preview";
5
+
6
+ const onTextExcerptAdd = vi.fn();
7
+
8
+ vi.mock("@/shared/hooks/use-server-path-read", () => ({
9
+ useServerPathRead: () => ({
10
+ isLoading: false,
11
+ error: null,
12
+ data: {
13
+ kind: "markdown",
14
+ resolvedPath: "/Users/demo/.nextclaw/workspace/BOOT.md",
15
+ startLine: 1,
16
+ text: "Add short, explicit startup instructions.",
17
+ truncated: false,
18
+ },
19
+ }),
20
+ }));
21
+
22
+ vi.mock("@/shared/hooks/use-server-path-browse", () => ({
23
+ useServerPathBrowse: () => ({ isLoading: false, error: new Error("not a directory"), data: null }),
24
+ }));
25
+
26
+ vi.mock("@nextclaw/agent-chat-ui", () => ({
27
+ ChatMessageMarkdown: ({ text }: { text: string }) => <div>{text}</div>,
28
+ FileOperationCodeSurface: () => null,
29
+ ChatTextSelectionAction: ({ children, onAddToChat }: { children: ReactNode; onAddToChat: (value: { text: string }) => void }) => (
30
+ <div>
31
+ {children}
32
+ <button type="button" onClick={() => onAddToChat({ text: "Add short, explicit startup instructions." })}>
33
+ select excerpt
34
+ </button>
35
+ </div>
36
+ ),
37
+ }));
38
+
39
+ describe("ChatSessionWorkspaceFilePreview selection", () => {
40
+ it("uses the resolved absolute path when a shell-style workspace root cannot be compared in the browser", () => {
41
+ render(
42
+ <ChatSessionWorkspaceFilePreview
43
+ file={{
44
+ key: "boot",
45
+ parentSessionKey: null,
46
+ path: "/Users/demo/.nextclaw/workspace/BOOT.md",
47
+ label: "BOOT.md",
48
+ viewMode: "preview",
49
+ }}
50
+ sessionProjectRoot="~/.nextclaw/workspace"
51
+ sessionWorkingDir="~/.nextclaw/workspace"
52
+ onFileOpen={vi.fn()}
53
+ onTextExcerptAdd={onTextExcerptAdd}
54
+ />,
55
+ );
56
+
57
+ fireEvent.click(screen.getByRole("button", { name: "select excerpt" }));
58
+ expect(onTextExcerptAdd).toHaveBeenCalledWith({
59
+ path: "/Users/demo/.nextclaw/workspace/BOOT.md",
60
+ label: "BOOT.md",
61
+ excerpt: "Add short, explicit startup instructions.",
62
+ startLine: 1,
63
+ endLine: 1,
64
+ });
65
+ });
66
+ });
@@ -1,4 +1,5 @@
1
1
  import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2
+ import type { ReactNode } from "react";
2
3
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
4
  import type {
4
5
  ChatFileOpenActionViewModel,
@@ -38,6 +39,7 @@ vi.mock("@/shared/hooks/use-server-path-browse", () => ({
38
39
  }));
39
40
 
40
41
  vi.mock("@nextclaw/agent-chat-ui", () => ({
42
+ ChatTextSelectionAction: ({ children }: { children: ReactNode }) => children,
41
43
  ChatMessageMarkdown: ({ text }: { text: string }) => (
42
44
  <div data-testid="markdown-preview">{text}</div>
43
45
  ),
@@ -56,6 +58,16 @@ vi.mock("@nextclaw/agent-chat-ui", () => ({
56
58
  ),
57
59
  }));
58
60
 
61
+ vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
62
+ usePresenter: () => ({
63
+ chatThreadManager: { removeWorkspacePath: vi.fn(), renameWorkspacePath: vi.fn() },
64
+ chatComposerIntentManager: {
65
+ requestDirectoryReference: vi.fn(),
66
+ requestFileReference: vi.fn(),
67
+ },
68
+ }),
69
+ }));
70
+
59
71
  vi.mock("docx-preview", () => ({
60
72
  renderAsync: (...args: unknown[]) => renderDocxMock(...args),
61
73
  }));
@@ -787,7 +799,7 @@ describe("ChatSessionWorkspaceFilePreview breadcrumbs", () => {
787
799
  screen.getByTestId("workspace-file-breadcrumb-scroll").className,
788
800
  ).toContain("py-1.5");
789
801
  expect(
790
- screen.getByTestId("workspace-file-breadcrumbs").className,
802
+ screen.getByTestId("workspace-file-breadcrumb-scroll").className,
791
803
  ).toContain("workspace-horizontal-scrollbar");
792
804
  });
793
805