@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,20 @@
1
- import { Fragment, useState } from "react";
2
- import type { ChatFileOpenActionViewModel } from "@nextclaw/agent-chat-ui";
3
- import { ChevronRight, Folder, FolderTree } from "lucide-react";
4
- import { Popover, PopoverTrigger } from "@/shared/components/ui/popover";
5
- import { FileTypeIcon } from "@/shared/components/file-type-icon";
6
- import { ChatPopoverContent } from "@/features/chat/components/chat-popover-content";
7
- import { WorkspaceBreadcrumbBrowser } from "./chat-session-workspace-file-breadcrumb-browser";
1
+ import { Fragment, useLayoutEffect, useRef, useState, type ReactNode } from 'react';
2
+ import type { ChatFileOpenActionViewModel } from '@nextclaw/agent-chat-ui';
3
+ import { ChevronRight, Folder, FolderTree } from 'lucide-react';
4
+ import { Popover, PopoverTrigger } from '@/shared/components/ui/popover';
5
+ import { FileTypeIcon } from '@/shared/components/file-type-icon';
6
+ import { ChatPopoverContent } from '@/features/chat/components/chat-popover-content';
7
+ import { WorkspaceBreadcrumbBrowser } from './chat-session-workspace-file-breadcrumb-browser';
8
8
  import type {
9
9
  WorkspaceFileBreadcrumbSegmentViewModel,
10
10
  WorkspaceFileBreadcrumbViewModel,
11
- } from "@/shared/lib/session-project";
12
- import { t } from "@/shared/lib/i18n";
13
- import { cn } from "@/shared/lib/utils";
11
+ } from '@/shared/lib/session-project';
12
+ import { t } from '@/shared/lib/i18n';
13
+ import { cn } from '@/shared/lib/utils';
14
14
 
15
15
  function WorkspaceBreadcrumbWarningChip({ value }: { value: string }) {
16
16
  return (
17
- <span
18
- className="inline-flex h-5 items-center rounded-sm border border-amber-200 bg-amber-50 px-1.5 text-[10px] font-medium leading-none text-amber-700"
19
- >
17
+ <span className="inline-flex h-5 items-center rounded-sm border border-amber-200 bg-amber-50 px-1.5 text-[10px] font-medium leading-none text-amber-700">
20
18
  {value}
21
19
  </span>
22
20
  );
@@ -43,20 +41,20 @@ function WorkspaceBreadcrumbSegmentButton({
43
41
  <PopoverTrigger asChild>
44
42
  <button
45
43
  type="button"
46
- aria-current={segment.isCurrent ? "page" : undefined}
44
+ aria-current={segment.isCurrent ? 'page' : undefined}
47
45
  className={cn(
48
- "inline-flex h-5 items-center gap-1 rounded-sm px-1 text-[11px] leading-none transition-colors hover:bg-gray-200/80 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border",
49
- segment.kind === "workspace"
50
- ? "bg-primary/8 text-primary hover:bg-primary/12"
46
+ 'inline-flex h-5 shrink-0 items-center gap-1 whitespace-nowrap rounded-sm px-1 text-[11px] leading-none transition-colors hover:bg-gray-200/80 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border',
47
+ segment.kind === 'workspace'
48
+ ? 'bg-primary/8 text-primary hover:bg-primary/12'
51
49
  : segment.isCurrent
52
- ? "bg-gray-200/70 text-gray-900"
53
- : "text-gray-500",
50
+ ? 'bg-gray-200/70 text-gray-900'
51
+ : 'text-gray-500',
54
52
  )}
55
53
  disabled={!segment.browsePath}
56
54
  >
57
- {segment.kind === "workspace" ? (
55
+ {segment.kind === 'workspace' ? (
58
56
  <FolderTree className="h-3 w-3 shrink-0" />
59
- ) : segment.kind === "directory" && segment.isCurrent ? (
57
+ ) : segment.kind === 'directory' && segment.isCurrent ? (
60
58
  <Folder className="h-3 w-3 shrink-0" />
61
59
  ) : segment.isCurrent ? (
62
60
  <FileTypeIcon fileName={segment.label} size="compact" />
@@ -64,11 +62,7 @@ function WorkspaceBreadcrumbSegmentButton({
64
62
  <span>{segment.label}</span>
65
63
  </button>
66
64
  </PopoverTrigger>
67
- <ChatPopoverContent
68
- data-testid="workspace-breadcrumb-popover"
69
- className="w-[22rem] rounded-md p-0"
70
- align="start"
71
- >
65
+ <ChatPopoverContent data-testid="workspace-breadcrumb-popover" className="w-[22rem] rounded-md p-0" align="start">
72
66
  <WorkspaceBreadcrumbBrowser
73
67
  browsePath={browsePath}
74
68
  onBrowsePathChange={setBrowsePath}
@@ -82,28 +76,55 @@ function WorkspaceBreadcrumbSegmentButton({
82
76
 
83
77
  export function ChatSessionWorkspaceFileBreadcrumbs({
84
78
  breadcrumb,
79
+ leading,
85
80
  onFileOpen,
86
81
  }: {
87
82
  breadcrumb: WorkspaceFileBreadcrumbViewModel;
83
+ leading?: ReactNode;
88
84
  onFileOpen: (action: ChatFileOpenActionViewModel) => void;
89
85
  }) {
86
+ const scrollRef = useRef<HTMLDivElement>(null);
87
+
88
+ useLayoutEffect(() => {
89
+ const scroll = scrollRef.current;
90
+ if (!scroll) return;
91
+ const current = scroll.querySelector<HTMLElement>('[aria-current="page"]');
92
+ if (!current) return;
93
+
94
+ const revealCurrentSegment = () => {
95
+ const scrollRect = scroll.getBoundingClientRect();
96
+ const currentRect = current.getBoundingClientRect();
97
+ if (currentRect.right > scrollRect.right) {
98
+ scroll.scrollLeft += currentRect.right - scrollRect.right;
99
+ } else if (currentRect.left < scrollRect.left) {
100
+ scroll.scrollLeft -= scrollRect.left - currentRect.left;
101
+ }
102
+ };
103
+
104
+ revealCurrentSegment();
105
+ if (typeof ResizeObserver === 'undefined') return;
106
+ const observer = new ResizeObserver(revealCurrentSegment);
107
+ observer.observe(scroll);
108
+ observer.observe(current);
109
+ return () => observer.disconnect();
110
+ }, [breadcrumb.fullPath]);
111
+
90
112
  return (
91
113
  <div
92
114
  data-testid="workspace-file-breadcrumbs"
93
115
  title={breadcrumb.fullPath}
94
- className="workspace-horizontal-scrollbar overflow-x-auto overflow-y-hidden border-b border-gray-200/80 bg-gray-50/55"
116
+ className="flex min-w-0 items-center border-b border-gray-200/80 bg-gray-50/55"
95
117
  >
118
+ {leading ? <div className="flex h-full shrink-0 items-center pl-1 pr-0.5">{leading}</div> : null}
96
119
  <div
120
+ ref={scrollRef}
97
121
  data-testid="workspace-file-breadcrumb-scroll"
98
- className="flex min-w-max items-center gap-2.5 px-3 py-1.5"
122
+ className="workspace-horizontal-scrollbar flex min-w-0 flex-1 items-center gap-2.5 overflow-x-auto overflow-y-hidden px-3 py-1.5"
99
123
  >
100
124
  <div className="flex min-w-0 flex-1 items-center gap-1 pr-1">
101
125
  {breadcrumb.segments.map((segment, index) => (
102
126
  <Fragment key={segment.key}>
103
- <WorkspaceBreadcrumbSegmentButton
104
- segment={segment}
105
- onFileOpen={onFileOpen}
106
- />
127
+ <WorkspaceBreadcrumbSegmentButton segment={segment} onFileOpen={onFileOpen} />
107
128
  {index < breadcrumb.segments.length - 1 ? (
108
129
  <ChevronRight className="h-3 w-3 shrink-0 text-gray-300" />
109
130
  ) : null}
@@ -113,9 +134,7 @@ export function ChatSessionWorkspaceFileBreadcrumbs({
113
134
 
114
135
  {breadcrumb.truncated ? (
115
136
  <div className="flex shrink-0 flex-wrap items-center justify-end gap-1">
116
- <WorkspaceBreadcrumbWarningChip
117
- value={t("chatWorkspacePreviewTruncated")}
118
- />
137
+ <WorkspaceBreadcrumbWarningChip value={t('chatWorkspacePreviewTruncated')} />
119
138
  </div>
120
139
  ) : null}
121
140
  </div>
@@ -1,56 +1,44 @@
1
- import { useMemo } from "react";
2
- import type {
3
- ChatFileOpenActionViewModel,
4
- ChatFileOperationBlockViewModel,
5
- } from "@nextclaw/agent-chat-ui";
6
- import { NextClawClientError } from "@nextclaw/client-sdk";
7
- import {
8
- ChatMessageMarkdown,
9
- FileOperationCodeSurface,
10
- } from "@nextclaw/agent-chat-ui";
11
- import type { ChatWorkspaceFileTab } from "@/features/chat/stores/chat-thread.store";
12
- import { ChatSessionWorkspaceDirectoryBrowser } from "./chat-session-workspace-directory-browser";
13
- import { ChatSessionWorkspaceFileBreadcrumbs } from "./chat-session-workspace-file-breadcrumbs";
14
- import { WorkspaceTextSelectionMenu } from "./workspace-text-selection-menu";
15
- import type { WorkspaceTextExcerpt } from "@/features/chat/features/workspace/utils/workspace-text-excerpt.utils";
1
+ import { useMemo, type ReactNode } from 'react';
2
+ import type { ChatFileOpenActionViewModel, ChatFileOperationBlockViewModel } from '@nextclaw/agent-chat-ui';
3
+ import { NextClawClientError } from '@nextclaw/client-sdk';
4
+ import { ChatMessageMarkdown, FileOperationCodeSurface } from '@nextclaw/agent-chat-ui';
5
+ import type { ChatWorkspaceFileTab } from '@/features/chat/stores/chat-thread.store';
6
+ import { ChatSessionWorkspaceDirectoryBrowser } from './chat-session-workspace-directory-browser';
7
+ import { ChatSessionWorkspaceFileBreadcrumbs } from './chat-session-workspace-file-breadcrumbs';
8
+ import { WorkspaceTextSelectionMenu } from './workspace-text-selection-menu';
9
+ import type { WorkspaceTextExcerpt } from '@/features/chat/features/workspace/utils/workspace-text-excerpt.utils';
16
10
  import {
17
11
  resolveWorkspaceFileContentKind,
18
12
  WorkspaceFileContentPreview,
19
13
  type WorkspaceFileContentKind,
20
- } from "./workspace-file-content-preview";
21
- import { useServerPathBrowse } from "@/shared/hooks/use-server-path-browse";
22
- import { useServerPathRead } from "@/shared/hooks/use-server-path-read";
23
- import { buildServerPathContentUrl } from "@/shared/lib/api";
14
+ } from './workspace-file-content-preview';
15
+ import { useServerPathBrowse } from '@/shared/hooks/use-server-path-browse';
16
+ import { useServerPathRead } from '@/shared/hooks/use-server-path-read';
17
+ import { buildServerPathContentUrl } from '@/shared/lib/api';
24
18
  import {
25
19
  buildLineDiff,
26
20
  buildPreviewLines,
27
- } from "@/features/chat/features/message/utils/file-operation/line-builder.utils";
28
- import { t } from "@/shared/lib/i18n";
29
- import {
30
- buildWorkspaceFileBreadcrumb,
31
- resolveWorkspaceRelativePath,
32
- } from "@/shared/lib/session-project";
33
- import { cn } from "@/shared/lib/utils";
34
- import { resolveWorkspaceFileViewer } from "@/features/chat/features/workspace/utils/chat-workspace-file-viewer.utils";
21
+ } from '@/features/chat/features/message/utils/file-operation/line-builder.utils';
22
+ import { t } from '@/shared/lib/i18n';
23
+ import { buildWorkspaceFileBreadcrumb, resolveWorkspaceRelativePath } from '@/shared/lib/session-project';
24
+ import { cn } from '@/shared/lib/utils';
25
+ import { resolveWorkspaceFileViewer } from '@/features/chat/features/workspace/utils/chat-workspace-file-viewer.utils';
35
26
 
36
27
  function inferPreviewKind(params: {
37
28
  path: string;
38
- serverKind?: "text" | "markdown" | "binary";
39
- }): "text" | "markdown" | "binary" {
29
+ serverKind?: 'text' | 'markdown' | 'binary';
30
+ }): 'text' | 'markdown' | 'binary' {
40
31
  if (params.serverKind) {
41
32
  return params.serverKind;
42
33
  }
43
- return /\.mdx?$/i.test(params.path) ? "markdown" : "text";
34
+ return /\.mdx?$/i.test(params.path) ? 'markdown' : 'text';
44
35
  }
45
36
 
46
- function appendPreviewRefreshVersion(
47
- url: string,
48
- refreshVersion: number,
49
- ): string {
37
+ function appendPreviewRefreshVersion(url: string, refreshVersion: number): string {
50
38
  if (refreshVersion <= 0) {
51
39
  return url;
52
40
  }
53
- return `${url}${url.includes("?") ? "&" : "?"}refresh=${refreshVersion}`;
41
+ return `${url}${url.includes('?') ? '&' : '?'}refresh=${refreshVersion}`;
54
42
  }
55
43
 
56
44
  function buildPreviewBlock(params: {
@@ -64,10 +52,10 @@ function buildPreviewBlock(params: {
64
52
  return {
65
53
  key: `preview:${path}`,
66
54
  path,
67
- display: "preview",
55
+ display: 'preview',
68
56
  lines: buildPreviewLines({
69
57
  text,
70
- kind: "context",
58
+ kind: 'context',
71
59
  oldStartLine: normalizedStartLine,
72
60
  newStartLine: normalizedStartLine,
73
61
  }),
@@ -78,25 +66,19 @@ function buildPreviewBlock(params: {
78
66
  };
79
67
  }
80
68
 
81
- function buildDiffBlock(
82
- file: ChatWorkspaceFileTab,
83
- ): ChatFileOperationBlockViewModel | null {
69
+ function buildDiffBlock(file: ChatWorkspaceFileTab): ChatFileOperationBlockViewModel | null {
84
70
  if (Array.isArray(file.fullLines) && file.fullLines.length > 0) {
85
71
  return {
86
72
  key: `diff:${file.key}`,
87
73
  path: file.path,
88
- display: "diff",
74
+ display: 'diff',
89
75
  lines: file.fullLines,
90
76
  fullLines: file.fullLines,
91
77
  ...(file.beforeText ? { beforeText: file.beforeText } : {}),
92
78
  ...(file.afterText ? { afterText: file.afterText } : {}),
93
79
  ...(file.patchText ? { patchText: file.patchText } : {}),
94
- ...(typeof file.oldStartLine === "number"
95
- ? { oldStartLine: file.oldStartLine }
96
- : {}),
97
- ...(typeof file.newStartLine === "number"
98
- ? { newStartLine: file.newStartLine }
99
- : {}),
80
+ ...(typeof file.oldStartLine === 'number' ? { oldStartLine: file.oldStartLine } : {}),
81
+ ...(typeof file.newStartLine === 'number' ? { newStartLine: file.newStartLine } : {}),
100
82
  };
101
83
  }
102
84
 
@@ -105,8 +87,8 @@ function buildDiffBlock(
105
87
  }
106
88
 
107
89
  const lines = buildLineDiff({
108
- beforeText: file.beforeText ?? "",
109
- afterText: file.afterText ?? "",
90
+ beforeText: file.beforeText ?? '',
91
+ afterText: file.afterText ?? '',
110
92
  oldStartLine: file.oldStartLine ?? undefined,
111
93
  newStartLine: file.newStartLine ?? undefined,
112
94
  });
@@ -114,32 +96,22 @@ function buildDiffBlock(
114
96
  return {
115
97
  key: `diff:${file.key}`,
116
98
  path: file.path,
117
- display: "diff",
99
+ display: 'diff',
118
100
  lines,
119
101
  fullLines: lines,
120
102
  ...(file.beforeText ? { beforeText: file.beforeText } : {}),
121
103
  ...(file.afterText ? { afterText: file.afterText } : {}),
122
- ...(typeof file.oldStartLine === "number"
123
- ? { oldStartLine: file.oldStartLine }
124
- : {}),
125
- ...(typeof file.newStartLine === "number"
126
- ? { newStartLine: file.newStartLine }
127
- : {}),
104
+ ...(typeof file.oldStartLine === 'number' ? { oldStartLine: file.oldStartLine } : {}),
105
+ ...(typeof file.newStartLine === 'number' ? { newStartLine: file.newStartLine } : {}),
128
106
  };
129
107
  }
130
108
 
131
- function WorkspaceFilePreviewStatus({
132
- text,
133
- tone = "muted",
134
- }: {
135
- text: string;
136
- tone?: "muted" | "error";
137
- }) {
109
+ function WorkspaceFilePreviewStatus({ text, tone = 'muted' }: { text: string; tone?: 'muted' | 'error' }) {
138
110
  return (
139
111
  <div
140
112
  className={cn(
141
- "flex h-full items-center justify-center px-6 text-center text-sm",
142
- tone === "error" ? "text-rose-600" : "text-gray-500",
113
+ 'flex h-full items-center justify-center px-6 text-center text-sm',
114
+ tone === 'error' ? 'text-rose-600' : 'text-gray-500',
143
115
  )}
144
116
  >
145
117
  {text}
@@ -148,19 +120,14 @@ function WorkspaceFilePreviewStatus({
148
120
  }
149
121
 
150
122
  export function resolveWorkspacePreviewErrorText(error: unknown): string {
151
- return error instanceof NextClawClientError &&
152
- error.code === "SERVER_PATH_NOT_FOUND"
153
- ? t("chatWorkspacePreviewNotFound")
154
- : t("chatWorkspacePreviewFailed");
123
+ return error instanceof NextClawClientError && error.code === 'SERVER_PATH_NOT_FOUND'
124
+ ? t('chatWorkspacePreviewNotFound')
125
+ : t('chatWorkspacePreviewFailed');
155
126
  }
156
127
 
157
- function WorkspaceDiffBody({
158
- diffBlock,
159
- }: {
160
- diffBlock: ChatFileOperationBlockViewModel | null;
161
- }) {
128
+ function WorkspaceDiffBody({ diffBlock }: { diffBlock: ChatFileOperationBlockViewModel | null }) {
162
129
  if (!diffBlock) {
163
- return <WorkspaceFilePreviewStatus text={t("chatWorkspaceDiffEmpty")} />;
130
+ return <WorkspaceFilePreviewStatus text={t('chatWorkspaceDiffEmpty')} />;
164
131
  }
165
132
  return <WorkspaceCodeSurface block={diffBlock} />;
166
133
  }
@@ -176,12 +143,7 @@ function WorkspaceCodeSurface({
176
143
  }) {
177
144
  return (
178
145
  <div className="h-full overflow-auto custom-scrollbar bg-white">
179
- <FileOperationCodeSurface
180
- block={block}
181
- layout="workspace"
182
- targetColumn={targetColumn}
183
- targetLine={targetLine}
184
- />
146
+ <FileOperationCodeSurface block={block} layout="workspace" targetColumn={targetColumn} targetLine={targetLine} />
185
147
  </div>
186
148
  );
187
149
  }
@@ -206,14 +168,14 @@ function WorkspacePreviewBody({
206
168
  contentUrl: string | null;
207
169
  contentUrlKind: WorkspaceFileContentKind | null;
208
170
  contentLabel: string;
209
- contentParams: ChatWorkspaceFileTab["params"];
171
+ contentParams: ChatWorkspaceFileTab['params'];
210
172
  directoryQuery: ReturnType<typeof useServerPathBrowse> | null | undefined;
211
173
  fileBasePath: string | null;
212
174
  onFileOpen: (action: ChatFileOpenActionViewModel) => void;
213
175
  onHtmlContentHeightChange?: (height: number) => void;
214
176
  previewBlock: ChatFileOperationBlockViewModel | null;
215
- previewKind: "text" | "markdown" | "binary";
216
- previewViewer: "source" | "rendered" | null;
177
+ previewKind: 'text' | 'markdown' | 'binary';
178
+ previewViewer: 'source' | 'rendered' | null;
217
179
  previewQuery: ReturnType<typeof useServerPathRead> | null | undefined;
218
180
  previewText: string | null;
219
181
  targetColumn?: number | null;
@@ -242,65 +204,47 @@ function WorkspacePreviewBody({
242
204
  }
243
205
 
244
206
  if (directoryQuery?.isLoading && previewQuery?.error && !previewBlock) {
245
- return (
246
- <WorkspaceFilePreviewStatus text={t("chatWorkspaceLoadingDirectory")} />
247
- );
207
+ return <WorkspaceFilePreviewStatus text={t('chatWorkspaceLoadingDirectory')} />;
248
208
  }
249
209
 
250
210
  if ((directoryQuery?.isLoading || previewQuery?.isLoading) && !previewBlock) {
251
- return (
252
- <WorkspaceFilePreviewStatus text={t("chatWorkspaceLoadingPreview")} />
253
- );
211
+ return <WorkspaceFilePreviewStatus text={t('chatWorkspaceLoadingPreview')} />;
254
212
  }
255
213
 
256
- if (previewQuery?.data?.kind === "binary") {
257
- return (
258
- <WorkspaceFilePreviewStatus text={t("chatWorkspacePreviewUnsupported")} />
259
- );
214
+ if (previewQuery?.data?.kind === 'binary') {
215
+ return <WorkspaceFilePreviewStatus text={t('chatWorkspacePreviewUnsupported')} />;
260
216
  }
261
217
 
262
218
  if (previewQuery?.error && !previewBlock) {
263
- return (
264
- <WorkspaceFilePreviewStatus
265
- tone="error"
266
- text={resolveWorkspacePreviewErrorText(previewQuery.error)}
267
- />
268
- );
219
+ return <WorkspaceFilePreviewStatus tone="error" text={resolveWorkspacePreviewErrorText(previewQuery.error)} />;
269
220
  }
270
221
 
271
- if (previewKind === "markdown" && previewViewer !== "source" && previewText) {
222
+ if (previewKind === 'markdown' && previewViewer !== 'source' && previewText) {
272
223
  return (
273
224
  <div className="h-full overflow-auto custom-scrollbar px-5 py-4">
274
225
  <ChatMessageMarkdown
275
226
  text={previewText}
276
227
  role="assistant"
277
228
  texts={{
278
- copyCodeLabel: t("chatCodeCopy"),
279
- copiedCodeLabel: t("chatCodeCopied"),
229
+ copyCodeLabel: t('chatCodeCopy'),
230
+ copiedCodeLabel: t('chatCodeCopied'),
280
231
  }}
281
232
  onFileOpen={onFileOpen}
282
- resolveFileContentUrl={(action) =>
283
- buildServerPathContentUrl(action.path, fileBasePath)
284
- }
233
+ resolveFileContentUrl={(action) => buildServerPathContentUrl(action.path, fileBasePath)}
285
234
  />
286
235
  </div>
287
236
  );
288
237
  }
289
238
 
290
239
  if (previewBlock) {
291
- return (
292
- <WorkspaceCodeSurface
293
- block={previewBlock}
294
- targetColumn={targetColumn}
295
- targetLine={targetLine}
296
- />
297
- );
240
+ return <WorkspaceCodeSurface block={previewBlock} targetColumn={targetColumn} targetLine={targetLine} />;
298
241
  }
299
242
 
300
- return <WorkspaceFilePreviewStatus text={t("chatWorkspacePreviewEmpty")} />;
243
+ return <WorkspaceFilePreviewStatus text={t('chatWorkspacePreviewEmpty')} />;
301
244
  }
302
245
 
303
246
  type ChatSessionWorkspaceFilePreviewProps = {
247
+ breadcrumbLeading?: ReactNode;
304
248
  file: ChatWorkspaceFileTab;
305
249
  refreshVersion?: number;
306
250
  sessionProjectRoot: string | null;
@@ -312,6 +256,7 @@ type ChatSessionWorkspaceFilePreviewProps = {
312
256
  };
313
257
 
314
258
  export function ChatSessionWorkspaceFilePreview({
259
+ breadcrumbLeading,
315
260
  file,
316
261
  refreshVersion = 0,
317
262
  sessionProjectRoot,
@@ -321,7 +266,7 @@ export function ChatSessionWorkspaceFilePreview({
321
266
  onFileOpen,
322
267
  onTextExcerptAdd,
323
268
  }: ChatSessionWorkspaceFilePreviewProps) {
324
- const isPreviewMode = file.viewMode === "preview";
269
+ const isPreviewMode = file.viewMode === 'preview';
325
270
  const suppliedContentUrl = file.contentUrl?.trim() || null;
326
271
  const usesServerPath = isPreviewMode && !suppliedContentUrl;
327
272
  const previewQuery = useServerPathRead({
@@ -336,13 +281,8 @@ export function ChatSessionWorkspaceFilePreview({
336
281
  includeFiles: true,
337
282
  enabled: usesServerPath,
338
283
  });
339
- const diffBlock = useMemo(
340
- () => (file.viewMode === "diff" ? buildDiffBlock(file) : null),
341
- [file],
342
- );
343
- const previewText = isPreviewMode
344
- ? (previewQuery?.data?.text ?? file.rawText ?? null)
345
- : null;
284
+ const diffBlock = useMemo(() => (file.viewMode === 'diff' ? buildDiffBlock(file) : null), [file]);
285
+ const previewText = isPreviewMode ? (previewQuery?.data?.text ?? file.rawText ?? null) : null;
346
286
  const previewKind = inferPreviewKind({
347
287
  path: previewQuery?.data?.resolvedPath ?? file.path,
348
288
  serverKind: previewQuery?.data?.kind,
@@ -353,37 +293,27 @@ export function ChatSessionWorkspaceFilePreview({
353
293
  mimeType: file.mimeType,
354
294
  })
355
295
  : null;
356
- const resolvedPath =
357
- directoryQuery?.data?.currentPath ??
358
- previewQuery?.data?.resolvedPath ??
359
- file.path;
360
- const previewPathKind = directoryQuery?.data ? "directory" : "file";
361
- const previewViewer = resolveWorkspaceFileViewer(
362
- resolvedPath,
363
- file.previewViewer,
364
- );
296
+ const resolvedPath = directoryQuery?.data?.currentPath ?? previewQuery?.data?.resolvedPath ?? file.path;
297
+ const previewPathKind = directoryQuery?.data ? 'directory' : 'file';
298
+ const previewViewer = resolveWorkspaceFileViewer(resolvedPath, file.previewViewer);
365
299
  const localContentKind = resolveWorkspaceFileContentKind({
366
300
  path: resolvedPath,
367
301
  });
368
- const localContentUrlCandidate = buildServerPathContentUrl(
369
- file.path,
370
- sessionWorkingDir,
371
- );
302
+ const localContentUrlCandidate = buildServerPathContentUrl(file.path, sessionWorkingDir);
372
303
  const shouldRenderLocalContent = Boolean(
373
304
  !suppliedContentUrl &&
374
305
  isPreviewMode &&
375
306
  localContentUrlCandidate &&
376
- file.previewViewer !== "source" &&
377
- localContentKind !== "other" &&
378
- (localContentKind !== "html" || previewViewer === "rendered"),
307
+ file.previewViewer !== 'source' &&
308
+ localContentKind !== 'other' &&
309
+ (localContentKind !== 'html' || previewViewer === 'rendered'),
379
310
  );
380
311
  const localContentUrl =
381
312
  shouldRenderLocalContent && localContentUrlCandidate
382
313
  ? appendPreviewRefreshVersion(localContentUrlCandidate, refreshVersion)
383
314
  : null;
384
315
  const contentUrl = suppliedContentUrl ?? localContentUrl;
385
- const contentUrlKind =
386
- suppliedContentKind ?? (localContentUrl ? localContentKind : null);
316
+ const contentUrlKind = suppliedContentKind ?? (localContentUrl ? localContentKind : null);
387
317
  const previewBlock = useMemo(() => {
388
318
  if (!isPreviewMode || !previewText || contentUrl) {
389
319
  return null;
@@ -403,13 +333,13 @@ export function ChatSessionWorkspaceFilePreview({
403
333
  previewQuery?.data?.startLine,
404
334
  previewText,
405
335
  ]);
406
- const isTextPreviewTruncated =
407
- !contentUrl && Boolean(previewQuery?.data?.truncated);
336
+ const isTextPreviewTruncated = !contentUrl && Boolean(previewQuery?.data?.truncated);
408
337
  const breadcrumbBasePath = sessionProjectRoot ?? sessionWorkingDir;
409
- const excerptPath = resolveWorkspaceRelativePath({
410
- path: resolvedPath,
411
- sessionProjectRoot: breadcrumbBasePath,
412
- });
338
+ const excerptPath =
339
+ resolveWorkspaceRelativePath({
340
+ path: resolvedPath,
341
+ sessionProjectRoot: breadcrumbBasePath,
342
+ }) ?? resolvedPath.trim();
413
343
  const breadcrumb = useMemo(
414
344
  () =>
415
345
  buildWorkspaceFileBreadcrumb({
@@ -445,16 +375,17 @@ export function ChatSessionWorkspaceFilePreview({
445
375
  {showBreadcrumbs ? (
446
376
  <ChatSessionWorkspaceFileBreadcrumbs
447
377
  breadcrumb={breadcrumb}
378
+ leading={breadcrumbLeading}
448
379
  onFileOpen={onFileOpen}
449
380
  />
450
381
  ) : null}
451
382
 
452
383
  <div className="flex-1 min-h-0 overflow-hidden">
453
- {file.viewMode === "diff" ? (
384
+ {file.viewMode === 'diff' ? (
454
385
  <WorkspaceDiffBody diffBlock={diffBlock} />
455
386
  ) : excerptPath && previewText ? (
456
387
  <WorkspaceTextSelectionMenu
457
- fileLabel={file.label?.trim() || excerptPath.split("/").at(-1) || excerptPath}
388
+ fileLabel={file.label?.trim() || excerptPath.split('/').at(-1) || excerptPath}
458
389
  filePath={excerptPath}
459
390
  sourceStartLine={previewQuery?.data?.startLine ?? 1}
460
391
  sourceText={previewText}