@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
@@ -4,6 +4,7 @@ import { MemoryRouter } from "react-router-dom";
4
4
  import { describe, expect, it, vi, beforeEach } from "vitest";
5
5
 
6
6
  import { SessionConversationArea } from "@/features/chat/features/conversation/components/session-conversation-area";
7
+ import type { ChatDraftIntent } from "@/features/chat/managers/chat-draft-intent.manager";
7
8
 
8
9
  const mocks = vi.hoisted(() => {
9
10
  const inputRenderSpy = vi.fn();
@@ -106,6 +107,7 @@ const mocks = vi.hoisted(() => {
106
107
  inputRenderSpy,
107
108
  initialPromptSpy,
108
109
  inputSnapshot,
110
+ runtimeBlocked: false,
109
111
  presenter: {
110
112
  chatUiManager: {
111
113
  goToProviders: vi.fn(),
@@ -117,7 +119,7 @@ const mocks = vi.hoisted(() => {
117
119
  },
118
120
  appPresenter: {
119
121
  chatDraftIntentManager: {
120
- consumePending: vi.fn(() => null),
122
+ consumePending: vi.fn<() => ChatDraftIntent | null>(() => null),
121
123
  markConsumed: vi.fn(),
122
124
  subscribe: vi.fn(() => vi.fn()),
123
125
  },
@@ -139,12 +141,14 @@ vi.mock(
139
141
  ChatConversationContent: ({
140
142
  bottomSlot,
141
143
  isContextCompacting,
144
+ messageActionsDisabled,
142
145
  messages,
143
146
  showWelcome,
144
147
  welcomeSlot,
145
148
  }: {
146
149
  bottomSlot?: ReactNode;
147
150
  isContextCompacting?: boolean;
151
+ messageActionsDisabled?: boolean;
148
152
  messages: readonly unknown[];
149
153
  showWelcome: boolean;
150
154
  welcomeSlot?: ReactNode;
@@ -152,6 +156,7 @@ vi.mock(
152
156
  <div
153
157
  data-testid="conversation-content"
154
158
  data-context-compacting={String(Boolean(isContextCompacting))}
159
+ data-message-actions-disabled={String(Boolean(messageActionsDisabled))}
155
160
  data-show-welcome={String(showWelcome)}
156
161
  >
157
162
  {showWelcome ? (
@@ -198,7 +203,7 @@ vi.mock(
198
203
  vi.mock(
199
204
  "@/features/chat/features/runtime/utils/ncp-chat-runtime-availability.utils",
200
205
  () => ({
201
- isNcpChatRuntimeBlocked: () => false,
206
+ isNcpChatRuntimeBlocked: () => mocks.runtimeBlocked,
202
207
  resolveNcpChatSendErrorMessage: ({ message }: { message: string | null }) =>
203
208
  message,
204
209
  }),
@@ -273,6 +278,7 @@ describe("SessionConversationArea input boundary", () => {
273
278
  mocks.agent.snapshot.contextWindow = null;
274
279
  mocks.agent.snapshot.error = null;
275
280
  mocks.controller.isSending = true;
281
+ mocks.runtimeBlocked = false;
276
282
  mocks.inputSnapshot.sendError = null;
277
283
  mocks.inputQuery.defaultModel = undefined;
278
284
  mocks.inputQuery.fallbackPreferredModel = undefined;
@@ -294,6 +300,30 @@ describe("SessionConversationArea input boundary", () => {
294
300
  expect(params.agent.isSending).toBe(false);
295
301
  });
296
302
 
303
+ it("disables message recovery actions until the NCP agent is ready", () => {
304
+ mocks.agent.isRunning = false;
305
+ mocks.agent.isSending = false;
306
+ mocks.controller.isSending = false;
307
+ mocks.runtimeBlocked = true;
308
+
309
+ const rendered = renderArea("session-1");
310
+
311
+ expect(
312
+ screen.getByTestId("conversation-content").dataset.messageActionsDisabled,
313
+ ).toBe("true");
314
+
315
+ mocks.runtimeBlocked = false;
316
+ rendered.rerender(
317
+ <MemoryRouter>
318
+ <SessionConversationArea sessionKey="session-1" />
319
+ </MemoryRouter>,
320
+ );
321
+
322
+ expect(
323
+ screen.getByTestId("conversation-content").dataset.messageActionsDisabled,
324
+ ).toBe("false");
325
+ });
326
+
297
327
  it("keeps the composer input subtree stable when only streamed messages change", () => {
298
328
  const rendered = renderArea("session-1");
299
329
 
@@ -380,6 +410,53 @@ describe("SessionConversationArea input boundary", () => {
380
410
  );
381
411
  });
382
412
 
413
+ it("consumes a system object draft intent as a visible composer token", () => {
414
+ const reference = {
415
+ uri: "nextclaw://objects/inbox-delivery/delivery-1",
416
+ objectType: "inbox-delivery",
417
+ objectId: "delivery-1",
418
+ label: "OOM investigation report",
419
+ description: "Root cause and mitigation",
420
+ updatedAt: "2026-08-11T00:00:00.000Z",
421
+ version: "sha256-report",
422
+ assetUri: "asset://store/report",
423
+ fileName: "oom-investigation-report.md",
424
+ mimeType: "text/markdown",
425
+ sizeBytes: 128,
426
+ };
427
+ mocks.appPresenter.chatDraftIntentManager.consumePending.mockReturnValueOnce({
428
+ id: 1,
429
+ kind: "system-object-reference",
430
+ reference,
431
+ });
432
+
433
+ render(
434
+ <MemoryRouter>
435
+ <SessionConversationArea
436
+ consumeDraftIntent
437
+ sessionKey={null}
438
+ />
439
+ </MemoryRouter>,
440
+ );
441
+
442
+ expect(mocks.presenter.chatSessionListManager.createSession).toHaveBeenCalledOnce();
443
+ expect(mocks.appPresenter.chatDraftIntentManager.markConsumed).toHaveBeenCalledWith(1);
444
+ const update = mocks.inputActions.update.mock.calls.at(-1)?.[0] as (
445
+ current: { nodes: []; text: string },
446
+ ) => { nodes: Array<Record<string, unknown>>; text: string };
447
+ const next = update({ nodes: [], text: "" });
448
+ expect(next.nodes).toEqual([
449
+ expect.objectContaining({
450
+ type: "token",
451
+ tokenKind: "system_object",
452
+ tokenKey: reference.uri,
453
+ label: reference.label,
454
+ data: { reference },
455
+ }),
456
+ ]);
457
+ expect(next.text).toBe("");
458
+ });
459
+
383
460
  it("syncs draft preferences with the selected runtime context", () => {
384
461
  mocks.inputQuery.defaultModel = "openai/gpt-5";
385
462
  mocks.inputQuery.fallbackPreferredModel = "minimax/MiniMax-M3";
@@ -349,7 +349,7 @@ describe('SessionConversationInput streaming stability', () => {
349
349
 
350
350
  it('inserts a project file reference at the saved composer caret', async () => {
351
351
  const controlRef: MutableRefObject<StreamingInputControl | null> = { current: null };
352
- render(
352
+ renderInput(
353
353
  <StreamingSessionConversationInputHarness
354
354
  controlRef={controlRef}
355
355
  initialText="Hello"
@@ -431,7 +431,7 @@ describe('SessionConversationInput streaming stability', () => {
431
431
  const controlRef: MutableRefObject<StreamingInputControl | null> = { current: null };
432
432
  const providerError = 'Chat Completions API failed (402): raw provider error';
433
433
 
434
- render(
434
+ renderInput(
435
435
  <StreamingSessionConversationInputHarness
436
436
  controlRef={controlRef}
437
437
  sendError={providerError}
@@ -546,7 +546,7 @@ describe('SessionConversationInput attachment submit', () => {
546
546
  it('preserves a project file reference in the outgoing user message and AI context', async () => {
547
547
  const send = vi.fn<AttachmentSubmitAgentSend>(async () => createAttachmentRunHandle());
548
548
 
549
- render(<AttachmentSubmitHarness initialPrompt="这里面有啥" send={send} />);
549
+ renderInput(<AttachmentSubmitHarness initialPrompt="这里面有啥" send={send} />);
550
550
 
551
551
  const textbox = screen.getByRole('textbox');
552
552
  fireEvent.focus(textbox);
@@ -605,7 +605,7 @@ describe('SessionConversationInput attachment submit', () => {
605
605
 
606
606
  it('preserves an exact workspace excerpt in the outgoing message metadata', async () => {
607
607
  const send = vi.fn<AttachmentSubmitAgentSend>(async () => createAttachmentRunHandle());
608
- render(<AttachmentSubmitHarness initialPrompt="解释一下" send={send} />);
608
+ renderInput(<AttachmentSubmitHarness initialPrompt="解释一下" send={send} />);
609
609
 
610
610
  const textbox = screen.getByRole('textbox');
611
611
  await waitFor(() => expect(textbox.textContent).toBe('解释一下'));
@@ -18,6 +18,10 @@ import { ChatConversationWelcome } from "@/features/chat/features/welcome/compon
18
18
  import { useChatSessionListStore } from "@/features/chat/stores/chat-session-list.store";
19
19
  import { useSystemStatus } from "@/features/system-status";
20
20
  import { t } from "@/shared/lib/i18n";
21
+ import type { SystemObjectResolvedReference } from "@nextclaw/shared";
22
+ import { deriveChatComposerDraft } from "@/features/chat/features/input/utils/chat-composer-state.utils";
23
+ import { appendSystemObjectReferenceToken } from "@/features/chat/features/input/utils/chat-system-object-reference.utils";
24
+ import type { ChatDraftIntent } from "@/features/chat/managers/chat-draft-intent.manager";
21
25
 
22
26
  import {
23
27
  useSessionConversationController,
@@ -42,18 +46,23 @@ type SessionConversationAreaProps = {
42
46
  function useSessionConversationDraftIntent(params: {
43
47
  readonly consumeDraftIntent: boolean;
44
48
  readonly applyPromptSuggestion: (prompt: string) => void;
49
+ readonly applySystemObjectReference: (reference: SystemObjectResolvedReference) => void;
45
50
  }) {
46
- const { applyPromptSuggestion, consumeDraftIntent } = params;
51
+ const { applyPromptSuggestion, applySystemObjectReference, consumeDraftIntent } = params;
47
52
  const appPresenter = useAppPresenter();
48
53
  const presenter = usePresenter();
49
54
  useEffect(() => {
50
55
  if (!consumeDraftIntent) {
51
56
  return undefined;
52
57
  }
53
- const applyIntent = (intent: { id: number; prompt: string }) => {
58
+ const applyIntent = (intent: ChatDraftIntent) => {
54
59
  presenter.chatSessionListManager.createSession();
55
60
  presenter.chatSessionListManager.setSelectedAgentId("main");
56
- applyPromptSuggestion(intent.prompt);
61
+ if (intent.kind === 'prompt') {
62
+ applyPromptSuggestion(intent.prompt);
63
+ } else {
64
+ applySystemObjectReference(intent.reference);
65
+ }
57
66
  appPresenter.chatDraftIntentManager.markConsumed(intent.id);
58
67
  };
59
68
  const unsubscribe =
@@ -63,7 +72,7 @@ function useSessionConversationDraftIntent(params: {
63
72
  applyIntent(pendingIntent);
64
73
  }
65
74
  return unsubscribe;
66
- }, [appPresenter, applyPromptSuggestion, consumeDraftIntent, presenter]);
75
+ }, [appPresenter, applyPromptSuggestion, applySystemObjectReference, consumeDraftIntent, presenter]);
67
76
  }
68
77
 
69
78
  type ChatDraftRouteState = {
@@ -204,6 +213,17 @@ export function SessionConversationArea(props: SessionConversationAreaProps) {
204
213
  initialPrompt,
205
214
  sessionKey,
206
215
  );
216
+ const applySystemObjectReference = useCallback((reference: SystemObjectResolvedReference) => {
217
+ inputActions.update((current) => {
218
+ const nodes = appendSystemObjectReferenceToken(current.nodes, reference);
219
+ return {
220
+ nodes,
221
+ text: deriveChatComposerDraft(nodes),
222
+ composerFocusRequestId: Date.now(),
223
+ sendError: null,
224
+ };
225
+ });
226
+ }, [inputActions]);
207
227
  const inputQuery = useSessionConversationInputQuery({
208
228
  sessionKey,
209
229
  inputSnapshot,
@@ -355,6 +375,7 @@ export function SessionConversationArea(props: SessionConversationAreaProps) {
355
375
  useSessionConversationDraftIntent({
356
376
  consumeDraftIntent,
357
377
  applyPromptSuggestion: inputActions.applyPromptSuggestion,
378
+ applySystemObjectReference,
358
379
  });
359
380
  const renderInput = useCallback(
360
381
  (surface: "default" | "embedded", placeholder?: string) => (
@@ -395,7 +416,7 @@ export function SessionConversationArea(props: SessionConversationAreaProps) {
395
416
  isLoadingPreviousMessages={agent.isLoadingPreviousMessages}
396
417
  isSending={controller.isSending}
397
418
  canContinue={controller.canContinue}
398
- messageActionsDisabled={controller.isSending}
419
+ messageActionsDisabled={controller.isSending || isRuntimeBlocked}
399
420
  isContextCompacting={Boolean(
400
421
  sessionKey && compactingSessionIds.has(sessionKey),
401
422
  )}
@@ -47,6 +47,7 @@ import { useSessionConversationInputAttachments } from '@/features/chat/features
47
47
  import { useChatComposerReferenceIntent } from '@/features/chat/features/conversation/hooks/use-chat-composer-reference-intent';
48
48
  import { useSessionConversationComposerNodes } from '@/features/chat/features/conversation/hooks/use-session-conversation-composer-nodes';
49
49
  import { useSessionConversationSlashCommands } from '@/features/chat/features/conversation/hooks/use-session-conversation-slash-commands';
50
+ import { useSystemObjectReferenceSelect } from '@/features/chat/features/conversation/hooks/use-system-object-reference-select';
50
51
  import { ChatConversationTrack } from '@/features/chat/components/conversation/chat-conversation-track';
51
52
  import { useChatMessageLayoutStore } from '@/features/chat/stores/chat-message-layout.store';
52
53
  import type { useSessionConversationInputQuery } from '@/features/chat/features/conversation/hooks/use-session-conversation-input-query';
@@ -231,6 +232,7 @@ export const SessionConversationInput = memo(function SessionConversationInput(p
231
232
  const contextReferenceProjectRoot = inputQuery.selectedSessionKey
232
233
  ? inputQuery.selectedSession?.projectRoot ?? inputQuery.defaultProjectRoot ?? ''
233
234
  : inputSnapshot.pendingProjectRoot ?? inputQuery.defaultProjectRoot ?? '';
235
+ const handleSystemObjectSelect = useSystemObjectReferenceSelect(inputBarRef);
234
236
  const { inputSurfaceState, setInputSurfaceTrigger } = useChatInputSurfaceState({
235
237
  commands: slashCommands,
236
238
  isSkillsLoading: inputQuery.isSkillsLoading,
@@ -240,6 +242,7 @@ export const SessionConversationInput = memo(function SessionConversationInput(p
240
242
  language,
241
243
  onSelectPanelApp: handleSlashPanelAppSelect,
242
244
  onSelectSkill: chatRecentSkillsManager.remember,
245
+ onSelectSystemObject: handleSystemObjectSelect,
243
246
  projectRoot: contextReferenceProjectRoot,
244
247
  recentSkillValues,
245
248
  skillRecords,
@@ -0,0 +1,27 @@
1
+ import { useCallback, type RefObject } from 'react';
2
+ import type { ChatInputBarHandle } from '@nextclaw/agent-chat-ui';
3
+ import { CHAT_SYSTEM_OBJECT_TOKEN_KIND } from '@nextclaw/shared';
4
+ import { toast } from 'sonner';
5
+
6
+ import { nextclawClient } from '@/shared/lib/api';
7
+ import { t } from '@/shared/lib/i18n';
8
+
9
+ export function useSystemObjectReferenceSelect(
10
+ inputBarRef: RefObject<ChatInputBarHandle | null>,
11
+ ) {
12
+ return useCallback((uri: string) => {
13
+ void nextclawClient.systemObjectReferences.resolve(uri)
14
+ .then((reference) => {
15
+ inputBarRef.current?.insertInputSurfaceToken({
16
+ tokenKind: CHAT_SYSTEM_OBJECT_TOKEN_KIND,
17
+ tokenKey: reference.uri,
18
+ label: reference.label,
19
+ data: { reference },
20
+ });
21
+ })
22
+ .catch((error: unknown) => {
23
+ const message = error instanceof Error ? error.message : t('error');
24
+ toast.error(`${t('chatSystemObjectResolveFailed')}: ${message}`);
25
+ });
26
+ }, [inputBarRef]);
27
+ }
@@ -6,6 +6,7 @@ import {
6
6
  } from '@nextclaw/agent-chat-ui';
7
7
  import type { NcpMessage } from '@nextclaw/ncp';
8
8
  import type { NcpDraftAttachment } from '@nextclaw/ncp-react';
9
+ import { CHAT_SYSTEM_OBJECT_TOKEN_KIND } from '@nextclaw/shared';
9
10
 
10
11
  import { deriveChatComposerDraft } from '@/features/chat/features/input/utils/chat-composer-state.utils';
11
12
  import {
@@ -44,6 +45,10 @@ function buildTextNodes(
44
45
  tokenKind: nextToken.token.kind,
45
46
  tokenKey: 'ref' in nextToken.token ? nextToken.token.ref : nextToken.token.key,
46
47
  label: nextToken.token.label,
48
+ data: nextToken.token.kind === CHAT_SYSTEM_OBJECT_TOKEN_KIND &&
49
+ 'reference' in nextToken.token
50
+ ? { reference: nextToken.token.reference }
51
+ : undefined,
47
52
  }));
48
53
  offset = nextToken.index + nextToken.token.rawText.length;
49
54
  }
@@ -42,6 +42,14 @@ const useServerPathBrowseMock = vi.hoisted(() =>
42
42
  isLoading: false,
43
43
  })),
44
44
  );
45
+ const useSystemObjectReferencesMock = vi.hoisted(() =>
46
+ vi.fn(() => ({
47
+ data: { groups: [], total: 0 },
48
+ error: null,
49
+ isFetching: false,
50
+ isLoading: false,
51
+ })),
52
+ );
45
53
 
46
54
  vi.mock('@/features/panel-apps', () => ({
47
55
  usePanelApps: usePanelAppsMock,
@@ -55,6 +63,9 @@ vi.mock('@/shared/hooks/use-server-path-search', () => ({
55
63
  vi.mock('@/shared/hooks/use-server-path-browse', () => ({
56
64
  useServerPathBrowse: useServerPathBrowseMock,
57
65
  }));
66
+ vi.mock('@/shared/hooks/use-system-object-references', () => ({
67
+ useSystemObjectReferences: useSystemObjectReferencesMock,
68
+ }));
58
69
 
59
70
  function createHookParams() {
60
71
  return {
@@ -71,6 +82,7 @@ function createHookParams() {
71
82
  language: 'zh' as const,
72
83
  onSelectPanelApp: vi.fn(),
73
84
  onSelectSkill: vi.fn(),
85
+ onSelectSystemObject: vi.fn(),
74
86
  projectRoot: '/tmp/project',
75
87
  recentSkillValues: [],
76
88
  skillRecords: [],
@@ -82,6 +94,62 @@ beforeEach(() => {
82
94
  useProjectsMock.mockClear();
83
95
  useServerPathBrowseMock.mockClear();
84
96
  useServerPathSearchMock.mockClear();
97
+ useSystemObjectReferencesMock.mockReset();
98
+ useSystemObjectReferencesMock.mockReturnValue({
99
+ data: { groups: [], total: 0 },
100
+ error: null,
101
+ isFetching: false,
102
+ isLoading: false,
103
+ } as never);
104
+ });
105
+
106
+ it('loads the catalog at root and scopes queries after entering a system object group', () => {
107
+ useSystemObjectReferencesMock.mockReturnValue({
108
+ data: {
109
+ groups: [{
110
+ objectType: 'cron-job',
111
+ label: { default: 'Scheduled Tasks', translations: { zh: '定时任务' } },
112
+ description: { default: 'Browse tasks', translations: { zh: '浏览定时任务' } },
113
+ icon: 'calendar-clock',
114
+ order: 200,
115
+ items: [],
116
+ total: 1,
117
+ }],
118
+ total: 1,
119
+ },
120
+ error: null,
121
+ isFetching: false,
122
+ isLoading: false,
123
+ } as never);
124
+ const { result } = renderHook(() => useChatInputSurfaceState(createHookParams()));
125
+
126
+ act(() => result.current.setInputSurfaceTrigger({
127
+ end: 1,
128
+ key: 'context-reference',
129
+ marker: '@',
130
+ query: '',
131
+ start: 0,
132
+ }));
133
+ expect(useSystemObjectReferencesMock).toHaveBeenLastCalledWith({
134
+ enabled: true,
135
+ query: '',
136
+ limit: 6,
137
+ objectType: undefined,
138
+ });
139
+ const groupItem = result.current.inputSurfaceState.panel?.items.find(
140
+ (item) => item.title === '定时任务',
141
+ );
142
+ act(() => result.current.inputSurfaceState.panel?.onSelectItem?.(groupItem!));
143
+
144
+ expect(useSystemObjectReferencesMock).toHaveBeenLastCalledWith({
145
+ enabled: true,
146
+ query: '',
147
+ limit: 20,
148
+ objectType: 'cron-job',
149
+ });
150
+ expect(useServerPathSearchMock).toHaveBeenLastCalledWith(expect.objectContaining({
151
+ enabled: false,
152
+ }));
85
153
  });
86
154
 
87
155
  it('browses nested folders while reserving search for project-wide queries', () => {
@@ -133,6 +201,40 @@ it('browses nested folders while reserving search for project-wide queries', ()
133
201
  });
134
202
  });
135
203
 
204
+ it('uses a folder-only browser and exposes the current folder as the selection', () => {
205
+ const { result } = renderHook(() => useChatInputSurfaceState(createHookParams()));
206
+
207
+ act(() => result.current.setInputSurfaceTrigger({
208
+ end: 1,
209
+ key: 'context-reference',
210
+ marker: '@',
211
+ query: '',
212
+ start: 0,
213
+ }));
214
+ const foldersItem = result.current.inputSurfaceState.panel?.items.find(
215
+ (item) => item.title === '文件夹',
216
+ );
217
+ act(() => result.current.inputSurfaceState.panel?.onSelectItem?.(foldersItem!));
218
+
219
+ expect(useServerPathBrowseMock).toHaveBeenLastCalledWith({
220
+ path: '.',
221
+ basePath: '/tmp/project',
222
+ includeFiles: false,
223
+ enabled: true,
224
+ });
225
+ expect(result.current.inputSurfaceState.panel?.items).toEqual(expect.arrayContaining([
226
+ expect.objectContaining({
227
+ title: '引用当前文件夹',
228
+ tokenKind: 'workspace_directory',
229
+ tokenKey: '.',
230
+ }),
231
+ expect.objectContaining({
232
+ title: 'src',
233
+ selectionBehavior: 'navigate',
234
+ }),
235
+ ]));
236
+ });
237
+
136
238
  it('keeps equivalent input surface trigger updates from rerendering the composer owner', () => {
137
239
  let renderCount = 0;
138
240
  const trigger = {