@nextclaw/ui 0.15.3 → 0.15.5

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 (314) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/assets/abnfDiagram-VRR7QNED-BYpK0F5F.js +1 -0
  3. package/dist/assets/aiden0z-pptx-renderer.es-D87ywFdC.js +94 -0
  4. package/dist/assets/api-IlX_CbwU.js +13 -0
  5. package/dist/assets/app-presenter-provider-Bbl_MVbg.js +106 -0
  6. package/dist/assets/app-presenter-provider-D3BuuOyZ.css +1 -0
  7. package/dist/assets/appearance-settings-page-80fLa4-9.js +1 -0
  8. package/dist/assets/arc-DFELHWM2.js +1 -0
  9. package/dist/assets/architecture-TIHT7OUA-ClwVFq-K.js +1 -0
  10. package/dist/assets/architectureDiagram-ZJ3FMSHR-CvRhdovL.js +36 -0
  11. package/dist/assets/array-BqYdCIE6.js +1 -0
  12. package/dist/assets/blockDiagram-677ZJIJ3-DVYNkbR_.js +132 -0
  13. package/dist/assets/{book-open-C3mJGwiy.js → book-open-CN7Shpij.js} +1 -1
  14. package/dist/assets/c4Diagram-LMCZKHZV-B1w-iwRe.js +10 -0
  15. package/dist/assets/channel-BEHOSFc5.js +1 -0
  16. package/dist/assets/channels-list-page-R7M6pzp6.js +8 -0
  17. package/dist/assets/chat-page-152YuwfU.js +1 -0
  18. package/dist/assets/chunk-2Q5K7J3B-DrIhesSX.js +1 -0
  19. package/dist/assets/chunk-32BRIVSS-kG3lg0bC.js +1 -0
  20. package/dist/assets/chunk-52WLFC77-BLeB7iGk.js +10 -0
  21. package/dist/assets/chunk-5FCAYU7R-BQga1Rr7.js +1 -0
  22. package/dist/assets/chunk-5HE753X5-DU81hkcF.js +1 -0
  23. package/dist/assets/chunk-5JV3BV7I-C2bAx0m7.js +1 -0
  24. package/dist/assets/chunk-5TONJI2A-BExIIgWY.js +2 -0
  25. package/dist/assets/chunk-5VM5RSS4-C3XB05yh.js +15 -0
  26. package/dist/assets/chunk-7BUUIJ7U-JiyRtrGu.js +1 -0
  27. package/dist/assets/chunk-BIQX33UG-BZRV20pI.js +1 -0
  28. package/dist/assets/chunk-C7G6YPKG-AsyDSQ9j.js +1 -0
  29. package/dist/assets/chunk-CQNSW5MT-iN-fiXVA.js +1 -0
  30. package/dist/assets/chunk-CYSBUYHQ-DhC_TRzI.js +1 -0
  31. package/dist/assets/chunk-DseTPa7n.js +1 -0
  32. package/dist/assets/chunk-EMLP6XTP-QFLK8R6d.js +1 -0
  33. package/dist/assets/chunk-EX3LRPZG-DzUwhkCz.js +231 -0
  34. package/dist/assets/chunk-FWX5IMBZ-DFelpZBy.js +2 -0
  35. package/dist/assets/chunk-HOUHSVGY-BMPwFEwN.js +1 -0
  36. package/dist/assets/chunk-ICXQ74PX-DH8NJMok.js +2 -0
  37. package/dist/assets/chunk-JG7HCLWE-D-95AsO4.js +2 -0
  38. package/dist/assets/chunk-JWPE2WC7-DIaTv8kx.js +1 -0
  39. package/dist/assets/chunk-KEIR6QF5-A3jEqwzn.js +161 -0
  40. package/dist/assets/chunk-MOJQB5TN-BPFLzWgj.js +88 -0
  41. package/dist/assets/chunk-MOZMSUNE-DR_fzxG0.js +1 -0
  42. package/dist/assets/chunk-OGEWGWER-TIcEoPPH.js +1 -0
  43. package/dist/assets/chunk-OSBZ3O6U-BALNvSfG.js +1 -0
  44. package/dist/assets/chunk-PUDLZKDR-I-EXhf_k.js +156 -0
  45. package/dist/assets/chunk-Q4XR5HBZ-uvIGstBS.js +70 -0
  46. package/dist/assets/chunk-QBLGF6JB-r-TjLdxa.js +1 -0
  47. package/dist/assets/chunk-R7FJI6CG-N-1LDgvy.js +1 -0
  48. package/dist/assets/chunk-RYQCIY6F-jxNASx65.js +1 -0
  49. package/dist/assets/chunk-U6XO7XAA-Cphbuc7q.js +2 -0
  50. package/dist/assets/chunk-V7JOEXUC-BLEuBf1s.js +206 -0
  51. package/dist/assets/chunk-VAUOI2AC-Dpcz6BhT.js +1 -0
  52. package/dist/assets/chunk-VR4S4FIN-BAUbR0ke.js +1 -0
  53. package/dist/assets/chunk-WYO6CB5R-Do6SJrnY.js +127 -0
  54. package/dist/assets/chunk-XXDRQBXY-C2QjjwYX.js +1 -0
  55. package/dist/assets/chunk-Y2CYZVJY-BGrd8tLy.js +1 -0
  56. package/dist/assets/chunk-YOTPTUD7-CQqvMTCr.js +1 -0
  57. package/dist/assets/chunk-ZGVPDNZ5-B7kWWaXv.js +62 -0
  58. package/dist/assets/chunk-ZIRB5QZD-DTU0cDNh.js +32 -0
  59. package/dist/assets/classDiagram-OUVF2IWQ-DESMaY3_.js +1 -0
  60. package/dist/assets/classDiagram-v2-EOCWNBFH-DwOlByYH.js +1 -0
  61. package/dist/assets/config-split-page-BlfvfmTm.js +1 -0
  62. package/dist/assets/confirm-dialog-Dt8Kdbgp.js +5 -0
  63. package/dist/assets/cose-bilkent-JH36ORCC-B9LrtV-q.js +1 -0
  64. package/dist/assets/cynefin-VYW2F7L2-CzjeeOq9.js +1 -0
  65. package/dist/assets/cynefinDiagram-TSTJHNR4-BfjvW4su.js +62 -0
  66. package/dist/assets/cytoscape.esm-CRW8q92n.js +321 -0
  67. package/dist/assets/dagre-DkiXZKkL.js +1 -0
  68. package/dist/assets/dagre-VKFMJZFB-B1pQKQSY.js +4 -0
  69. package/dist/assets/defaultLocale-Cdv9x6q7.js +1 -0
  70. package/dist/assets/desktop-update-config-DreMJu9z.js +1 -0
  71. package/dist/assets/diagram-FQU43EPY-cB4EZdaP.js +3 -0
  72. package/dist/assets/diagram-G47NLZAW-CtW8im1B.js +24 -0
  73. package/dist/assets/diagram-NH7WQ7WH-BDCtrCCm.js +24 -0
  74. package/dist/assets/diagram-OA4YK3LP-DEMJ42Gt.js +30 -0
  75. package/dist/assets/diagram-WEI45ONY-CdCcxSYU.js +41 -0
  76. package/dist/assets/dist-D5ycbwCo.js +41 -0
  77. package/dist/assets/dist-dw-gAfM_.js +1 -0
  78. package/dist/assets/doc-browser-C9u7N9vH.js +1 -0
  79. package/dist/assets/doc-browser-DJQ5XPsi2.js +1 -0
  80. package/dist/assets/doc-browser-context-CCdW9TJf.js +1 -0
  81. package/dist/assets/docx-preview-zis3U0Fa.js +20 -0
  82. package/dist/assets/download-CyPgglKr.js +1 -0
  83. package/dist/assets/ebnfDiagram-CCIWWBDH-DBZETBwE.js +1 -0
  84. package/dist/assets/erDiagram-Q63AITRT-y2zDXprP.js +85 -0
  85. package/dist/assets/eventmodeling-45OFAUF4-C38BqG8w.js +1 -0
  86. package/dist/assets/{external-link-CU0kzzIP.js → external-link-BahW1sl3.js} +1 -1
  87. package/dist/assets/eye-D8gGXMkD.js +1 -0
  88. package/dist/assets/flowDiagram-23GEKE2U-BoKk8RRq.js +1 -0
  89. package/dist/assets/folder-DGWqFDvE.js +1 -0
  90. package/dist/assets/{form-actions-BvCp_0lS.js → form-actions-D2imZLnU.js} +1 -1
  91. package/dist/assets/ganttDiagram-NO4QXBWP-D2DP344e.js +292 -0
  92. package/dist/assets/gitGraph-TEB2WS4Q-IsQHHJuS.js +1 -0
  93. package/dist/assets/gitGraphDiagram-IHSO6WYX-D37uiwA2.js +106 -0
  94. package/dist/assets/graphlib-BcNFQr5y.js +1 -0
  95. package/dist/assets/index-0av6WO9-.css +1 -0
  96. package/dist/assets/index-CT0iYlxV.js +2 -0
  97. package/dist/assets/info-DKCQHKI2-ofy2qlHI.js +1 -0
  98. package/dist/assets/infoDiagram-FWYZ7A6U-CG-WAIRi.js +2 -0
  99. package/dist/assets/init-D8TjIqfm.js +1 -0
  100. package/dist/assets/ishikawaDiagram-FXEZZL3T-WeCTnW0f.js +70 -0
  101. package/dist/assets/journeyDiagram-5HDEW3XC-DUFBW9Td.js +139 -0
  102. package/dist/assets/jszip.min-CP5uPNQa.js +2 -0
  103. package/dist/assets/kanban-definition-HUTT4EX6-B0lxgMpg.js +89 -0
  104. package/dist/assets/katex-wEmrEFTg.js +257 -0
  105. package/dist/assets/line-B78frP_c.js +1 -0
  106. package/dist/assets/linear-C6lVEcb2.js +1 -0
  107. package/dist/assets/loader-circle-DtKek-qG.js +1 -0
  108. package/dist/assets/logo-badge-CuPetu-v.js +1 -0
  109. package/dist/assets/map-Bdri5UL5.js +1 -0
  110. package/dist/assets/mcp-marketplace-page-4qMwFDpz.js +1 -0
  111. package/dist/assets/mcp-marketplace-page-BbxN5aZF.js +9 -0
  112. package/dist/assets/mermaid-parser.core-Cue18vLo.js +4 -0
  113. package/dist/assets/mermaid.core-CXwWRh5i.js +11 -0
  114. package/dist/assets/mindmap-definition-LN4V7U3C-CFxz0P0-.js +96 -0
  115. package/dist/assets/model-config-page-DiJcvBML.js +1 -0
  116. package/dist/assets/ordinal-Cbd8t4LB.js +1 -0
  117. package/dist/assets/packet-7NZHBO7P-Rfopfa1o.js +1 -0
  118. package/dist/assets/path-DzBnMI1r.js +1 -0
  119. package/dist/assets/pegDiagram-2B236MQR-B_Qt9zyT.js +1 -0
  120. package/dist/assets/pie-RZYD4A2V-CJR1xKEv.js +1 -0
  121. package/dist/assets/pieDiagram-ENE6RG2P-CRQdSuwS.js +39 -0
  122. package/dist/assets/plus-BwgE-Zwf.js +1 -0
  123. package/dist/assets/popover-Btp7KVc3.js +1 -0
  124. package/dist/assets/preload-helper-D4M6sveU.js +1 -0
  125. package/dist/assets/provider-models-BoUhFo9R.js +1 -0
  126. package/dist/assets/provider-scoped-model-input-DZMtoAJG.js +1 -0
  127. package/dist/assets/providers-config-page-DfiWveEF.js +1 -0
  128. package/dist/assets/quadrantDiagram-ABIIQ3AL-D5kPpttq.js +7 -0
  129. package/dist/assets/radar-I7S5WNFK-CDg8Z-1r.js +1 -0
  130. package/dist/assets/railroad-3IZDKUUU-BHnNmjxO.js +1 -0
  131. package/dist/assets/railroad-abnf-AHOZXSZD-DGtNcusW.js +1 -0
  132. package/dist/assets/railroad-ebnf-EBAXGLYW-BRFtsQmm.js +1 -0
  133. package/dist/assets/railroad-peg-LSFZ7HO6-Bj5IypCA.js +1 -0
  134. package/dist/assets/railroadDiagram-RFXS5EU6-DGh_TGlQ.js +1 -0
  135. package/dist/assets/react-BY-U3h3t.js +8 -0
  136. package/dist/assets/{refresh-cw-CILd1vAP.js → refresh-cw-Cme5qFej.js} +1 -1
  137. package/dist/assets/remote-BaVECEZw.js +1 -0
  138. package/dist/assets/requirementDiagram-TGXJPOKE-EmFph0H_.js +84 -0
  139. package/dist/assets/rotate-cw-CMRZxIkH.js +1 -0
  140. package/dist/assets/rough.esm-wJ1d3nQl.js +1 -0
  141. package/dist/assets/runtime-config-page-wygwvMB4.js +1 -0
  142. package/dist/assets/sankeyDiagram-HTMAVEWB-BXWB5Ugi.js +40 -0
  143. package/dist/assets/{save-ByJqcPTP.js → save-DNg2yJTS.js} +1 -1
  144. package/dist/assets/{search-DVIV6pfD.js → search-3ykfrAFt.js} +1 -1
  145. package/dist/assets/search-config-page-DrVKa_Ls.js +1 -0
  146. package/dist/assets/secrets-config-page-B39uQ5kF.js +3 -0
  147. package/dist/assets/security-config-BPzet76z.js +1 -0
  148. package/dist/assets/select-B5EecXJt.js +1 -0
  149. package/dist/assets/sequenceDiagram-DBY2YBRQ-ClKnO7v0.js +162 -0
  150. package/dist/assets/setting-row-Qv1Ps79v.js +1 -0
  151. package/dist/assets/{settings-2-CH5shGg_.js → settings-2-D-3um9Az.js} +1 -1
  152. package/dist/assets/sizeCapture-X5ZJPWSS-DSo-t5ou.js +1 -0
  153. package/dist/assets/{skeleton-DeX1FKw7.js → skeleton-BgkzQd4U.js} +1 -1
  154. package/dist/assets/src-Dad2ZbCt.js +1 -0
  155. package/dist/assets/stateDiagram-2N3HPSRC-BvAalBfz.js +1 -0
  156. package/dist/assets/stateDiagram-v2-6OUMAXLB-CfMU38yc.js +1 -0
  157. package/dist/assets/swimlanes-5IMT3BWC-DdVqVa1a.js +2 -0
  158. package/dist/assets/swimlanesDiagram-G3AALYLV-D9Zb9X57.js +8 -0
  159. package/dist/assets/tabs-BVD8gp3y.js +1 -0
  160. package/dist/assets/tag-chip-0qn-f3Bo.js +1 -0
  161. package/dist/assets/timeline-definition-FHXFAJF6-D4ar8IQY.js +120 -0
  162. package/dist/assets/trash-2-cnsMppRC.js +1 -0
  163. package/dist/assets/treeView-QDETBFTQ-Uy7M0WvH.js +1 -0
  164. package/dist/assets/treemap-6X3UGDF4-BJfGV7KX.js +1 -0
  165. package/dist/assets/use-config-D6yx0lb0.js +1 -0
  166. package/dist/assets/use-confirm-dialog-C_o0eQeH.js +1 -0
  167. package/dist/assets/use-viewport-layout-BWav4KCL.js +1 -0
  168. package/dist/assets/vennDiagram-L72KCM5P-CDXJ_i3p.js +34 -0
  169. package/dist/assets/wardley-OPB4EBWU-q263iF3K.js +1 -0
  170. package/dist/assets/wardleyDiagram-EHGQE667-D-dSuT_7.js +78 -0
  171. package/dist/assets/x-B3o1dWR5.js +1 -0
  172. package/dist/assets/xlsx-DUqJhg5u.js +64 -0
  173. package/dist/assets/xychartDiagram-FW5EYKEG-C9JCzsZF.js +7 -0
  174. package/dist/index.html +35 -28
  175. package/package.json +11 -6
  176. package/src/features/chat/components/chat-popover-content.tsx +1 -0
  177. package/src/features/chat/components/conversation/__tests__/chat-conversation-content.test.tsx +13 -0
  178. package/src/features/chat/components/conversation/__tests__/chat-conversation-header-section.test.tsx +21 -11
  179. package/src/features/chat/components/conversation/__tests__/chat-conversation-header.test.tsx +2 -2
  180. package/src/features/chat/components/conversation/__tests__/chat-conversation-workspace-section.test.tsx +28 -1
  181. package/src/features/chat/components/conversation/chat-conversation-content.tsx +5 -4
  182. package/src/features/chat/components/conversation/chat-conversation-header-section.tsx +9 -18
  183. package/src/features/chat/components/conversation/chat-conversation-track.tsx +35 -0
  184. package/src/features/chat/components/conversation/chat-conversation-workspace-section.tsx +2 -0
  185. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +7 -7
  186. package/src/features/chat/components/layout/chat-sidebar-utility-menu.tsx +3 -14
  187. package/src/features/chat/features/conversation/components/__tests__/session-conversation-input.streaming.test.tsx +20 -1
  188. package/src/features/chat/features/conversation/components/session-conversation-input.tsx +97 -65
  189. package/src/features/chat/features/input/input-surface-plugins/__tests__/slash-command-plugin.test.ts +43 -0
  190. package/src/features/chat/features/input/input-surface-plugins/slash-command-plugin.utils.ts +14 -10
  191. package/src/features/chat/features/input/utils/__tests__/chat-input-bar.utils.test.ts +51 -0
  192. package/src/features/chat/features/input/utils/chat-input-bar.utils.ts +61 -21
  193. package/src/features/chat/features/message/components/__tests__/chat-message-list.container.test.tsx +42 -10
  194. package/src/features/chat/features/message/components/chat-inline-file-preview.tsx +80 -0
  195. package/src/features/chat/features/message/components/chat-message-list.container.tsx +66 -56
  196. package/src/features/chat/features/message/utils/__tests__/chat-message-file-operation.utils.test.ts +30 -0
  197. package/src/features/chat/features/message/utils/chat-message-texts.utils.ts +2 -0
  198. package/src/features/chat/features/session/components/__tests__/chat-sidebar-session-item.test.tsx +37 -0
  199. package/src/features/chat/features/session/components/chat-sidebar-project-groups.tsx +4 -3
  200. package/src/features/chat/features/session/components/chat-sidebar-session-item.tsx +3 -8
  201. package/src/features/chat/features/session/components/session-header/__tests__/chat-session-header-actions.test.tsx +65 -20
  202. package/src/features/chat/features/session/components/session-header/chat-session-header-actions.tsx +26 -28
  203. package/src/features/chat/features/session/components/session-header/chat-session-project-badge.tsx +3 -3
  204. package/src/features/chat/features/session/components/session-header/chat-session-title-switcher.tsx +3 -3
  205. package/src/features/chat/features/welcome/components/chat-welcome-project-picker.tsx +3 -3
  206. package/src/features/chat/features/welcome/components/chat-welcome-session-type-picker.tsx +3 -3
  207. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-file-preview.test.tsx +424 -129
  208. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel-content.test.tsx +113 -2
  209. package/src/features/chat/features/workspace/components/__tests__/chat-session-workspace-panel.test.tsx +3 -1
  210. package/src/features/chat/features/workspace/components/chat-session-workspace-directory-browser.tsx +197 -44
  211. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumb-browser.tsx +9 -3
  212. package/src/features/chat/features/workspace/components/chat-session-workspace-file-breadcrumbs.tsx +13 -22
  213. package/src/features/chat/features/workspace/components/chat-session-workspace-file-preview.tsx +96 -194
  214. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-content.tsx +239 -1
  215. package/src/features/chat/features/workspace/components/chat-session-workspace-panel-nav.tsx +61 -7
  216. package/src/features/chat/features/workspace/components/chat-session-workspace-panel.tsx +34 -8
  217. package/src/features/chat/features/workspace/components/file-content-preview/use-workspace-file-buffer.ts +42 -0
  218. package/src/features/chat/features/workspace/components/file-content-preview/workspace-document-preview-state.tsx +18 -0
  219. package/src/features/chat/features/workspace/components/file-content-preview/workspace-docx-preview.css +89 -0
  220. package/src/features/chat/features/workspace/components/file-content-preview/workspace-docx-preview.tsx +87 -0
  221. package/src/features/chat/features/workspace/components/file-content-preview/workspace-presentation-preview.tsx +82 -0
  222. package/src/features/chat/features/workspace/components/file-content-preview/workspace-spreadsheet-preview.tsx +180 -0
  223. package/src/features/chat/features/workspace/components/workspace-file-content-preview.tsx +191 -0
  224. package/src/features/chat/features/workspace/hooks/use-chat-conversation-workspace-state.ts +1 -4
  225. package/src/features/chat/features/workspace/utils/__tests__/chat-workspace-panel-view-model.utils.test.ts +157 -13
  226. package/src/features/chat/features/workspace/utils/chat-thread-workspace-session.utils.ts +151 -2
  227. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab-persistence.utils.ts +17 -0
  228. package/src/features/chat/features/workspace/utils/chat-workspace-file-tab.utils.ts +66 -0
  229. package/src/features/chat/features/workspace/utils/chat-workspace-file-viewer.utils.ts +49 -0
  230. package/src/features/chat/features/workspace/utils/chat-workspace-panel-layout.utils.ts +13 -0
  231. package/src/features/chat/features/workspace/utils/chat-workspace-panel-view-model.utils.ts +196 -43
  232. package/src/features/chat/index.ts +1 -0
  233. package/src/features/chat/managers/__tests__/chat-thread-workspace.manager.test.ts +101 -0
  234. package/src/features/chat/managers/__tests__/chat-thread.manager.test.ts +48 -60
  235. package/src/features/chat/managers/chat-session-list.manager.ts +1 -0
  236. package/src/features/chat/managers/chat-thread.manager.ts +137 -162
  237. package/src/features/chat/pages/ncp-chat-page.tsx +1 -2
  238. package/src/features/chat/stores/__tests__/chat-thread.store.test.ts +87 -1
  239. package/src/features/chat/stores/chat-message-layout.store.test.ts +37 -0
  240. package/src/features/chat/stores/chat-message-layout.store.ts +41 -0
  241. package/src/features/chat/stores/chat-thread.store.ts +77 -40
  242. package/src/features/chat/types/chat-input-bar.types.ts +2 -0
  243. package/src/features/settings/pages/__tests__/appearance-settings-page.test.tsx +25 -8
  244. package/src/features/settings/pages/appearance-settings-page.tsx +92 -13
  245. package/src/index.css +36 -2
  246. package/src/shared/components/__tests__/file-type-icon.test.tsx +61 -0
  247. package/src/shared/components/common/__tests__/brand-header.test.tsx +17 -7
  248. package/src/shared/components/common/brand-header.tsx +34 -34
  249. package/src/shared/components/doc-browser/__tests__/doc-browser-context.test.tsx +19 -0
  250. package/src/shared/components/doc-browser/__tests__/doc-browser.test.tsx +16 -0
  251. package/src/shared/components/doc-browser/doc-browser-context.tsx +1 -0
  252. package/src/shared/components/doc-browser/doc-browser.tsx +11 -3
  253. package/src/shared/components/doc-browser/managers/doc-browser.manager.ts +5 -0
  254. package/src/shared/components/doc-browser/stores/doc-browser.store.ts +6 -1
  255. package/src/shared/components/doc-browser/types/doc-browser.types.ts +2 -0
  256. package/src/shared/components/doc-browser/utils/doc-browser-state.utils.ts +11 -0
  257. package/src/shared/components/file-type-icon.tsx +272 -0
  258. package/src/shared/components/resizable-right-panel/__tests__/resizable-right-panel.test.tsx +22 -0
  259. package/src/shared/components/resizable-right-panel/resizable-right-panel.tsx +17 -2
  260. package/src/shared/components/ui/tab-strip/__tests__/compact-tab-strip.test.tsx +38 -0
  261. package/src/shared/components/ui/tab-strip/compact-tab-strip.tsx +82 -2
  262. package/src/shared/hooks/use-server-path-read.ts +10 -5
  263. package/src/shared/lib/api/__tests__/server-path.utils.test.ts +28 -0
  264. package/src/shared/lib/api/types.ts +3 -3
  265. package/src/shared/lib/api/utils/server-path.utils.ts +20 -20
  266. package/src/shared/lib/i18n/locales/en-US/chat.json +25 -1
  267. package/src/shared/lib/i18n/locales/en-US/core.json +6 -0
  268. package/src/shared/lib/i18n/locales/zh-CN/chat.json +25 -1
  269. package/src/shared/lib/i18n/locales/zh-CN/core.json +6 -0
  270. package/src/shared/lib/session-project/__tests__/workspace-file-breadcrumb.test.ts +1 -4
  271. package/src/shared/lib/session-project/workspace-file-breadcrumb.utils.ts +1 -18
  272. package/dist/assets/api-iNBpppzj.js +0 -13
  273. package/dist/assets/appearance-settings-page-DMffQFR3.js +0 -1
  274. package/dist/assets/channels-list-page-CCtp0BRS.js +0 -8
  275. package/dist/assets/chat-page-H5a0dWvO.js +0 -1
  276. package/dist/assets/config-split-page-CrOJgB-Y.js +0 -1
  277. package/dist/assets/confirm-dialog-Chv50USy.js +0 -5
  278. package/dist/assets/desktop-update-config-KzTuXRf_.js +0 -1
  279. package/dist/assets/dist-BunzmC4B.js +0 -1
  280. package/dist/assets/dist-ChmGwvtK.js +0 -1
  281. package/dist/assets/doc-browser-DNRL4Zvd.js +0 -1
  282. package/dist/assets/doc-browser-Dg0pmkOg.js +0 -1
  283. package/dist/assets/doc-browser-context-BHY-0FSD.js +0 -1
  284. package/dist/assets/es2015-DQZ5JWwK.js +0 -41
  285. package/dist/assets/i18n-provider-Cu8XyZb_.js +0 -1
  286. package/dist/assets/index-CzfBdvK1.css +0 -1
  287. package/dist/assets/index-DGqHne1Q.js +0 -104
  288. package/dist/assets/loader-circle-CDSFuzmk.js +0 -1
  289. package/dist/assets/mcp-marketplace-page-BeEQK0DL.js +0 -9
  290. package/dist/assets/mcp-marketplace-page-D6idOTLp.js +0 -1
  291. package/dist/assets/model-config-page-bNNo-XyG.js +0 -1
  292. package/dist/assets/plus-D4DsdLN-.js +0 -1
  293. package/dist/assets/provider-scoped-model-input-IlgQCsoT.js +0 -1
  294. package/dist/assets/providers-config-page-wLo6CAJw.js +0 -1
  295. package/dist/assets/react-BPIsQIlO.js +0 -8
  296. package/dist/assets/remote-uKEYp7AR.js +0 -1
  297. package/dist/assets/rotate-cw-wPFPg1kH.js +0 -1
  298. package/dist/assets/runtime-config-page-DDn1sP4G.js +0 -1
  299. package/dist/assets/search-config-page-B-Cf4iiB.js +0 -1
  300. package/dist/assets/secrets-config-page-DPKsY8Iw.js +0 -3
  301. package/dist/assets/security-config-e9SSBlKr.js +0 -1
  302. package/dist/assets/select-BdgczSNw.js +0 -1
  303. package/dist/assets/setting-row-BkTVUTKx.js +0 -1
  304. package/dist/assets/side-dock-BsBvcJ9i.js +0 -3
  305. package/dist/assets/switch-Cv8Ekb3x.js +0 -1
  306. package/dist/assets/tag-chip-RB9uKcoC.js +0 -1
  307. package/dist/assets/tooltip-oQlEN-l6.js +0 -1
  308. package/dist/assets/use-config-l3W7y8Qz.js +0 -1
  309. package/dist/assets/use-confirm-dialog-BAxaVOJI.js +0 -1
  310. package/dist/assets/x-BBMffEN0.js +0 -1
  311. package/src/features/chat/components/layout/__tests__/chat-sidebar-utility-menu.test.tsx +0 -55
  312. /package/dist/assets/{config-hints-C_iP1zl_.js → config-hints-LxG80Uj5.js} +0 -0
  313. /package/dist/assets/{host-capabilities-9bB_998Z.js → host-capabilities-CFbAfrrA.js} +0 -0
  314. /package/dist/assets/{middleware-BILWbJE4.js → middleware-CAXxl-af.js} +0 -0
@@ -1,13 +1,22 @@
1
1
  import { render, screen } from "@testing-library/react";
2
+ import userEvent from "@testing-library/user-event";
2
3
  import { expect, it, vi } from "vitest";
3
4
  import { ChatSessionWorkspacePanelContent } from "@/features/chat/features/workspace/components/chat-session-workspace-panel-content";
4
5
  import type { ResolvedChildSessionTab } from "@/features/chat/features/ncp/hooks/use-ncp-child-session-tabs-view";
5
6
 
7
+ const mocks = vi.hoisted(() => ({
8
+ materializeSideChatDraft: vi.fn(),
9
+ openChildSessions: vi.fn(),
10
+ openFilePreview: vi.fn(),
11
+ openProjectFiles: vi.fn(),
12
+ openSessionCronPanel: vi.fn(),
13
+ selectChildSessionDetail: vi.fn(),
14
+ }));
15
+
6
16
  vi.mock("@/features/chat/components/providers/chat-presenter.provider", () => ({
7
17
  usePresenter: () => ({
8
18
  chatThreadManager: {
9
- materializeSideChatDraft: vi.fn(),
10
- openFilePreview: vi.fn(),
19
+ ...mocks,
11
20
  },
12
21
  }),
13
22
  }));
@@ -16,6 +25,33 @@ vi.mock("@/features/chat/features/conversation/components/session-conversation-a
16
25
  SessionConversationArea: () => <div data-testid="session-conversation-area" />,
17
26
  }));
18
27
 
28
+ vi.mock("@/shared/hooks/use-server-path-browse", () => ({
29
+ useServerPathBrowse: () => ({
30
+ isLoading: false,
31
+ error: null,
32
+ data: {
33
+ currentPath: "/Users/peiwang/Projects/nextbot",
34
+ parentPath: "/Users/peiwang/Projects",
35
+ homePath: "/Users/peiwang",
36
+ breadcrumbs: [],
37
+ entries: [
38
+ {
39
+ name: "src",
40
+ path: "/Users/peiwang/Projects/nextbot/src",
41
+ kind: "directory",
42
+ hidden: false,
43
+ },
44
+ {
45
+ name: "package.json",
46
+ path: "/Users/peiwang/Projects/nextbot/package.json",
47
+ kind: "file",
48
+ hidden: false,
49
+ },
50
+ ],
51
+ },
52
+ }),
53
+ }));
54
+
19
55
  function createChildTab(): ResolvedChildSessionTab {
20
56
  return {
21
57
  sessionKey: "child-1",
@@ -40,7 +76,9 @@ it("shows compact child session metadata without repeating the tab title", () =>
40
76
  kind: "child-session",
41
77
  tab: createChildTab(),
42
78
  }}
79
+ childSessionTabs={[createChildTab()]}
43
80
  filePreviewRefreshVersion={0}
81
+ sessionKey="parent-1"
44
82
  sessionCronJobs={[]}
45
83
  sessionProjectRoot={null}
46
84
  sessionWorkingDir={null}
@@ -53,3 +91,76 @@ it("shows compact child session metadata without repeating the tab title", () =>
53
91
  expect(screen.getByText("nextbot")).toBeTruthy();
54
92
  expect(screen.getByTitle("/Users/peiwang/Projects/nextbot")).toBeTruthy();
55
93
  });
94
+
95
+ it("shows all session workspace entries in the overview", async () => {
96
+ const user = userEvent.setup();
97
+ const childTab = createChildTab();
98
+
99
+ render(
100
+ <ChatSessionWorkspacePanelContent
101
+ activeSelection={{ kind: "overview" }}
102
+ childSessionTabs={[childTab]}
103
+ filePreviewRefreshVersion={0}
104
+ sessionKey="parent-1"
105
+ sessionCronJobs={[]}
106
+ sessionProjectRoot="/tmp/project"
107
+ sessionWorkingDir="/tmp/project"
108
+ />,
109
+ );
110
+
111
+ expect(screen.getByText("Overview")).toBeTruthy();
112
+ const childSessionsButton = screen.getByRole("button", {
113
+ name: /Child sessions/,
114
+ });
115
+ const cronJobsButton = screen.getByRole("button", {
116
+ name: /Session cron jobs/,
117
+ });
118
+
119
+ expect((childSessionsButton as HTMLButtonElement).disabled).toBe(false);
120
+ expect((cronJobsButton as HTMLButtonElement).disabled).toBe(false);
121
+
122
+ await user.click(childSessionsButton);
123
+ await user.click(cronJobsButton);
124
+ await user.click(screen.getByRole("button", { name: /Project files/ }));
125
+
126
+ expect(mocks.openChildSessions).toHaveBeenCalledWith("parent-1");
127
+ expect(mocks.openSessionCronPanel).toHaveBeenCalledWith("parent-1");
128
+ expect(mocks.openProjectFiles).toHaveBeenCalledWith("parent-1");
129
+ });
130
+
131
+ it("shows an empty child sessions page instead of disabling the entry", () => {
132
+ render(
133
+ <ChatSessionWorkspacePanelContent
134
+ activeSelection={{ kind: "child-sessions" }}
135
+ childSessionTabs={[]}
136
+ filePreviewRefreshVersion={0}
137
+ sessionKey="parent-1"
138
+ sessionCronJobs={[]}
139
+ sessionProjectRoot={null}
140
+ sessionWorkingDir={null}
141
+ />,
142
+ );
143
+
144
+ expect(screen.getByText("No child sessions yet.")).toBeTruthy();
145
+ });
146
+
147
+ it("shows the selected session project as a hierarchical file tree", () => {
148
+ render(
149
+ <ChatSessionWorkspacePanelContent
150
+ activeSelection={{ kind: "project-files" }}
151
+ childSessionTabs={[]}
152
+ filePreviewRefreshVersion={0}
153
+ sessionKey="parent-1"
154
+ sessionCronJobs={[]}
155
+ sessionProjectRoot="/Users/peiwang/Projects/nextbot"
156
+ sessionWorkingDir="/Users/peiwang/Projects/nextbot"
157
+ />,
158
+ );
159
+
160
+ expect(screen.getByRole("tree", { name: "Project files" })).toBeTruthy();
161
+ expect(screen.getByText("nextbot")).toBeTruthy();
162
+ expect(
163
+ screen.getByRole("treeitem", { name: "Open directory: src" }),
164
+ ).toBeTruthy();
165
+ expect(document.querySelector('[data-file-type-icon="npm"]')).toBeTruthy();
166
+ });
@@ -9,11 +9,12 @@ const mocks = vi.hoisted(() => ({
9
9
  syncVisibleWorkspaceSelection: vi.fn(),
10
10
  selectChildSessionDetail: vi.fn(),
11
11
  selectWorkspaceFile: vi.fn(),
12
- closeWorkspaceFile: vi.fn(),
12
+ closeWorkspaceTab: vi.fn(),
13
13
  openSessionCronPanel: vi.fn(),
14
14
  goBackWorkspacePanel: vi.fn(),
15
15
  goForwardWorkspacePanel: vi.fn(),
16
16
  closeWorkspacePanel: vi.fn(),
17
+ setWorkspacePanelWidth: vi.fn(),
17
18
  invalidateQueries: vi.fn(),
18
19
  }));
19
20
 
@@ -71,6 +72,7 @@ function renderPanel(displayMode: "docked" | "overlay" = "docked") {
71
72
  activeSideChatDraft={null}
72
73
  workspaceFileTabs={[fileTab]}
73
74
  activeWorkspaceFileKey={fileTab.key}
75
+ closedWorkspaceTabEntries={[]}
74
76
  workspaceNavigationHistory={[{ kind: "file", key: fileTab.key }]}
75
77
  workspaceNavigationHistoryIndex={0}
76
78
  activePanelKind="file"
@@ -1,7 +1,8 @@
1
- import type { ReactNode } from "react";
1
+ import { useState, type ReactNode } from "react";
2
2
  import type { ChatFileOpenActionViewModel } from "@nextclaw/agent-chat-ui";
3
- import { ChevronRight, FileCode2, Folder } from "lucide-react";
4
- import type { useServerPathBrowse } from "@/shared/hooks/use-server-path-browse";
3
+ import { ChevronDown, ChevronRight, Folder, FolderOpen } from "lucide-react";
4
+ import { FileTypeIcon } from "@/shared/components/file-type-icon";
5
+ import { useServerPathBrowse } from "@/shared/hooks/use-server-path-browse";
5
6
  import type { ServerPathEntryView } from "@/shared/lib/api";
6
7
  import { t } from "@/shared/lib/i18n";
7
8
  import { cn } from "@/shared/lib/utils";
@@ -13,20 +14,9 @@ type ChatSessionWorkspaceDirectoryBrowserProps = {
13
14
  text: string;
14
15
  tone?: "muted" | "error";
15
16
  }) => ReactNode;
17
+ showRoot?: boolean;
16
18
  };
17
19
 
18
- function WorkspaceDirectoryEntryIcon({
19
- kind,
20
- }: {
21
- kind: ServerPathEntryView["kind"];
22
- }) {
23
- return kind === "directory" ? (
24
- <Folder className="h-4 w-4 shrink-0 text-emerald-600" />
25
- ) : (
26
- <FileCode2 className="h-4 w-4 shrink-0 text-sky-600" />
27
- );
28
- }
29
-
30
20
  function buildDirectoryEntryLabel(entry: ServerPathEntryView): string {
31
21
  const actionLabel =
32
22
  entry.kind === "directory"
@@ -35,18 +25,115 @@ function buildDirectoryEntryLabel(entry: ServerPathEntryView): string {
35
25
  return `${actionLabel}: ${entry.name}`;
36
26
  }
37
27
 
38
- export function ChatSessionWorkspaceDirectoryBrowser({
28
+ function readPathName(path: string): string {
29
+ return path.split(/[\\/]/).filter(Boolean).pop() ?? path;
30
+ }
31
+
32
+ function readBrowseError(
33
+ browseQuery: ReturnType<typeof useServerPathBrowse>,
34
+ ): string | null {
35
+ if (!browseQuery.error) {
36
+ return null;
37
+ }
38
+ return browseQuery.error instanceof Error
39
+ ? browseQuery.error.message
40
+ : String(browseQuery.error);
41
+ }
42
+
43
+ function WorkspaceDirectoryEntryIcon({
44
+ fileName,
45
+ isDirectory,
46
+ isExpanded,
47
+ }: {
48
+ fileName: string;
49
+ isDirectory: boolean;
50
+ isExpanded: boolean;
51
+ }) {
52
+ if (!isDirectory) {
53
+ return <FileTypeIcon fileName={fileName} />;
54
+ }
55
+ return isExpanded ? (
56
+ <FolderOpen className="h-4 w-4 shrink-0 text-amber-500" />
57
+ ) : (
58
+ <Folder className="h-4 w-4 shrink-0 text-amber-500" />
59
+ );
60
+ }
61
+
62
+ function WorkspaceDirectoryTreeChildren({
39
63
  browseQuery,
64
+ level,
40
65
  onFileOpen,
41
- renderStatus,
42
- }: ChatSessionWorkspaceDirectoryBrowserProps) {
66
+ }: {
67
+ browseQuery: ReturnType<typeof useServerPathBrowse>;
68
+ level: number;
69
+ onFileOpen: (action: ChatFileOpenActionViewModel) => void;
70
+ }) {
43
71
  const entries = browseQuery.data?.entries ?? [];
44
- const errorMessage = browseQuery.error
45
- ? browseQuery.error instanceof Error
46
- ? browseQuery.error.message
47
- : String(browseQuery.error)
48
- : null;
49
- const openEntry = (entry: ServerPathEntryView) => {
72
+ const errorMessage = readBrowseError(browseQuery);
73
+ const statusStyle = { paddingLeft: `${36 + level * 14}px` };
74
+
75
+ if (browseQuery.isLoading && !browseQuery.data) {
76
+ return (
77
+ <div
78
+ className="h-7 truncate pr-2 text-[11px] leading-7 text-gray-400"
79
+ style={statusStyle}
80
+ >
81
+ {t("chatWorkspaceLoadingDirectory")}
82
+ </div>
83
+ );
84
+ }
85
+ if (errorMessage && !browseQuery.data) {
86
+ return (
87
+ <div
88
+ className="h-7 truncate pr-2 text-[11px] leading-7 text-rose-600"
89
+ style={statusStyle}
90
+ title={errorMessage}
91
+ >
92
+ {t("chatWorkspaceDirectoryLoadFailed")}
93
+ </div>
94
+ );
95
+ }
96
+ if (entries.length === 0) {
97
+ return (
98
+ <div
99
+ className="h-7 truncate pr-2 text-[11px] leading-7 text-gray-400"
100
+ style={statusStyle}
101
+ >
102
+ {t("chatWorkspaceDirectoryEmpty")}
103
+ </div>
104
+ );
105
+ }
106
+ return entries.map((entry) => (
107
+ <WorkspaceDirectoryTreeEntry
108
+ key={entry.path}
109
+ entry={entry}
110
+ level={level + 1}
111
+ onFileOpen={onFileOpen}
112
+ />
113
+ ));
114
+ }
115
+
116
+ function WorkspaceDirectoryTreeEntry({
117
+ entry,
118
+ level,
119
+ onFileOpen,
120
+ }: {
121
+ entry: ServerPathEntryView;
122
+ level: number;
123
+ onFileOpen: (action: ChatFileOpenActionViewModel) => void;
124
+ }) {
125
+ const isDirectory = entry.kind === "directory";
126
+ const [isExpanded, setIsExpanded] = useState(false);
127
+ const browseQuery = useServerPathBrowse({
128
+ path: entry.path,
129
+ includeFiles: true,
130
+ enabled: isDirectory && isExpanded,
131
+ });
132
+ const activateEntry = () => {
133
+ if (isDirectory) {
134
+ setIsExpanded((value) => !value);
135
+ return;
136
+ }
50
137
  onFileOpen({
51
138
  path: entry.path,
52
139
  label: entry.name,
@@ -54,6 +141,60 @@ export function ChatSessionWorkspaceDirectoryBrowser({
54
141
  });
55
142
  };
56
143
 
144
+ return (
145
+ <div
146
+ role="treeitem"
147
+ aria-expanded={isDirectory ? isExpanded : undefined}
148
+ aria-label={buildDirectoryEntryLabel(entry)}
149
+ >
150
+ <button
151
+ type="button"
152
+ className={cn(
153
+ "flex h-7 w-full min-w-0 items-center gap-1.5 pr-2 text-left text-[13px] text-gray-700 transition-colors hover:bg-gray-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-border",
154
+ entry.hidden ? "opacity-65" : null,
155
+ )}
156
+ style={{ paddingLeft: `${8 + level * 14}px` }}
157
+ onClick={activateEntry}
158
+ >
159
+ <span className="inline-flex h-4 w-4 shrink-0 items-center justify-center text-gray-400">
160
+ {isDirectory ? (
161
+ isExpanded ? (
162
+ <ChevronDown className="h-3.5 w-3.5" />
163
+ ) : (
164
+ <ChevronRight className="h-3.5 w-3.5" />
165
+ )
166
+ ) : null}
167
+ </span>
168
+ <WorkspaceDirectoryEntryIcon
169
+ fileName={entry.name}
170
+ isDirectory={isDirectory}
171
+ isExpanded={isExpanded}
172
+ />
173
+ <span className="min-w-0 flex-1 truncate">{entry.name}</span>
174
+ </button>
175
+
176
+ {isDirectory && isExpanded ? (
177
+ <div role="group">
178
+ <WorkspaceDirectoryTreeChildren
179
+ browseQuery={browseQuery}
180
+ level={level}
181
+ onFileOpen={onFileOpen}
182
+ />
183
+ </div>
184
+ ) : null}
185
+ </div>
186
+ );
187
+ }
188
+
189
+ export function ChatSessionWorkspaceDirectoryBrowser({
190
+ browseQuery,
191
+ onFileOpen,
192
+ renderStatus,
193
+ showRoot = false,
194
+ }: ChatSessionWorkspaceDirectoryBrowserProps) {
195
+ const entries = browseQuery.data?.entries ?? [];
196
+ const errorMessage = readBrowseError(browseQuery);
197
+
57
198
  if (browseQuery.isLoading && !browseQuery.data) {
58
199
  return renderStatus({ text: t("chatWorkspaceLoadingDirectory") });
59
200
  }
@@ -72,28 +213,40 @@ export function ChatSessionWorkspaceDirectoryBrowser({
72
213
  return (
73
214
  <div
74
215
  data-testid="workspace-directory-browser"
75
- className="h-full overflow-auto bg-white px-2 py-2 custom-scrollbar"
216
+ role="tree"
217
+ aria-label={t("chatWorkspaceProjectFiles")}
218
+ className="h-full overflow-auto bg-white py-2 custom-scrollbar"
76
219
  >
77
- <div className="space-y-0.5">
78
- {entries.map((entry) => (
79
- <button
220
+ {showRoot && browseQuery.data ? (
221
+ <div role="treeitem" aria-expanded="true">
222
+ <div className="flex h-8 items-center gap-1.5 border-b border-gray-100 px-2 text-xs font-semibold text-gray-700">
223
+ <ChevronDown className="h-3.5 w-3.5 shrink-0 text-gray-400" />
224
+ <FolderOpen className="h-4 w-4 shrink-0 text-amber-500" />
225
+ <span className="min-w-0 flex-1 truncate" title={browseQuery.data.currentPath}>
226
+ {readPathName(browseQuery.data.currentPath)}
227
+ </span>
228
+ </div>
229
+ <div role="group" className="pt-1">
230
+ {entries.map((entry) => (
231
+ <WorkspaceDirectoryTreeEntry
232
+ key={entry.path}
233
+ entry={entry}
234
+ level={1}
235
+ onFileOpen={onFileOpen}
236
+ />
237
+ ))}
238
+ </div>
239
+ </div>
240
+ ) : (
241
+ entries.map((entry) => (
242
+ <WorkspaceDirectoryTreeEntry
80
243
  key={entry.path}
81
- type="button"
82
- aria-label={buildDirectoryEntryLabel(entry)}
83
- className={cn(
84
- "flex h-8 w-full min-w-0 items-center gap-2 rounded-sm px-2 text-left text-sm text-gray-700 transition-colors hover:bg-gray-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-border",
85
- entry.hidden ? "opacity-65" : null,
86
- )}
87
- onClick={() => openEntry(entry)}
88
- >
89
- <WorkspaceDirectoryEntryIcon kind={entry.kind} />
90
- <span className="min-w-0 flex-1 truncate">{entry.name}</span>
91
- {entry.kind === "directory" ? (
92
- <ChevronRight className="h-3.5 w-3.5 shrink-0 text-gray-300" />
93
- ) : null}
94
- </button>
95
- ))}
96
- </div>
244
+ entry={entry}
245
+ level={0}
246
+ onFileOpen={onFileOpen}
247
+ />
248
+ ))
249
+ )}
97
250
  </div>
98
251
  );
99
252
  }
@@ -1,6 +1,7 @@
1
1
  import { Fragment } from "react";
2
2
  import type { ChatFileOpenActionViewModel } from "@nextclaw/agent-chat-ui";
3
- import { ChevronRight, File, Folder, Loader2 } from "lucide-react";
3
+ import { ChevronRight, Folder, Loader2 } from "lucide-react";
4
+ import { FileTypeIcon } from "@/shared/components/file-type-icon";
4
5
  import { ScrollArea } from "@/shared/components/ui/scroll-area";
5
6
  import { useServerPathBrowse } from "@/shared/hooks/use-server-path-browse";
6
7
  import type { ServerPathEntryView } from "@/shared/lib/api";
@@ -8,14 +9,16 @@ import { t } from "@/shared/lib/i18n";
8
9
  import { cn } from "@/shared/lib/utils";
9
10
 
10
11
  function WorkspaceBreadcrumbEntryIcon({
12
+ name,
11
13
  kind,
12
14
  }: {
15
+ name: string;
13
16
  kind: ServerPathEntryView["kind"];
14
17
  }) {
15
18
  return kind === "directory" ? (
16
19
  <Folder className="h-3.5 w-3.5 shrink-0 text-emerald-600" />
17
20
  ) : (
18
- <File className="h-3.5 w-3.5 shrink-0 text-sky-600" />
21
+ <FileTypeIcon fileName={name} size="compact" />
19
22
  );
20
23
  }
21
24
 
@@ -102,7 +105,10 @@ export function WorkspaceBreadcrumbBrowser({
102
105
  )}
103
106
  onClick={() => openEntry(entry)}
104
107
  >
105
- <WorkspaceBreadcrumbEntryIcon kind={entry.kind} />
108
+ <WorkspaceBreadcrumbEntryIcon
109
+ kind={entry.kind}
110
+ name={entry.name}
111
+ />
106
112
  <span className="min-w-0 flex-1 truncate">{entry.name}</span>
107
113
  {entry.kind === "directory" ? (
108
114
  <ChevronRight className="h-3 w-3 shrink-0 text-gray-300" />
@@ -1,7 +1,9 @@
1
1
  import { Fragment, useState } from "react";
2
2
  import type { ChatFileOpenActionViewModel } from "@nextclaw/agent-chat-ui";
3
- import { ChevronRight, FileCode2, Folder, FolderTree } from "lucide-react";
4
- import { Popover, PopoverContent, PopoverTrigger } from "@/shared/components/ui/popover";
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";
5
7
  import { WorkspaceBreadcrumbBrowser } from "./chat-session-workspace-file-breadcrumb-browser";
6
8
  import type {
7
9
  WorkspaceFileBreadcrumbSegmentViewModel,
@@ -10,15 +12,10 @@ import type {
10
12
  import { t } from "@/shared/lib/i18n";
11
13
  import { cn } from "@/shared/lib/utils";
12
14
 
13
- function WorkspaceBreadcrumbMetaChip({ tone = "neutral", value }: { tone?: "neutral" | "warning"; value: string }) {
15
+ function WorkspaceBreadcrumbWarningChip({ value }: { value: string }) {
14
16
  return (
15
17
  <span
16
- className={cn(
17
- "inline-flex h-5 items-center rounded-sm border px-1.5 text-[10px] font-medium leading-none",
18
- tone === "warning"
19
- ? "border-amber-200 bg-amber-50 text-amber-700"
20
- : "border-gray-200 bg-gray-50 text-gray-500",
21
- )}
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"
22
19
  >
23
20
  {value}
24
21
  </span>
@@ -62,12 +59,12 @@ function WorkspaceBreadcrumbSegmentButton({
62
59
  ) : segment.kind === "directory" && segment.isCurrent ? (
63
60
  <Folder className="h-3 w-3 shrink-0" />
64
61
  ) : segment.isCurrent ? (
65
- <FileCode2 className="h-3 w-3 shrink-0" />
62
+ <FileTypeIcon fileName={segment.label} size="compact" />
66
63
  ) : null}
67
64
  <span>{segment.label}</span>
68
65
  </button>
69
66
  </PopoverTrigger>
70
- <PopoverContent
67
+ <ChatPopoverContent
71
68
  data-testid="workspace-breadcrumb-popover"
72
69
  className="w-[22rem] rounded-md p-0"
73
70
  align="start"
@@ -78,7 +75,7 @@ function WorkspaceBreadcrumbSegmentButton({
78
75
  onClose={() => setOpen(false)}
79
76
  onFileOpen={onFileOpen}
80
77
  />
81
- </PopoverContent>
78
+ </ChatPopoverContent>
82
79
  </Popover>
83
80
  );
84
81
  }
@@ -114,17 +111,11 @@ export function ChatSessionWorkspaceFileBreadcrumbs({
114
111
  ))}
115
112
  </div>
116
113
 
117
- {breadcrumb.locationLabel || breadcrumb.truncated ? (
114
+ {breadcrumb.truncated ? (
118
115
  <div className="flex shrink-0 flex-wrap items-center justify-end gap-1">
119
- {breadcrumb.locationLabel ? (
120
- <WorkspaceBreadcrumbMetaChip value={breadcrumb.locationLabel} />
121
- ) : null}
122
- {breadcrumb.truncated ? (
123
- <WorkspaceBreadcrumbMetaChip
124
- tone="warning"
125
- value={t("chatWorkspacePreviewTruncated")}
126
- />
127
- ) : null}
116
+ <WorkspaceBreadcrumbWarningChip
117
+ value={t("chatWorkspacePreviewTruncated")}
118
+ />
128
119
  </div>
129
120
  ) : null}
130
121
  </div>