@nextclaw/ui 0.12.10 → 0.12.12

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 (543) hide show
  1. package/CHANGELOG.md +103 -10
  2. package/dist/assets/api-DnPN4SyA.js +15 -0
  3. package/dist/assets/app-manager-provider-M7TngYxx.js +1 -0
  4. package/dist/assets/app-navigation.config-B5YIdRju.js +1 -0
  5. package/dist/assets/{book-open-DzdUViDm.js → book-open-B4mOKdz8.js} +1 -1
  6. package/dist/assets/channels-list-page-Cm-Bbu6u.js +8 -0
  7. package/dist/assets/chat-C0ZNZtS3.js +58 -0
  8. package/dist/assets/chat-page-CGHNhXaw.js +1 -0
  9. package/dist/assets/chunk-JZWAC4HX-BJer-fqD.js +3 -0
  10. package/dist/assets/config-split-page-B3PRA_AV.js +1 -0
  11. package/dist/assets/{createLucideIcon-dy5ie7Ox.js → createLucideIcon-C_GFKVuW.js} +1 -1
  12. package/dist/assets/desktop-update-config-Dfh-3uma.js +1 -0
  13. package/dist/assets/dialog-D-I7ONHQ.js +5 -0
  14. package/dist/assets/{dist-Cy7_j6hA.js → dist-DreLBS93.js} +1 -1
  15. package/dist/assets/doc-browser-CoKIUCJj.js +1 -0
  16. package/dist/assets/doc-browser-CwgI7ipB.js +1 -0
  17. package/dist/assets/doc-browser-DYKpRqe-.js +1 -0
  18. package/dist/assets/doc-browser-context-Dib9sS83.js +1 -0
  19. package/dist/assets/es2015-DMSUl3fm.js +41 -0
  20. package/dist/assets/{external-link-kZSAO8nT.js → external-link-DP2IJ7AM.js} +1 -1
  21. package/dist/assets/folder-BPwc278w.js +1 -0
  22. package/dist/assets/{hash-BHJC2Ovu.js → hash-CvcvtMBq.js} +1 -1
  23. package/dist/assets/i18n-BnNAQpVM.js +1 -0
  24. package/dist/assets/index-Bc6c1kIx.js +2 -0
  25. package/dist/assets/index-mRmSAB-e.css +1 -0
  26. package/dist/assets/key-round-BQXmPSxD.js +1 -0
  27. package/dist/assets/loader-circle-C6gg2m2a.js +1 -0
  28. package/dist/assets/{LogoBadge-hO7tY7hE.js → logo-badge-uB4SwANR.js} +1 -1
  29. package/dist/assets/{logos-B7gRObP8.js → logos-BcELLmYh.js} +1 -1
  30. package/dist/assets/marketplace-page-BCrS-jH6.js +49 -0
  31. package/dist/assets/marketplace-page-DVrlpB68.js +1 -0
  32. package/dist/assets/mcp-marketplace-page-CjrxT6wI.js +40 -0
  33. package/dist/assets/mcp-marketplace-page-pQ_A38fH.js +1 -0
  34. package/dist/assets/message-square-CLVODA23.js +1 -0
  35. package/dist/assets/model-config-D4myteLK.js +1 -0
  36. package/dist/assets/notice-card-DX_NEZTQ.js +1 -0
  37. package/dist/assets/play-DeNVUA5C.js +1 -0
  38. package/dist/assets/plus-BptLViq1.js +1 -0
  39. package/dist/assets/popover-Dm_NQ3Cs.js +1 -0
  40. package/dist/assets/provider-scoped-model-input-BLHImwI5.js +1 -0
  41. package/dist/assets/providers-list-DsBFslNi.js +1 -0
  42. package/dist/assets/{refresh-ccw-COVhNHtN.js → refresh-ccw-CeG203yU.js} +1 -1
  43. package/dist/assets/remote-CQQykOYe.js +1 -0
  44. package/dist/assets/{rotate-cw-oHMKJMC8.js → rotate-cw-F7aThvYj.js} +1 -1
  45. package/dist/assets/runtime-config-page-Bz9r68Rf.js +1 -0
  46. package/dist/assets/{save-EqJPOF0G.js → save-7ztImRj7.js} +1 -1
  47. package/dist/assets/search-DZSNKEGp.js +1 -0
  48. package/dist/assets/search-config-C-6KpgRQ.js +1 -0
  49. package/dist/assets/secrets-config-MiMElvpm.js +3 -0
  50. package/dist/assets/select-RgeHgn_-.js +1 -0
  51. package/dist/assets/sessions-config-page-0KNW9QC_.js +2 -0
  52. package/dist/assets/setting-row-vwm4XKv2.js +1 -0
  53. package/dist/assets/settings-DjvNMJde.js +1 -0
  54. package/dist/assets/skeleton-5Mg6vZHN.js +1 -0
  55. package/dist/assets/sparkles-CyDTgTM4.js +1 -0
  56. package/dist/assets/{status-dot-DpPtVzQT.js → status-dot-aQU9Mia4.js} +1 -1
  57. package/dist/assets/{tabs-custom-YcZUWn3o.js → tabs-custom-C4P7g4vR.js} +1 -1
  58. package/dist/assets/tag-chip-DGqz3TON.js +1 -0
  59. package/dist/assets/theme-provider-CUppbOyN.js +1 -0
  60. package/dist/assets/tooltip-DQlSKhZ_.js +1 -0
  61. package/dist/assets/{trash-2-mJT6oWa2.js → trash-2-C1cdqL6V.js} +1 -1
  62. package/dist/assets/use-config-CrsavfWZ.js +1 -0
  63. package/dist/assets/use-confirm-dialog-D1AnLFlc.js +1 -0
  64. package/dist/assets/use-infinite-scroll-loader-DZhv-rmv.js +1 -0
  65. package/dist/assets/use-viewport-layout-CytJAPWM.js +1 -0
  66. package/dist/assets/x-BjMO7v8q.js +1 -0
  67. package/dist/index.html +39 -22
  68. package/module-structure.config.json +7 -0
  69. package/package.json +5 -5
  70. package/src/app/components/app-manager-provider.tsx +20 -0
  71. package/src/{components/providers/I18nProvider.tsx → app/components/i18n-provider.tsx} +1 -1
  72. package/src/{components → app/components}/layout/app-layout.test.tsx +50 -3
  73. package/src/app/components/layout/app-layout.tsx +54 -0
  74. package/src/{components → app/components}/layout/page-layout.tsx +1 -1
  75. package/src/app/components/layout/runtime-status-entry.test.tsx +101 -0
  76. package/src/app/components/layout/runtime-status-entry.tsx +95 -0
  77. package/src/app/components/layout/settings-entry-page.test.tsx +65 -0
  78. package/src/app/components/layout/settings-entry-page.tsx +13 -0
  79. package/src/{components → app/components}/layout/sidebar-items.tsx +2 -2
  80. package/src/{components → app/components}/layout/sidebar.layout.test.tsx +19 -12
  81. package/src/{components/layout/Sidebar.tsx → app/components/layout/sidebar.tsx} +25 -89
  82. package/src/{components/providers/ThemeProvider.tsx → app/components/theme-provider.tsx} +2 -2
  83. package/src/app/configs/app-navigation.config.ts +246 -0
  84. package/src/{hooks → app/hooks}/use-realtime-query-bridge.ts +36 -20
  85. package/src/app/hooks/use-viewport-layout.ts +15 -0
  86. package/src/app/index.tsx +261 -0
  87. package/src/app/managers/app.manager.ts +12 -0
  88. package/src/app/managers/viewport-layout.manager.ts +73 -0
  89. package/src/app/stores/viewport-layout.store.ts +32 -0
  90. package/src/{test/setup.ts → app/test/vitest-setup.ts} +3 -3
  91. package/src/{account → features/account}/components/account-panel.tsx +19 -19
  92. package/src/{components/auth → features/account/components}/login-page.tsx +4 -4
  93. package/src/{hooks → features/account/hooks}/use-auth.test.ts +1 -1
  94. package/src/{hooks → features/account/hooks}/use-auth.ts +3 -3
  95. package/src/features/account/index.ts +7 -0
  96. package/src/{account → features/account}/managers/account.manager.ts +6 -6
  97. package/src/{components/agents → features/agents/components}/agent-dialogs.tsx +11 -11
  98. package/src/{components/agents → features/agents/components}/agents-page.test.tsx +12 -9
  99. package/src/{components/agents → features/agents/components}/agents-page.tsx +17 -17
  100. package/src/features/agents/index.ts +1 -0
  101. package/src/{components/config → features/channels/components}/channel-form-fields-section.tsx +11 -32
  102. package/src/{components/config/ChannelForm.test.tsx → features/channels/components/config/channel-form.test.tsx} +4 -4
  103. package/src/features/channels/components/config/channel-form.tsx +382 -0
  104. package/src/{components → features/channels/components}/config/weixin-channel-auth-section.test.tsx +6 -3
  105. package/src/features/channels/components/config/weixin-channel-auth-section.tsx +245 -0
  106. package/src/{hooks → features/channels/hooks}/use-channel-auth.ts +1 -1
  107. package/src/features/channels/index.ts +5 -0
  108. package/src/features/channels/pages/channels-list-page.test.tsx +288 -0
  109. package/src/{components/config/ChannelsList.tsx → features/channels/pages/channels-list-page.tsx} +57 -83
  110. package/src/{components/config/channel-form-fields.test.ts → features/channels/utils/channel-form-fields.utils.test.ts} +1 -1
  111. package/src/{components/config/channel-form-fields.ts → features/channels/utils/channel-form-fields.utils.ts} +1 -1
  112. package/src/{lib/channel-tutorials.ts → features/channels/utils/channel-tutorials.utils.ts} +2 -2
  113. package/src/{components/chat → features/chat/components}/chat-session-type-option-item.test.tsx +1 -1
  114. package/src/{components/chat → features/chat/components}/chat-session-type-option-item.tsx +4 -4
  115. package/src/{components/chat → features/chat/components}/chat-session-workspace-file-preview.test.tsx +4 -4
  116. package/src/{components/chat → features/chat/components}/chat-session-workspace-file-preview.tsx +12 -32
  117. package/src/{components/chat → features/chat/components}/chat-session-workspace-panel-nav.tsx +8 -20
  118. package/src/{components/chat → features/chat/components}/chat-session-workspace-panel.tsx +105 -65
  119. package/src/features/chat/components/chat-sidebar-list-mode-switch.tsx +28 -0
  120. package/src/{components/chat → features/chat/components}/chat-sidebar-project-groups.tsx +6 -6
  121. package/src/{components/chat → features/chat/components}/chat-sidebar-session-item.tsx +10 -10
  122. package/src/{components/chat/ChatWelcome.test.tsx → features/chat/components/chat-welcome.test.tsx} +1 -1
  123. package/src/{components/chat/ChatWelcome.tsx → features/chat/components/chat-welcome.tsx} +5 -10
  124. package/src/features/chat/components/config/sessions-config-detail-pane.tsx +244 -0
  125. package/src/{components/chat → features/chat/components/conversation}/chat-attachment-upload-limit.test.ts +1 -4
  126. package/src/features/chat/components/conversation/chat-conversation-header.tsx +146 -0
  127. package/src/{components/chat → features/chat/components/conversation}/chat-conversation-panel.test.tsx +41 -19
  128. package/src/{components/chat → features/chat/components/conversation}/chat-conversation-panel.tsx +28 -140
  129. package/src/{components/chat/containers → features/chat/components/conversation}/chat-input-bar.container.tsx +137 -128
  130. package/src/{components/chat/containers → features/chat/components/conversation}/chat-message-list.container.test.tsx +2 -2
  131. package/src/{components/chat/containers → features/chat/components/conversation}/chat-message-list.container.tsx +6 -6
  132. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-header-actions.test.tsx +3 -3
  133. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-header-actions.tsx +6 -6
  134. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-header-menu-item.tsx +1 -1
  135. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-project-badge.test.tsx +3 -3
  136. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-project-badge.tsx +5 -5
  137. package/src/{components/chat → features/chat/components/conversation}/session-header/chat-session-project-dialog.tsx +2 -2
  138. package/src/features/chat/components/layout/chat-page-shell.test.tsx +61 -0
  139. package/src/{components/chat → features/chat/components/layout}/chat-page-shell.tsx +14 -17
  140. package/src/features/chat/components/layout/chat-sidebar-session-entry.tsx +82 -0
  141. package/src/features/chat/components/layout/chat-sidebar-toolbar.tsx +205 -0
  142. package/src/{components/chat/ChatSidebar.test.tsx → features/chat/components/layout/chat-sidebar.test.tsx} +59 -16
  143. package/src/features/chat/components/layout/chat-sidebar.tsx +415 -0
  144. package/src/{components/chat/presenter/chat-presenter-context.tsx → features/chat/components/providers/chat-presenter.provider.tsx} +10 -31
  145. package/src/{components/common → features/chat/components/session}/session-context-icon.tsx +5 -5
  146. package/src/{components/common/SessionRunBadge.tsx → features/chat/components/session/session-run-badge.tsx} +3 -3
  147. package/src/{components/chat → features/chat/components}/workspace/chat-session-workspace-file-breadcrumbs.tsx +5 -15
  148. package/src/{components/chat/chat-input/chat-input-bar.controller.test.tsx → features/chat/hooks/use-chat-input-bar-controller.test.tsx} +1 -1
  149. package/src/{components → features}/chat/hooks/use-chat-session-label.ts +3 -4
  150. package/src/{components → features}/chat/hooks/use-chat-session-project.test.tsx +19 -19
  151. package/src/features/chat/hooks/use-chat-session-project.ts +34 -0
  152. package/src/{components/chat/useChatSessionTypeState.test.tsx → features/chat/hooks/use-chat-session-type-state.test.tsx} +2 -2
  153. package/src/{components/chat/useChatSessionTypeState.ts → features/chat/hooks/use-chat-session-type-state.ts} +3 -16
  154. package/src/{components → features}/chat/hooks/use-chat-session-update.test.tsx +19 -21
  155. package/src/{components → features}/chat/hooks/use-chat-session-update.ts +5 -7
  156. package/src/features/chat/hooks/use-chat-sidebar-session-label-editor.ts +49 -0
  157. package/src/{components/chat/useHydratedNcpAgent.test.tsx → features/chat/hooks/use-hydrated-ncp-agent.test.tsx} +2 -2
  158. package/src/{components/chat/useNcpAgentRuntime.test.tsx → features/chat/hooks/use-ncp-agent-runtime.test.tsx} +1 -1
  159. package/src/{components/chat/ncp/page/ncp-chat-derived-state.ts → features/chat/hooks/use-ncp-chat-derived-state.ts} +8 -8
  160. package/src/{components/chat/ncp/ncp-chat-page-data.ts → features/chat/hooks/use-ncp-chat-page-data.ts} +137 -80
  161. package/src/{hooks → features/chat/hooks}/use-ncp-chat-session-types.ts +1 -1
  162. package/src/{components/chat/ncp/session-conversation → features/chat/hooks}/use-ncp-child-session-tabs-view.ts +7 -7
  163. package/src/{components/chat/ncp/session-conversation → features/chat/hooks}/use-ncp-session-conversation.test.tsx +55 -7
  164. package/src/features/chat/hooks/use-ncp-session-conversation.ts +121 -0
  165. package/src/{components/chat/ncp → features/chat/hooks}/use-ncp-session-list-view.ts +6 -6
  166. package/src/features/chat/index.ts +6 -0
  167. package/src/{components/chat → features/chat/managers}/chat-recent-models.manager.ts +1 -1
  168. package/src/{components/chat → features/chat/managers}/chat-recent-skills.manager.ts +1 -1
  169. package/src/{components → features}/chat/managers/chat-session-list.manager.test.ts +11 -7
  170. package/src/{components → features}/chat/managers/chat-session-list.manager.ts +8 -10
  171. package/src/{components/chat/chat-session-preference-sync.test.ts → features/chat/managers/chat-session-preference-sync.manager.test.ts} +18 -14
  172. package/src/{components/chat/chat-session-preference-sync.ts → features/chat/managers/chat-session-preference-sync.manager.ts} +7 -14
  173. package/src/{components → features}/chat/managers/chat-stream-actions.manager.ts +3 -2
  174. package/src/{components → features}/chat/managers/chat-ui.manager.ts +11 -3
  175. package/src/{components/chat/ncp/tests → features/chat/managers}/ncp-chat-input.manager.test.ts +55 -5
  176. package/src/{components/chat/ncp → features/chat/managers}/ncp-chat-input.manager.ts +28 -20
  177. package/src/{components/chat/ncp/ncp-chat.presenter.ts → features/chat/managers/ncp-chat-presenter.manager.ts} +5 -5
  178. package/src/{components/chat/ncp/tests → features/chat/managers}/ncp-chat-thread.manager.test.ts +11 -10
  179. package/src/{components/chat/ncp → features/chat/managers}/ncp-chat-thread.manager.ts +11 -13
  180. package/src/{lib → features/chat/managers}/recent-selection.manager.test.ts +1 -1
  181. package/src/{lib → features/chat/managers}/recent-selection.manager.ts +14 -14
  182. package/src/features/chat/pages/chat-page.tsx +6 -0
  183. package/src/{components/chat/chat-page-runtime.test.ts → features/chat/pages/ncp-chat-page.test.ts} +69 -4
  184. package/src/{components/chat/ncp → features/chat/pages}/ncp-chat-page.tsx +180 -109
  185. package/src/features/chat/pages/sessions-config-page.test.tsx +152 -0
  186. package/src/features/chat/pages/sessions-config-page.tsx +192 -0
  187. package/src/{components → features}/chat/stores/chat-input.store.ts +3 -3
  188. package/src/{components → features}/chat/stores/chat-session-list.store.ts +2 -4
  189. package/src/{components → features}/chat/stores/chat-thread.store.ts +3 -3
  190. package/src/features/chat/types/chat-input-bar.types.ts +44 -0
  191. package/src/{components/chat → features/chat/types}/chat-input.types.ts +1 -1
  192. package/src/features/chat/types/chat-message.types.ts +58 -0
  193. package/src/{components/chat/chat-stream/types.ts → features/chat/types/chat-stream.types.ts} +1 -1
  194. package/src/{components/chat/chat-composer-state.test.ts → features/chat/utils/chat-composer-state.utils.test.ts} +1 -1
  195. package/src/{components/chat/chat-composer-state.ts → features/chat/utils/chat-composer-state.utils.ts} +17 -19
  196. package/src/features/chat/utils/chat-inline-token.utils.test.ts +87 -0
  197. package/src/{components/chat → features/chat/utils}/chat-inline-token.utils.ts +22 -39
  198. package/src/{components/chat/adapters/chat-input-bar.adapter.test.ts → features/chat/utils/chat-input-bar.utils.test.ts} +2 -2
  199. package/src/{components/chat/adapters/chat-input-bar.adapter.ts → features/chat/utils/chat-input-bar.utils.ts} +18 -196
  200. package/src/features/chat/utils/chat-input-toolbar.utils.ts +191 -0
  201. package/src/{lib/chat-message.ts → features/chat/utils/chat-message-core.utils.ts} +1 -1
  202. package/src/{components/chat/adapters/chat-message-inline-content.adapter.ts → features/chat/utils/chat-message-inline-content.utils.ts} +2 -2
  203. package/src/features/chat/utils/chat-message-part.utils.ts +233 -0
  204. package/src/{components/chat/adapters/chat-message.session-request-tool-card.ts → features/chat/utils/chat-message-session-request-tool-card.utils.ts} +2 -2
  205. package/src/{components/chat/adapters/chat-message.session-spawn-tool-card.test.ts → features/chat/utils/chat-message-session-spawn-tool-card.utils.test.ts} +2 -2
  206. package/src/{components/chat/adapters/chat-message.summary-truncation.test.ts → features/chat/utils/chat-message-summary-truncation.utils.test.ts} +2 -2
  207. package/src/{components/chat/adapters/chat-message-tool-agent-id.test.ts → features/chat/utils/chat-message-tool-agent-id.utils.test.ts} +1 -1
  208. package/src/features/chat/utils/chat-message-tool-card.utils.ts +216 -0
  209. package/src/{components/chat/adapters/chat-message.adapter.test.ts → features/chat/utils/chat-message.utils.test.ts} +2 -2
  210. package/src/{components/chat/adapters/chat-message.adapter.ts → features/chat/utils/chat-message.utils.ts} +4 -4
  211. package/src/features/chat/utils/chat-runtime.utils.ts +235 -0
  212. package/src/{components/chat/chat-session-display.test.ts → features/chat/utils/chat-session-display.utils.test.ts} +2 -2
  213. package/src/{components/chat/chat-session-display.ts → features/chat/utils/chat-session-display.utils.ts} +5 -9
  214. package/src/{components/chat/chat-session-preference-governance.ts → features/chat/utils/chat-session-preference-governance.utils.ts} +51 -64
  215. package/src/{components/chat/chat-session-route.ts → features/chat/utils/chat-session-route.utils.ts} +1 -1
  216. package/src/{components/chat/adapters/file-operation/card.ts → features/chat/utils/file-operation/card.utils.ts} +3 -3
  217. package/src/{components/chat/adapters/file-operation/diff.ts → features/chat/utils/file-operation/diff.utils.ts} +9 -99
  218. package/src/features/chat/utils/file-operation/parsed-block.utils.ts +98 -0
  219. package/src/{components/chat/adapters/file-operation/record-readers.ts → features/chat/utils/file-operation/record-readers.utils.ts} +1 -1
  220. package/src/{components/chat/ncp/ncp-app-client-fetch.test.ts → features/chat/utils/ncp-app-client-fetch.utils.test.ts} +1 -1
  221. package/src/{components/chat/ncp/ncp-app-client-fetch.ts → features/chat/utils/ncp-app-client-fetch.utils.ts} +3 -0
  222. package/src/features/chat/utils/ncp-chat-input-availability.utils.test.ts +92 -0
  223. package/src/features/chat/utils/ncp-chat-input-availability.utils.ts +45 -0
  224. package/src/{components/chat/ncp/__tests__/ncp-session-adapter.cancelled-tool.test.ts → features/chat/utils/ncp-session-adapter.utils.cancelled-tool.test.ts} +2 -2
  225. package/src/{components/chat/ncp/ncp-session-adapter.test.ts → features/chat/utils/ncp-session-adapter.utils.test.ts} +3 -3
  226. package/src/{components/chat/ncp/ncp-session-adapter.ts → features/chat/utils/ncp-session-adapter.utils.ts} +3 -3
  227. package/src/{lib → features/chat/utils}/session-context.utils.test.ts +3 -3
  228. package/src/{lib → features/chat/utils}/session-context.utils.ts +3 -3
  229. package/src/{components/marketplace → features/marketplace/components}/marketplace-list-card.tsx +69 -124
  230. package/src/{components/marketplace → features/marketplace/components}/marketplace-localization.ts +1 -1
  231. package/src/{components/marketplace → features/marketplace/components}/marketplace-page-data.ts +2 -2
  232. package/src/features/marketplace/components/marketplace-page-detail.test.tsx +336 -0
  233. package/src/features/marketplace/components/marketplace-page-parts.tsx +121 -0
  234. package/src/{components/marketplace → features/marketplace/components}/marketplace-page.test.tsx +6 -6
  235. package/src/{components/marketplace → features/marketplace/components}/marketplace-page.tsx +92 -91
  236. package/src/{components/marketplace → features/marketplace/components}/mcp/mcp-marketplace-card.tsx +4 -4
  237. package/src/{components/marketplace → features/marketplace/components}/mcp/mcp-marketplace-dialogs.tsx +7 -7
  238. package/src/{components/marketplace → features/marketplace/components}/mcp/mcp-marketplace-doc.ts +3 -3
  239. package/src/{components/marketplace → features/marketplace/components}/mcp/mcp-marketplace-page.test.tsx +13 -9
  240. package/src/features/marketplace/components/mcp/mcp-marketplace-page.tsx +446 -0
  241. package/src/{hooks/useMarketplace.ts → features/marketplace/hooks/use-marketplace.ts} +5 -5
  242. package/src/{hooks/useMcpMarketplace.ts → features/marketplace/hooks/use-mcp-marketplace.ts} +3 -3
  243. package/src/features/marketplace/index.ts +26 -0
  244. package/src/{components/marketplace/marketplace-installed-cache.test.ts → features/marketplace/utils/marketplace-installed-cache.utils.test.ts} +2 -2
  245. package/src/{components/marketplace/marketplace-installed-cache.ts → features/marketplace/utils/marketplace-installed-cache.utils.ts} +1 -1
  246. package/src/{hooks/marketplace-list-pages.ts → features/marketplace/utils/marketplace-list-pages.utils.ts} +1 -1
  247. package/src/{pwa → features/pwa}/components/pwa-install-entry.test.tsx +2 -2
  248. package/src/{pwa → features/pwa}/components/pwa-install-entry.tsx +7 -7
  249. package/src/features/pwa/index.ts +4 -0
  250. package/src/{pwa/register-pwa.ts → features/pwa/managers/pwa-bootstrap.manager.ts} +2 -2
  251. package/src/{pwa → features/pwa}/managers/pwa-install.manager.test.ts +3 -3
  252. package/src/{pwa → features/pwa}/managers/pwa-install.manager.ts +5 -5
  253. package/src/{pwa → features/pwa}/managers/pwa-runtime.manager.ts +1 -1
  254. package/src/{pwa → features/pwa}/managers/pwa-shell-theme.manager.test.ts +1 -1
  255. package/src/{pwa → features/pwa}/managers/pwa-shell-theme.manager.ts +1 -1
  256. package/src/{pwa → features/pwa}/stores/pwa.store.ts +2 -2
  257. package/src/{components/remote → features/remote/components}/remote-access-page.test.tsx +5 -6
  258. package/src/{components/remote → features/remote/components}/remote-access-page.tsx +21 -19
  259. package/src/{hooks/useRemoteAccess.ts → features/remote/hooks/use-remote-access.ts} +3 -3
  260. package/src/features/remote/index.ts +27 -0
  261. package/src/{remote → features/remote}/managers/remote-access.manager.ts +6 -7
  262. package/src/{remote → features/remote/services}/remote-access-feedback.service.test.ts +3 -3
  263. package/src/{remote → features/remote/services}/remote-access-feedback.service.ts +2 -2
  264. package/src/{remote/remote-access.query.ts → features/remote/services/remote-access-query.service.ts} +2 -2
  265. package/src/{remote → features/remote}/stores/remote-access.store.ts +1 -1
  266. package/src/features/settings/hooks/use-language-preference.ts +30 -0
  267. package/src/features/settings/index.ts +2 -0
  268. package/src/features/settings/pages/language-settings-page.test.tsx +36 -0
  269. package/src/features/settings/pages/language-settings-page.tsx +56 -0
  270. package/src/features/system-status/components/config/runtime-agent-list-card.tsx +72 -0
  271. package/src/features/system-status/components/config/runtime-binding-list-card.tsx +85 -0
  272. package/src/features/system-status/components/config/runtime-config-editor.tsx +131 -0
  273. package/src/features/system-status/components/config/runtime-config-overview.tsx +16 -0
  274. package/src/features/system-status/components/config/runtime-entry-list-card.tsx +58 -0
  275. package/src/features/system-status/components/config/runtime-settings-card.tsx +73 -0
  276. package/src/{components/config → features/system-status/components}/desktop-update-config.test.tsx +12 -6
  277. package/src/features/system-status/components/desktop-update-config.tsx +219 -0
  278. package/src/features/system-status/components/runtime-control-card.test.tsx +213 -0
  279. package/src/features/system-status/components/runtime-control-card.tsx +260 -0
  280. package/src/{components/config → features/system-status/components}/runtime-presence-card.test.tsx +12 -16
  281. package/src/{components/config → features/system-status/components}/runtime-presence-card.tsx +38 -51
  282. package/src/features/system-status/components/runtime-security-card.tsx +263 -0
  283. package/src/{components/config → features/system-status/components}/security-config.tsx +3 -3
  284. package/src/features/system-status/hooks/use-system-status.ts +104 -0
  285. package/src/features/system-status/index.ts +4 -0
  286. package/src/features/system-status/managers/system-status.manager.bootstrap-polling.test.ts +126 -0
  287. package/src/features/system-status/managers/system-status.manager.test.ts +142 -0
  288. package/src/features/system-status/managers/system-status.manager.ts +511 -0
  289. package/src/features/system-status/pages/runtime-config-page.test.tsx +140 -0
  290. package/src/features/system-status/pages/runtime-config-page.tsx +15 -0
  291. package/src/features/system-status/stores/system-status.store.ts +32 -0
  292. package/src/features/system-status/types/system-status.types.ts +73 -0
  293. package/src/features/system-status/utils/runtime-config-agent.utils.ts +152 -0
  294. package/src/features/system-status/utils/system-status.utils.test.ts +132 -0
  295. package/src/features/system-status/utils/system-status.utils.ts +202 -0
  296. package/src/index.css +1 -1
  297. package/src/platforms/desktop/components/desktop-app-shell.tsx +52 -0
  298. package/src/platforms/desktop/index.ts +21 -0
  299. package/src/{desktop → platforms/desktop}/managers/desktop-presence.manager.ts +3 -3
  300. package/src/{desktop → platforms/desktop}/managers/desktop-update.manager.ts +3 -3
  301. package/src/{desktop → platforms/desktop}/stores/desktop-presence.store.ts +1 -1
  302. package/src/{desktop → platforms/desktop}/stores/desktop-update.store.ts +1 -1
  303. package/src/{desktop → platforms/desktop/types}/desktop-update.types.ts +4 -0
  304. package/src/platforms/mobile/components/chat-mobile-shell.tsx +20 -0
  305. package/src/platforms/mobile/components/mobile-app-shell.test.tsx +42 -0
  306. package/src/platforms/mobile/components/mobile-app-shell.tsx +48 -0
  307. package/src/platforms/mobile/components/mobile-bottom-nav.test.tsx +45 -0
  308. package/src/platforms/mobile/components/mobile-bottom-nav.tsx +71 -0
  309. package/src/platforms/mobile/components/mobile-settings-shell.tsx +39 -0
  310. package/src/platforms/mobile/components/mobile-topbar.tsx +41 -0
  311. package/src/platforms/mobile/index.ts +3 -0
  312. package/src/shared/components/__tests__/config-split-page.test.tsx +47 -0
  313. package/src/{components/common/AgentAvatar.tsx → shared/components/common/agent-avatar.tsx} +1 -1
  314. package/src/{components → shared/components}/common/agent-identity/agent-identity-avatar.tsx +2 -2
  315. package/src/shared/components/common/agent-identity/index.ts +3 -0
  316. package/src/{components → shared/components}/common/agent-identity/use-agent-identity.ts +3 -3
  317. package/src/{components/common/BrandHeader.tsx → shared/components/common/brand-header.tsx} +2 -2
  318. package/src/{components/common/KeyValueEditor.tsx → shared/components/common/key-value-editor.tsx} +4 -4
  319. package/src/{components/common/LogoBadge.tsx → shared/components/common/logo-badge.tsx} +1 -1
  320. package/src/{components/common/MaskedInput.tsx → shared/components/common/masked-input.tsx} +3 -3
  321. package/src/{components/common/ProviderScopedModelInput.tsx → shared/components/common/provider-scoped-model-input.tsx} +6 -6
  322. package/src/{components/common/SearchableModelInput.tsx → shared/components/common/searchable-model-input.tsx} +2 -2
  323. package/src/{components/common/StatusBadge.tsx → shared/components/common/status-badge.tsx} +3 -3
  324. package/src/{components → shared/components}/common/tag-input.tsx +3 -3
  325. package/src/{components → shared/components}/config/provider-form-support.ts +3 -3
  326. package/src/{components/config/ProviderForm.tsx → shared/components/config/provider-form.tsx} +14 -14
  327. package/src/{components → shared/components}/config/provider-models-section.tsx +7 -7
  328. package/src/{components → shared/components}/config/providers-list.test.tsx +19 -19
  329. package/src/{components/config/ProvidersList.tsx → shared/components/config/providers-list.tsx} +56 -54
  330. package/src/shared/components/config/secrets-config-form.tsx +407 -0
  331. package/src/shared/components/config/secrets-config.test.tsx +90 -0
  332. package/src/shared/components/config/secrets-config.tsx +25 -0
  333. package/src/{components/config → shared/components}/config-split-page.tsx +55 -9
  334. package/src/{components/config/CronConfig.tsx → shared/components/cron-config.tsx} +63 -96
  335. package/src/shared/components/doc-browser/doc-browser-context.test.tsx +102 -0
  336. package/src/{components/doc-browser/DocBrowserContext.tsx → shared/components/doc-browser/doc-browser-context.tsx} +98 -45
  337. package/src/shared/components/doc-browser/doc-browser.test.tsx +72 -0
  338. package/src/{components/doc-browser/DocBrowser.tsx → shared/components/doc-browser/doc-browser.tsx} +60 -34
  339. package/src/shared/components/doc-browser/index.ts +3 -0
  340. package/src/{components/doc-browser/useDocLinkInterceptor.ts → shared/components/doc-browser/use-doc-link-interceptor.ts} +1 -1
  341. package/src/{components/config/ModelConfig.test.tsx → shared/components/model-config.test.tsx} +4 -4
  342. package/src/shared/components/model-config.tsx +151 -0
  343. package/src/{components → shared/components}/path-picker/server-path-picker-dialog.test.tsx +3 -3
  344. package/src/{components → shared/components}/path-picker/server-path-picker-dialog.tsx +7 -7
  345. package/src/{components/config → shared/components}/provider-advanced-settings-section.tsx +5 -18
  346. package/src/{components/config → shared/components}/provider-auth-section.tsx +7 -24
  347. package/src/{components/config → shared/components}/provider-enabled-field.tsx +4 -8
  348. package/src/{components/config → shared/components}/provider-pill-selector.tsx +3 -15
  349. package/src/{components/config → shared/components}/provider-status-badge.tsx +3 -9
  350. package/src/{components/config/SearchConfig.test.tsx → shared/components/search-config.test.tsx} +3 -3
  351. package/src/shared/components/search-config.tsx +496 -0
  352. package/src/{components → shared/components}/ui/action-link.tsx +1 -1
  353. package/src/{components → shared/components}/ui/button.tsx +1 -1
  354. package/src/{components → shared/components}/ui/card.tsx +1 -1
  355. package/src/{components → shared/components}/ui/config-card.tsx +1 -1
  356. package/src/{components → shared/components}/ui/confirm-dialog.tsx +3 -3
  357. package/src/{components → shared/components}/ui/dialog.tsx +1 -1
  358. package/src/{components/ui/HighlightCard.tsx → shared/components/ui/highlight-card.tsx} +1 -1
  359. package/src/{components → shared/components}/ui/input.tsx +1 -1
  360. package/src/{components → shared/components}/ui/label.tsx +1 -1
  361. package/src/{components → shared/components}/ui/notice-card.tsx +1 -1
  362. package/src/{components → shared/components}/ui/popover.tsx +1 -1
  363. package/src/{components → shared/components}/ui/scroll-area.tsx +1 -1
  364. package/src/{components → shared/components}/ui/select.tsx +1 -1
  365. package/src/{components → shared/components}/ui/setting-row.tsx +1 -1
  366. package/src/{components → shared/components}/ui/skeleton.tsx +1 -1
  367. package/src/{components → shared/components}/ui/status-dot.tsx +1 -1
  368. package/src/{components → shared/components}/ui/switch.tsx +1 -1
  369. package/src/{components → shared/components}/ui/tabs-custom.tsx +2 -2
  370. package/src/{components → shared/components}/ui/tabs.tsx +1 -1
  371. package/src/{components → shared/components}/ui/tag-chip.tsx +1 -1
  372. package/src/{components → shared/components}/ui/textarea.tsx +1 -1
  373. package/src/{components → shared/components}/ui/tooltip.tsx +1 -1
  374. package/src/{hooks/agents/useAgents.ts → shared/hooks/use-agents.ts} +2 -2
  375. package/src/{hooks/useConfig.ts → shared/hooks/use-config.ts} +4 -4
  376. package/src/{hooks/useConfirmDialog.tsx → shared/hooks/use-confirm-dialog.tsx} +2 -2
  377. package/src/{hooks/server-path → shared/hooks}/use-server-path-browse.ts +1 -1
  378. package/src/{hooks/server-path → shared/hooks}/use-server-path-read.ts +1 -1
  379. package/src/{api → shared/lib/api}/api-base.test.ts +2 -2
  380. package/src/{api → shared/lib/api}/client.test.ts +2 -2
  381. package/src/{api → shared/lib/api}/client.ts +1 -1
  382. package/src/{api → shared/lib/api}/config.ts +10 -0
  383. package/src/shared/lib/api/index.ts +20 -0
  384. package/src/{api → shared/lib/api}/ncp-session-query-cache.test.ts +2 -2
  385. package/src/{api → shared/lib/api}/ncp-session-query-cache.ts +1 -1
  386. package/src/{api → shared/lib/api}/ncp-session.test.ts +3 -3
  387. package/src/{api → shared/lib/api}/raw-client.test.ts +1 -1
  388. package/src/{api/raw-client.ts → shared/lib/api/raw-client.utils.ts} +2 -0
  389. package/src/{api → shared/lib/api}/types.ts +40 -0
  390. package/src/{lib → shared/lib/app-resource-uri}/app-resource-uri.test.ts +1 -1
  391. package/src/{lib/config-hints.ts → shared/lib/config-hints/index.ts} +1 -1
  392. package/src/{lib/i18n.chat.ts → shared/lib/i18n/chat.ts} +8 -0
  393. package/src/{lib/i18n.ts → shared/lib/i18n/index.ts} +11 -11
  394. package/src/shared/lib/i18n/runtime/i18n-language-owner.test.ts +94 -0
  395. package/src/{lib/i18n-runtime → shared/lib/i18n/runtime}/i18n-language-owner.ts +15 -1
  396. package/src/{lib/provider-models.ts → shared/lib/provider-models/index.ts} +1 -1
  397. package/src/shared/lib/session-project/index.ts +2 -0
  398. package/src/{lib → shared/lib}/session-project/workspace-file-breadcrumb.test.ts +1 -1
  399. package/src/{lib → shared/lib}/session-project/workspace-file-breadcrumb.ts +1 -1
  400. package/src/{transport/app-client.ts → shared/lib/transport/app-client.service.ts} +11 -12
  401. package/src/{transport → shared/lib/transport}/app-client.test.ts +15 -5
  402. package/src/{transport → shared/lib/transport}/index.ts +1 -1
  403. package/src/{transport/local.transport.ts → shared/lib/transport/local-transport.service.ts} +19 -19
  404. package/src/{transport/remote.transport.ts → shared/lib/transport/remote-transport.service.ts} +14 -15
  405. package/src/{transport → shared/lib/transport}/remote.transport.test.ts +5 -5
  406. package/src/{transport → shared/lib/transport}/sse-stream.test.ts +2 -2
  407. package/src/{transport/sse-stream.ts → shared/lib/transport/sse-stream.utils.ts} +13 -11
  408. package/src/{transport → shared/lib/transport}/transport.types.ts +1 -1
  409. package/src/{lib/ui-document-title.ts → shared/lib/ui-document-title/index.ts} +1 -1
  410. package/tsconfig.json +20 -0
  411. package/vite.config.ts +62 -2
  412. package/vitest.config.ts +21 -1
  413. package/dist/assets/ChannelsList-M9FTK1Ak.js +0 -8
  414. package/dist/assets/DocBrowser-CH7-GxlL.js +0 -1
  415. package/dist/assets/DocBrowser-DMfr0Oow.js +0 -1
  416. package/dist/assets/DocBrowserContext-BXydqby-.js +0 -1
  417. package/dist/assets/ModelConfig-CNIgLf0e.js +0 -1
  418. package/dist/assets/ProviderScopedModelInput-B3HWP4oz.js +0 -1
  419. package/dist/assets/ProvidersList-CHjMnRhX.js +0 -1
  420. package/dist/assets/RuntimeConfig-psp8nMSG.js +0 -1
  421. package/dist/assets/SearchConfig-CSoKip1f.js +0 -1
  422. package/dist/assets/SecretsConfig-MEt6MjuD.js +0 -3
  423. package/dist/assets/SessionsConfig-DifCiXwR.js +0 -2
  424. package/dist/assets/app-query-client-9jNewezV.js +0 -1
  425. package/dist/assets/chat-page-CLp0UV0Y.js +0 -58
  426. package/dist/assets/chat-session-display-DsYHx0RZ.js +0 -1
  427. package/dist/assets/chunk-JZWAC4HX-C5dEc8hV.js +0 -3
  428. package/dist/assets/client-C-8fH7-c.js +0 -7
  429. package/dist/assets/config-CBScxsdV.js +0 -1
  430. package/dist/assets/config-split-page-BUout_Ak.js +0 -1
  431. package/dist/assets/desktop-update-config-2BS6BMkW.js +0 -1
  432. package/dist/assets/dist-BruyLa92.js +0 -9
  433. package/dist/assets/download-BD0ETkB-.js +0 -1
  434. package/dist/assets/i18n-CpTZLchQ.js +0 -1
  435. package/dist/assets/index-mW8W2FUu.css +0 -1
  436. package/dist/assets/index-zDZfXoI4.js +0 -6
  437. package/dist/assets/infiniteQueryBehavior-CyER9hv0.js +0 -1
  438. package/dist/assets/loader-circle-Bc2gCU33.js +0 -1
  439. package/dist/assets/marketplace-page-3qVMnF3d.js +0 -1
  440. package/dist/assets/marketplace-page-BhFIeQzI.js +0 -49
  441. package/dist/assets/mcp-marketplace-page-DYfteJ1D.js +0 -40
  442. package/dist/assets/page-layout-0UcO9H9Z.js +0 -1
  443. package/dist/assets/play-CKDjSQFL.js +0 -1
  444. package/dist/assets/plus-CG0QrVY_.js +0 -1
  445. package/dist/assets/refresh-cw-Bcv40SXy.js +0 -1
  446. package/dist/assets/remote-access-page-CWHG-sug.js +0 -1
  447. package/dist/assets/search-BCAlB8nz.js +0 -1
  448. package/dist/assets/security-config-Slh0Mayz.js +0 -1
  449. package/dist/assets/select-CVz0t7MF.js +0 -41
  450. package/dist/assets/setting-row-CbVHAuQt.js +0 -1
  451. package/dist/assets/skeleton-D5rdKvzy.js +0 -1
  452. package/dist/assets/switch-CM29eCAR.js +0 -1
  453. package/dist/assets/tag-chip-DMXdnLcj.js +0 -1
  454. package/dist/assets/use-infinite-scroll-loader-DJ1L81Dz.js +0 -1
  455. package/dist/assets/useConfirmDialog-BsVuqu1x.js +0 -1
  456. package/dist/assets/useMutation-CNcz2fgt.js +0 -1
  457. package/dist/assets/x-Czwxm82I.js +0 -1
  458. package/src/app.tsx +0 -271
  459. package/src/components/chat/ChatSidebar.tsx +0 -486
  460. package/src/components/chat/README.md +0 -2
  461. package/src/components/chat/adapters/chat-message-part.adapter.ts +0 -472
  462. package/src/components/chat/chat-inline-token.utils.test.ts +0 -87
  463. package/src/components/chat/chat-page.tsx +0 -6
  464. package/src/components/chat/chat-sidebar-list-mode-switch.tsx +0 -43
  465. package/src/components/chat/hooks/use-chat-session-project.ts +0 -35
  466. package/src/components/chat/index.ts +0 -1
  467. package/src/components/chat/ncp/README.md +0 -3
  468. package/src/components/chat/ncp/ncp-chat-page-data.test.ts +0 -79
  469. package/src/components/chat/ncp/session-conversation/use-ncp-session-conversation.ts +0 -72
  470. package/src/components/chat/nextclaw/index.ts +0 -23
  471. package/src/components/common/agent-identity/index.ts +0 -3
  472. package/src/components/config/ChannelForm.tsx +0 -338
  473. package/src/components/config/ChannelsList.test.tsx +0 -309
  474. package/src/components/config/ModelConfig.tsx +0 -156
  475. package/src/components/config/README.md +0 -2
  476. package/src/components/config/RuntimeConfig.tsx +0 -588
  477. package/src/components/config/SearchConfig.tsx +0 -513
  478. package/src/components/config/SecretsConfig.tsx +0 -469
  479. package/src/components/config/SessionsConfig.tsx +0 -437
  480. package/src/components/config/desktop-update-config.tsx +0 -271
  481. package/src/components/config/runtime-config-agent.utils.ts +0 -96
  482. package/src/components/config/runtime-control-card.test.tsx +0 -311
  483. package/src/components/config/runtime-control-card.tsx +0 -326
  484. package/src/components/config/runtime-security-card.tsx +0 -276
  485. package/src/components/config/weixin-channel-auth-section.tsx +0 -305
  486. package/src/components/doc-browser/index.ts +0 -3
  487. package/src/components/layout/AppLayout.tsx +0 -82
  488. package/src/components/layout/runtime-status-entry.test.tsx +0 -157
  489. package/src/components/layout/runtime-status-entry.tsx +0 -143
  490. package/src/components/marketplace/marketplace-page-parts.tsx +0 -94
  491. package/src/components/marketplace/mcp/mcp-marketplace-page.tsx +0 -414
  492. package/src/hooks/README.md +0 -3
  493. package/src/hooks/use-runtime-control.ts +0 -24
  494. package/src/hooks/useObservable.ts +0 -20
  495. package/src/lib/chat-runtime-utils.ts +0 -250
  496. package/src/presenter/app-presenter-context.tsx +0 -20
  497. package/src/presenter/app.presenter.ts +0 -12
  498. package/src/runtime-control/runtime-control.manager.ts +0 -118
  499. package/src/stores/ui.store.ts +0 -23
  500. /package/dist/assets/{config-hints-BhTmc9P1.js → config-hints-CPNzbMEp.js} +0 -0
  501. /package/src/{components/layout/Header.tsx → app/components/layout/header.tsx} +0 -0
  502. /package/src/{styles → app/styles}/design-system.css +0 -0
  503. /package/src/{account → features/account}/stores/account.store.ts +0 -0
  504. /package/src/{components/chat/chat-input/chat-input-bar.controller.ts → features/chat/hooks/use-chat-input-bar-controller.ts} +0 -0
  505. /package/src/{lib/session-run-status.ts → features/chat/types/session-run-status.types.ts} +0 -0
  506. /package/src/{components/chat/adapters/chat-message.partial-json.ts → features/chat/utils/chat-message-partial-json.utils.ts} +0 -0
  507. /package/src/{components/chat/adapters/chat-message-tool-agent-id.ts → features/chat/utils/chat-message-tool-agent-id.utils.ts} +0 -0
  508. /package/src/{components/chat/adapters/file-operation/line-builder.ts → features/chat/utils/file-operation/line-builder.utils.ts} +0 -0
  509. /package/src/{components/marketplace → features/marketplace/components}/marketplace-detail-doc.ts +0 -0
  510. /package/src/{pwa → features/pwa/types}/pwa.types.ts +0 -0
  511. /package/src/{pwa/pwa-install-banner.storage.ts → features/pwa/utils/pwa-install-banner.utils.ts} +0 -0
  512. /package/src/{hooks → shared/hooks}/use-infinite-scroll-loader.ts +0 -0
  513. /package/src/{api → shared/lib/api}/agents.ts +0 -0
  514. /package/src/{api → shared/lib/api}/api-base.ts +0 -0
  515. /package/src/{api → shared/lib/api}/auth.types.ts +0 -0
  516. /package/src/{api → shared/lib/api}/channel-auth.ts +0 -0
  517. /package/src/{api → shared/lib/api}/channel-auth.types.ts +0 -0
  518. /package/src/{api → shared/lib/api}/chat-session-type.types.ts +0 -0
  519. /package/src/{api → shared/lib/api}/marketplace.ts +0 -0
  520. /package/src/{api → shared/lib/api}/mcp-marketplace.ts +0 -0
  521. /package/src/{api → shared/lib/api}/ncp-attachments.ts +0 -0
  522. /package/src/{api → shared/lib/api}/ncp-session.ts +0 -0
  523. /package/src/{api → shared/lib/api}/remote.ts +0 -0
  524. /package/src/{api → shared/lib/api}/remote.types.ts +0 -0
  525. /package/src/{api → shared/lib/api}/runtime-control.ts +0 -0
  526. /package/src/{api → shared/lib/api}/runtime-control.types.ts +0 -0
  527. /package/src/{api → shared/lib/api}/server-path.ts +0 -0
  528. /package/src/{lib/app-resource-uri.ts → shared/lib/app-resource-uri/index.ts} +0 -0
  529. /package/src/{lib/i18n.agents.ts → shared/lib/i18n/agents.ts} +0 -0
  530. /package/src/{lib/i18n.channel-auth.ts → shared/lib/i18n/channel-auth.ts} +0 -0
  531. /package/src/{lib/i18n.channels.ts → shared/lib/i18n/channels.ts} +0 -0
  532. /package/src/{lib → shared/lib/i18n}/desktop-update-labels.utils.ts +0 -0
  533. /package/src/{lib/i18n.marketplace.ts → shared/lib/i18n/marketplace.ts} +0 -0
  534. /package/src/{lib/i18n.pwa.ts → shared/lib/i18n/pwa.ts} +0 -0
  535. /package/src/{lib/i18n.remote.ts → shared/lib/i18n/remote.ts} +0 -0
  536. /package/src/{lib/i18n-runtime → shared/lib/i18n/runtime}/i18n.path-picker.ts +0 -0
  537. /package/src/{lib/i18n.runtime-control.ts → shared/lib/i18n/runtime-control.ts} +0 -0
  538. /package/src/{lib/i18n.search.ts → shared/lib/i18n/search.ts} +0 -0
  539. /package/src/{lib/logos.ts → shared/lib/logos/index.ts} +0 -0
  540. /package/src/{lib → shared/lib}/session-project/session-project.utils.ts +0 -0
  541. /package/src/{lib/theme.ts → shared/lib/theme/index.ts} +0 -0
  542. /package/src/{transport/transport-websocket-url.ts → shared/lib/transport/transport-websocket-url.utils.ts} +0 -0
  543. /package/src/{lib/utils.ts → shared/lib/utils/index.ts} +0 -0
@@ -1,24 +1,21 @@
1
1
  import { type ComponentProps, useRef } from "react";
2
- import { ArrowLeft } from "lucide-react";
3
2
  import { useStickyBottomScroll } from "@nextclaw/agent-chat-ui";
4
3
  import type { ChatFileOpenActionViewModel } from "@nextclaw/agent-chat-ui";
4
+ import { ChatInputBarContainer } from "@/features/chat/components/conversation/chat-input-bar.container";
5
+ import { ChatMessageListContainer } from "@/features/chat/components/conversation/chat-message-list.container";
5
6
  import {
6
- ChatInputBarContainer,
7
- ChatMessageListContainer,
8
- } from "@/components/chat/nextclaw";
9
- import { ChatWelcome } from "@/components/chat/ChatWelcome";
10
- import { ChatSessionWorkspacePanel } from "@/components/chat/chat-session-workspace-panel";
11
- import { AgentAvatar } from "@/components/common/AgentAvatar";
12
- import { SessionContextIconNode } from "@/components/common/session-context-icon";
13
- import { usePresenter } from "@/components/chat/presenter/chat-presenter-context";
14
- import { ChatSessionHeaderActions } from "@/components/chat/session-header/chat-session-header-actions";
15
- import { ChatSessionProjectBadge } from "@/components/chat/session-header/chat-session-project-badge";
16
- import { useChatInputStore } from "@/components/chat/stores/chat-input.store";
17
- import { useChatThreadStore } from "@/components/chat/stores/chat-thread.store";
18
- import { Skeleton } from "@/components/ui/skeleton";
19
- import { resolveAgentRuntimeSessionType } from "@/components/chat/useChatSessionTypeState";
20
- import { t } from "@/lib/i18n";
21
- import { cn } from "@/lib/utils";
7
+ ChatConversationHeader,
8
+ ChatParentSessionBanner,
9
+ } from "@/features/chat/components/conversation/chat-conversation-header";
10
+ import { ChatWelcome } from "@/features/chat/components/chat-welcome";
11
+ import { ChatSessionWorkspacePanel } from "@/features/chat";
12
+ import { usePresenter } from "@/features/chat/components/providers/chat-presenter.provider";
13
+ import { resolveAgentRuntimeSessionType } from "@/features/chat/hooks/use-chat-session-type-state";
14
+ import { useChatInputStore } from "@/features/chat/stores/chat-input.store";
15
+ import { useChatThreadStore } from "@/features/chat/stores/chat-thread.store";
16
+ import { Skeleton } from "@/shared/components/ui/skeleton";
17
+ import { t } from "@/shared/lib/i18n";
18
+ import { cn } from "@/shared/lib/utils";
22
19
 
23
20
  const CHAT_CONVERSATION_SKELETON_BUBBLES = [
24
21
  {
@@ -105,9 +102,6 @@ function ChatConversationSkeleton() {
105
102
  }
106
103
 
107
104
  type ChatThreadSnapshot = ReturnType<typeof useChatThreadStore.getState>["snapshot"];
108
- type ChatHeaderDeleteHandler = ComponentProps<
109
- typeof ChatSessionHeaderActions
110
- >["onDeleteSession"];
111
105
  type ChatToolActionHandler = ComponentProps<
112
106
  typeof ChatMessageListContainer
113
107
  >["onToolAction"];
@@ -115,126 +109,12 @@ type ChatFileOpenHandler = ComponentProps<
115
109
  typeof ChatMessageListContainer
116
110
  >["onFileOpen"];
117
111
 
118
- type ChatParentSessionBannerProps = {
119
- parentSessionLabel: string | null;
120
- onGoToParentSession: () => void;
121
- };
122
-
123
- function ChatParentSessionBanner({
124
- parentSessionLabel,
125
- onGoToParentSession,
126
- }: ChatParentSessionBannerProps) {
127
- if (!parentSessionLabel) {
128
- return null;
129
- }
130
- const trimmedLabel = parentSessionLabel.trim();
131
- return (
132
- <div className="border-b border-gray-200/60 bg-white/75 px-5 py-2 backdrop-blur-sm">
133
- <button
134
- type="button"
135
- onClick={onGoToParentSession}
136
- className="inline-flex items-center gap-2 text-xs font-medium text-gray-600 transition-colors hover:text-gray-900"
137
- >
138
- <ArrowLeft className="h-3.5 w-3.5" />
139
- <span>
140
- {t("chatBackToParent")}
141
- {trimmedLabel ? ` · ${trimmedLabel}` : ""}
142
- </span>
143
- </button>
144
- </div>
145
- );
146
- }
147
-
148
- type ChatConversationHeaderProps = {
149
- snapshot: ChatThreadSnapshot;
150
- childSessionCount: number;
151
- normalizedAgentId: string;
152
- sessionHeaderTitle: string;
153
- shouldShowHeaderAgentAvatar: boolean;
154
- shouldShowSessionHeader: boolean;
155
- onOpenChildSessions: () => void;
156
- onDeleteSession: ChatHeaderDeleteHandler;
157
- };
158
-
159
- function ChatConversationHeader({
160
- snapshot,
161
- childSessionCount,
162
- normalizedAgentId,
163
- sessionHeaderTitle,
164
- shouldShowHeaderAgentAvatar,
165
- shouldShowSessionHeader,
166
- onOpenChildSessions,
167
- onDeleteSession,
168
- }: ChatConversationHeaderProps) {
169
- return (
170
- <div
171
- className={cn(
172
- "px-5 border-b border-gray-200/60 bg-white/80 backdrop-blur-sm flex items-center justify-between shrink-0 overflow-hidden transition-all duration-200",
173
- shouldShowSessionHeader ? "py-3 opacity-100" : "h-0 py-0 opacity-0 border-b-0",
174
- )}
175
- >
176
- <div className="min-w-0 flex-1 flex items-center gap-2">
177
- {shouldShowHeaderAgentAvatar ? (
178
- <div className="inline-flex shrink-0 items-center">
179
- <AgentAvatar
180
- agentId={normalizedAgentId}
181
- displayName={snapshot.agentDisplayName}
182
- avatarUrl={snapshot.agentAvatarUrl}
183
- className="h-5 w-5"
184
- />
185
- </div>
186
- ) : null}
187
- <span className="text-sm font-medium text-gray-700 truncate">
188
- {sessionHeaderTitle}
189
- </span>
190
- {snapshot.sessionTypeLabel ? (
191
- <span className="inline-flex shrink-0 items-center gap-1.5 rounded-full border border-gray-200 bg-gray-100 px-2 py-0.5 text-[11px] font-medium text-gray-600">
192
- {snapshot.sessionTypeIcon?.src ? (
193
- <span className="inline-flex h-[1.125rem] w-[1.125rem] items-center justify-center">
194
- <SessionContextIconNode
195
- icon={{
196
- kind: "runtime-image",
197
- src: snapshot.sessionTypeIcon.src,
198
- alt: snapshot.sessionTypeIcon.alt ?? null,
199
- name: snapshot.sessionTypeLabel
200
- }}
201
- />
202
- </span>
203
- ) : null}
204
- {snapshot.sessionTypeLabel}
205
- </span>
206
- ) : null}
207
- {snapshot.sessionProjectName ? (
208
- <ChatSessionProjectBadge
209
- sessionKey={snapshot.sessionKey ?? "draft"}
210
- projectName={snapshot.sessionProjectName}
211
- projectRoot={snapshot.sessionProjectRoot}
212
- persistToServer={snapshot.canDeleteSession}
213
- />
214
- ) : null}
215
- </div>
216
- {snapshot.sessionKey ? (
217
- <ChatSessionHeaderActions
218
- sessionKey={snapshot.sessionKey}
219
- canDeleteSession={snapshot.canDeleteSession}
220
- isDeletePending={snapshot.isDeletePending}
221
- projectRoot={snapshot.sessionProjectRoot}
222
- childSessionCount={childSessionCount}
223
- onOpenChildSessions={onOpenChildSessions}
224
- onDeleteSession={onDeleteSession}
225
- />
226
- ) : null}
227
- </div>
228
- );
229
- }
230
-
231
112
  type ChatConversationAlertsProps = {
232
113
  shouldShowProviderHint: boolean;
233
114
  sessionTypeUnavailable: boolean;
234
115
  sessionTypeUnavailableMessage: string | null;
235
116
  onGoToProviders: () => void;
236
117
  };
237
-
238
118
  function ChatConversationAlerts({
239
119
  shouldShowProviderHint,
240
120
  sessionTypeUnavailable,
@@ -244,7 +124,7 @@ function ChatConversationAlerts({
244
124
  return (
245
125
  <>
246
126
  {shouldShowProviderHint ? (
247
- <div className="px-5 py-2.5 border-b border-amber-200/70 bg-amber-50/70 flex items-center justify-between gap-3 shrink-0">
127
+ <div className="px-4 py-2.5 border-b border-amber-200/70 bg-amber-50/70 flex items-center justify-between gap-3 shrink-0 sm:px-5">
248
128
  <span className="text-xs text-amber-800">
249
129
  {t("chatModelNoOptions")}
250
130
  </span>
@@ -258,7 +138,7 @@ function ChatConversationAlerts({
258
138
  </div>
259
139
  ) : null}
260
140
  {sessionTypeUnavailable && sessionTypeUnavailableMessage?.trim() ? (
261
- <div className="px-5 py-2.5 border-b border-amber-200/70 bg-amber-50/70 shrink-0">
141
+ <div className="px-4 py-2.5 border-b border-amber-200/70 bg-amber-50/70 shrink-0 sm:px-5">
262
142
  <span className="text-xs text-amber-800">
263
143
  {sessionTypeUnavailableMessage}
264
144
  </span>
@@ -280,7 +160,6 @@ type ChatConversationContentProps = {
280
160
  onToolAction: ChatToolActionHandler;
281
161
  onFileOpen: ChatFileOpenHandler;
282
162
  };
283
-
284
163
  function ChatConversationContent({
285
164
  snapshot,
286
165
  availableAgents,
@@ -307,11 +186,11 @@ function ChatConversationContent({
307
186
  onSelectAgent={onSelectAgent}
308
187
  />
309
188
  ) : hideEmptyHint ? null : snapshot.messages.length === 0 ? (
310
- <div className="px-5 py-5 text-sm text-gray-500">
189
+ <div className="px-4 py-4 text-sm text-gray-500 sm:px-5 sm:py-5">
311
190
  {t("chatNoMessages")}
312
191
  </div>
313
192
  ) : (
314
- <div className="mx-auto w-full max-w-[min(1120px,100%)] px-6 py-5">
193
+ <div className="mx-auto w-full max-w-[min(1120px,100%)] px-4 py-4 sm:px-6 sm:py-5">
315
194
  <ChatMessageListContainer
316
195
  key={snapshot.sessionKey ?? "draft"}
317
196
  messages={snapshot.messages}
@@ -336,7 +215,13 @@ function shouldShowWorkspacePanel(
336
215
  return childSessionTabs.length > 0 || workspaceFileTabs.length > 0;
337
216
  }
338
217
 
339
- export function ChatConversationPanel() {
218
+ export function ChatConversationPanel({
219
+ layoutMode = "desktop",
220
+ onBackToList,
221
+ }: {
222
+ layoutMode?: "desktop" | "mobile";
223
+ onBackToList?: () => void;
224
+ }) {
340
225
  const presenter = usePresenter();
341
226
  const defaultSessionType = useChatInputStore(
342
227
  (state) => state.snapshot.defaultSessionType,
@@ -432,10 +317,12 @@ export function ChatConversationPanel() {
432
317
  <ChatConversationHeader
433
318
  snapshot={snapshot}
434
319
  childSessionCount={childSessionTabs.length}
320
+ layoutMode={layoutMode}
435
321
  normalizedAgentId={normalizedAgentId}
436
322
  sessionHeaderTitle={sessionHeaderTitle}
437
323
  shouldShowHeaderAgentAvatar={shouldShowHeaderAgentAvatar}
438
324
  shouldShowSessionHeader={shouldShowSessionHeader}
325
+ onBackToList={onBackToList}
439
326
  onOpenChildSessions={openChildSessions}
440
327
  onDeleteSession={presenter.chatThreadManager.deleteSession}
441
328
  />
@@ -468,6 +355,7 @@ export function ChatConversationPanel() {
468
355
  workspaceFileTabs={workspaceFileTabs}
469
356
  activeWorkspaceFileKey={snapshot.activeWorkspaceFileKey ?? null}
470
357
  sessionProjectRoot={snapshot.sessionProjectRoot ?? null}
358
+ displayMode={layoutMode === "mobile" ? "overlay" : "docked"}
471
359
  onSelectSession={presenter.chatThreadManager.selectChildSessionDetail}
472
360
  onSelectFile={presenter.chatThreadManager.selectWorkspaceFile}
473
361
  onCloseFile={presenter.chatThreadManager.closeWorkspaceFile}
@@ -1,36 +1,21 @@
1
- import { useCallback, useMemo, useRef, useState } from 'react';
1
+ import { useCallback, useMemo, useRef, useState, type ChangeEvent, type RefObject } from 'react';
2
2
  import { ChatInputBar, type ChatInputBarHandle } from '@nextclaw/agent-chat-ui';
3
- import {
4
- DEFAULT_NCP_ATTACHMENT_MAX_BYTES,
5
- uploadFilesAsNcpDraftAttachments
6
- } from '@nextclaw/ncp-react';
7
- import { uploadNcpAssets } from '@/api/ncp-attachments';
8
- import {
9
- buildChatSlashItems,
10
- buildModelStateHint,
11
- buildModelToolbarSelect,
12
- buildSkillPickerModel,
13
- buildThinkingToolbarSelect,
14
- type ChatModelRecord,
15
- type ChatSkillRecord,
16
- type ChatThinkingLevel
17
- } from '@/components/chat/adapters/chat-input-bar.adapter';
18
- import { deriveSelectedSkillsFromComposer } from '@/components/chat/chat-composer-state';
19
- import { usePresenter } from '@/components/chat/presenter/chat-presenter-context';
20
- import {
21
- CHAT_RECENT_MODELS_MIN_OPTIONS,
22
- chatRecentModelsManager
23
- } from '@/components/chat/chat-recent-models.manager';
24
- import {
25
- CHAT_RECENT_SKILLS_MIN_OPTIONS,
26
- chatRecentSkillsManager
27
- } from '@/components/chat/chat-recent-skills.manager';
28
- import { useI18n } from '@/components/providers/I18nProvider';
29
- import { useChatInputStore } from '@/components/chat/stores/chat-input.store';
30
- import type { SessionSkillEntryView } from '@/api/types';
31
- import { t } from '@/lib/i18n';
3
+ import { DEFAULT_NCP_ATTACHMENT_MAX_BYTES, uploadFilesAsNcpDraftAttachments } from '@nextclaw/ncp-react';
4
+ import { uploadNcpAssets } from '@/shared/lib/api';
5
+ import type { SessionSkillEntryView } from '@/shared/lib/api';
6
+ import { buildChatSlashItems, buildModelStateHint, buildModelToolbarSelect, buildSkillPickerModel, buildThinkingToolbarSelect, type ChatModelRecord, type ChatSkillRecord, type ChatThinkingLevel } from '@/features/chat/utils/chat-input-bar.utils';
7
+ import { usePresenter } from '@/features/chat/components/providers/chat-presenter.provider';
8
+ import { useI18n } from '@/app/components/i18n-provider';
9
+ import { useChatInputStore } from '@/features/chat/stores/chat-input.store';
10
+ import { chatRecentModelsManager, CHAT_RECENT_MODELS_MIN_OPTIONS } from '@/features/chat/managers/chat-recent-models.manager';
11
+ import { chatRecentSkillsManager, CHAT_RECENT_SKILLS_MIN_OPTIONS } from '@/features/chat/managers/chat-recent-skills.manager';
12
+ import { deriveSelectedSkillsFromComposer } from '@/features/chat/utils/chat-composer-state.utils';
13
+ import { hasNcpChatModelOptions, isNcpChatComposerDisabled, isNcpChatModelOptionsEmpty, isNcpChatModelOptionsLoading, isNcpChatSendDisabled } from '@/features/chat/utils/ncp-chat-input-availability.utils';
14
+ import { useChatRuntimeAvailability } from '@/features/system-status';
15
+ import { t } from '@/shared/lib/i18n';
32
16
  import { toast } from 'sonner';
33
17
 
18
+ type ChatInputStoreSnapshot = ReturnType<typeof useChatInputStore.getState>['snapshot']; type ChatPresenter = ReturnType<typeof usePresenter>;
34
19
  function buildThinkingLabels(): Record<ChatThinkingLevel, string> {
35
20
  return {
36
21
  off: t('chatThinkingLevelOff'),
@@ -42,7 +27,6 @@ function buildThinkingLabels(): Record<ChatThinkingLevel, string> {
42
27
  xhigh: t('chatThinkingLevelXhigh')
43
28
  };
44
29
  }
45
-
46
30
  function toSkillRecords(
47
31
  snapshotRecords: SessionSkillEntryView[],
48
32
  scopeLabels: Record<SessionSkillEntryView['scope'], string>
@@ -56,7 +40,6 @@ function toSkillRecords(
56
40
  badgeLabel: scopeLabels[record.scope]
57
41
  }));
58
42
  }
59
-
60
43
  function toModelRecords(snapshotModels: Array<{
61
44
  value: string;
62
45
  modelLabel: string;
@@ -78,82 +61,58 @@ function toModelRecords(snapshotModels: Array<{
78
61
  : null
79
62
  }));
80
63
  }
81
-
82
- export function ChatInputBarContainer() {
83
- const presenter = usePresenter();
84
- const { language } = useI18n();
85
- const snapshot = useChatInputStore((state) => state.snapshot);
86
- const [slashQuery, setSlashQuery] = useState<string | null>(null);
87
- const inputBarRef = useRef<ChatInputBarHandle | null>(null);
88
- const fileInputRef = useRef<HTMLInputElement | null>(null);
89
-
64
+ function useChatInputBarLabels(language: string) {
90
65
  const skillScopeLabels = useMemo<Record<'builtin' | 'project' | 'workspace', string>>(() => {
66
+ void language;
91
67
  return {
92
68
  builtin: t('chatSkillScopeBuiltin'),
93
69
  project: t('chatSkillScopeProject'),
94
- workspace: t('chatSkillScopeWorkspace'),
70
+ workspace: t('chatSkillScopeWorkspace')
95
71
  };
96
72
  }, [language]);
97
- const slashTexts = useMemo(
98
- () => {
99
- return {
100
- slashSkillSubtitle: t('chatSlashTypeSkill'),
101
- slashSkillSpecLabel: t('chatSlashSkillSpec'),
102
- slashSkillScopeLabel: t('chatSlashSkillScope'),
103
- noSkillDescription: t('chatSkillsPickerNoDescription')
104
- };
105
- },
106
- [language]
107
- );
108
-
73
+ const slashTexts = useMemo(() => {
74
+ void language;
75
+ return {
76
+ slashSkillSubtitle: t('chatSlashTypeSkill'),
77
+ slashSkillSpecLabel: t('chatSlashSkillSpec'),
78
+ slashSkillScopeLabel: t('chatSlashSkillScope'),
79
+ noSkillDescription: t('chatSkillsPickerNoDescription')
80
+ };
81
+ }, [language]);
82
+ return {
83
+ skillScopeLabels,
84
+ slashTexts,
85
+ recentModelsLabel: t('chatPickerRecentModels'),
86
+ allModelsLabel: t('chatPickerAllModels'),
87
+ recentSkillsLabel: t('chatPickerRecent'),
88
+ allSkillsLabel: t('chatPickerAllSkills')
89
+ };
90
+ }
91
+ function useChatInputBarCollections(snapshot: ChatInputStoreSnapshot, skillScopeLabels: Record<'builtin' | 'project' | 'workspace', string>) {
109
92
  const skillRecords = useMemo(
110
93
  () => toSkillRecords(snapshot.skillRecords, skillScopeLabels),
111
94
  [snapshot.skillRecords, skillScopeLabels]
112
95
  );
113
96
  const modelRecords = useMemo(() => toModelRecords(snapshot.modelOptions), [snapshot.modelOptions]);
114
- const recentModelValues = chatRecentModelsManager.resolveVisible({
115
- availableValues: modelRecords.map((option) => option.value),
116
- minAvailableCount: CHAT_RECENT_MODELS_MIN_OPTIONS
117
- });
118
- const recentSkillValues = chatRecentSkillsManager.resolveVisible({
119
- availableValues: skillRecords.map((record) => record.key),
120
- minAvailableCount: 0
121
- });
122
- const recentSkillGroupValues = chatRecentSkillsManager.resolveVisible({
123
- availableValues: skillRecords.map((record) => record.key),
124
- minAvailableCount: CHAT_RECENT_SKILLS_MIN_OPTIONS
125
- });
126
-
127
- const hasModelOptions = modelRecords.length > 0;
128
- const isModelOptionsLoading = !snapshot.isProviderStateResolved && !hasModelOptions;
129
- const isModelOptionsEmpty = snapshot.isProviderStateResolved && !hasModelOptions;
130
- const inputDisabled =
131
- ((isModelOptionsLoading || isModelOptionsEmpty) && !snapshot.isSending) || snapshot.sessionTypeUnavailable;
132
- const attachmentSupported = typeof presenter.chatInputManager.addAttachments === 'function';
133
- const textareaPlaceholder = isModelOptionsLoading
134
- ? ''
135
- : hasModelOptions
136
- ? t('chatInputPlaceholder')
137
- : t('chatModelNoOptions');
138
- const recentModelsLabel = t('chatPickerRecentModels');
139
- const allModelsLabel = t('chatPickerAllModels');
140
- const recentSkillsLabel = t('chatPickerRecent');
141
- const allSkillsLabel = t('chatPickerAllSkills');
142
-
143
- const slashItems = useMemo(
144
- () => buildChatSlashItems(skillRecords, slashQuery ?? '', slashTexts, recentSkillValues),
145
- [slashQuery, skillRecords, slashTexts, recentSkillValues]
146
- );
147
-
148
- const selectedModelOption = modelRecords.find((option) => option.value === snapshot.selectedModel);
149
- const selectedModelThinkingCapability = selectedModelOption?.thinkingCapability;
150
- const thinkingSupportedLevels = selectedModelThinkingCapability?.supported ?? [];
151
-
152
- const resolvedStopHint =
153
- snapshot.stopDisabledReason === '__preparing__'
154
- ? t('chatStopPreparing')
155
- : snapshot.stopDisabledReason?.trim() || t('chatStopUnavailable');
156
-
97
+ return {
98
+ skillRecords,
99
+ modelRecords,
100
+ recentModelValues: chatRecentModelsManager.resolveVisible({
101
+ availableValues: modelRecords.map((option) => option.value),
102
+ minAvailableCount: CHAT_RECENT_MODELS_MIN_OPTIONS
103
+ }),
104
+ recentSkillValues: chatRecentSkillsManager.resolveVisible({
105
+ availableValues: skillRecords.map((record) => record.key),
106
+ minAvailableCount: 0
107
+ }),
108
+ recentSkillGroupValues: chatRecentSkillsManager.resolveVisible({
109
+ availableValues: skillRecords.map((record) => record.key),
110
+ minAvailableCount: CHAT_RECENT_SKILLS_MIN_OPTIONS
111
+ })
112
+ };
113
+ }
114
+ function useChatInputBarAttachments(params: { attachmentSupported: boolean; inputBarRef: RefObject<ChatInputBarHandle | null>; presenter: ChatPresenter; }) {
115
+ const { attachmentSupported, inputBarRef, presenter } = params;
157
116
  const showAttachmentError = useCallback((reason: 'unsupported-type' | 'too-large' | 'read-failed') => {
158
117
  if (reason === 'unsupported-type') {
159
118
  toast.error(t('chatInputAttachmentUnsupported'));
@@ -167,35 +126,39 @@ export function ChatInputBarContainer() {
167
126
  }
168
127
  toast.error(t('chatInputAttachmentReadFailed'));
169
128
  }, []);
170
-
171
129
  const handleFilesAdd = useCallback(async (files: File[]) => {
172
130
  if (!attachmentSupported || files.length === 0) {
173
131
  return;
174
132
  }
175
- const result = await uploadFilesAsNcpDraftAttachments(files, {
176
- uploadBatch: uploadNcpAssets,
177
- });
133
+ const result = await uploadFilesAsNcpDraftAttachments(files, { uploadBatch: uploadNcpAssets });
178
134
  if (result.attachments.length > 0) {
179
135
  const insertedAttachments = presenter.chatInputManager.addAttachments?.(result.attachments) ?? [];
180
136
  if (insertedAttachments.length > 0) {
181
137
  inputBarRef.current?.insertFileTokens(
182
- insertedAttachments.map((attachment) => ({
183
- tokenKey: attachment.id,
184
- label: attachment.name
185
- }))
138
+ insertedAttachments.map((attachment) => ({ tokenKey: attachment.id, label: attachment.name }))
186
139
  );
187
140
  }
188
141
  }
189
142
  if (result.rejected.length > 0) {
190
143
  showAttachmentError(result.rejected[0].reason);
191
144
  }
192
- }, [attachmentSupported, presenter.chatInputManager, showAttachmentError]);
193
-
194
- const toolbarSelects = [
145
+ }, [attachmentSupported, inputBarRef, presenter.chatInputManager, showAttachmentError]);
146
+ return {
147
+ handleFilesAdd,
148
+ handleFileInputChange: useCallback(async (event: ChangeEvent<HTMLInputElement>) => {
149
+ const files = Array.from(event.target.files ?? []);
150
+ event.currentTarget.value = '';
151
+ await handleFilesAdd(files);
152
+ }, [handleFilesAdd])
153
+ };
154
+ }
155
+ function buildToolbarSelects(params: { allModelsLabel: string; hasModelOptions: boolean; isModelOptionsLoading: boolean; modelRecords: ChatModelRecord[]; presenter: ChatPresenter; recentModelValues: string[]; recentModelsLabel: string; selectedModel: string; selectedThinkingLevel: ChatThinkingLevel | null; thinkingSupportedLevels: ChatThinkingLevel[]; thinkingDefaultLevel: ChatThinkingLevel | null; }) {
156
+ const { allModelsLabel, hasModelOptions, isModelOptionsLoading, modelRecords, presenter, recentModelValues, recentModelsLabel, selectedModel, selectedThinkingLevel, thinkingSupportedLevels, thinkingDefaultLevel } = params;
157
+ return [
195
158
  buildModelToolbarSelect({
196
159
  modelOptions: modelRecords,
197
160
  recentModelValues,
198
- selectedModel: snapshot.selectedModel,
161
+ selectedModel,
199
162
  isModelOptionsLoading,
200
163
  hasModelOptions,
201
164
  onValueChange: presenter.chatInputManager.selectModel,
@@ -208,16 +171,18 @@ export function ChatInputBarContainer() {
208
171
  }),
209
172
  buildThinkingToolbarSelect({
210
173
  supportedLevels: thinkingSupportedLevels,
211
- selectedThinkingLevel: snapshot.selectedThinkingLevel as ChatThinkingLevel | null,
212
- defaultThinkingLevel: selectedModelThinkingCapability?.default ?? null,
174
+ selectedThinkingLevel,
175
+ defaultThinkingLevel: thinkingDefaultLevel,
213
176
  onValueChange: (value) => presenter.chatInputManager.selectThinkingLevel(value),
214
177
  texts: {
215
178
  thinkingLabels: buildThinkingLabels()
216
179
  }
217
180
  })
218
181
  ].filter((item): item is NonNullable<typeof item> => item !== null);
219
-
220
- const skillPicker = buildSkillPickerModel({
182
+ }
183
+ function buildSkillPicker(params: { allSkillsLabel: string; presenter: ChatPresenter; recentSkillGroupValues: string[]; recentSkillValues: string[]; recentSkillsLabel: string; skillRecords: ChatSkillRecord[]; snapshot: ChatInputStoreSnapshot; }) {
184
+ const { allSkillsLabel, presenter, recentSkillGroupValues, recentSkillValues, recentSkillsLabel, skillRecords, snapshot } = params;
185
+ return buildSkillPickerModel({
221
186
  skillRecords,
222
187
  recentSkillValues,
223
188
  groupedRecentSkillValues: recentSkillGroupValues,
@@ -234,12 +199,56 @@ export function ChatInputBarContainer() {
234
199
  allSkillsLabel
235
200
  }
236
201
  });
237
-
238
- const composerSelectedSkillCount = deriveSelectedSkillsFromComposer(snapshot.composerNodes).length;
239
- const hasSendableDraft =
240
- snapshot.draft.trim().length > 0 ||
241
- snapshot.attachments.length > 0 ||
242
- composerSelectedSkillCount > 0;
202
+ }
203
+ export function ChatInputBarContainer() {
204
+ const presenter = usePresenter();
205
+ const { language } = useI18n();
206
+ const snapshot = useChatInputStore((state) => state.snapshot);
207
+ const runtimeAvailability = useChatRuntimeAvailability();
208
+ const [slashQuery, setSlashQuery] = useState<string | null>(null);
209
+ const inputBarRef = useRef<ChatInputBarHandle | null>(null);
210
+ const fileInputRef = useRef<HTMLInputElement | null>(null);
211
+ const labels = useChatInputBarLabels(language);
212
+ const { skillRecords, modelRecords, recentModelValues, recentSkillValues, recentSkillGroupValues } = useChatInputBarCollections(snapshot, labels.skillScopeLabels);
213
+ const hasModelOptions = hasNcpChatModelOptions(snapshot);
214
+ const isModelOptionsLoading = isNcpChatModelOptionsLoading(snapshot);
215
+ const isModelOptionsEmpty = isNcpChatModelOptionsEmpty(snapshot);
216
+ const inputDisabled = isNcpChatComposerDisabled(snapshot);
217
+ const attachmentSupported = typeof presenter.chatInputManager.addAttachments === 'function';
218
+ const textareaPlaceholder = isModelOptionsEmpty ? t('chatModelNoOptions') : t('chatInputPlaceholder');
219
+ const slashItems = useMemo(
220
+ () => buildChatSlashItems(skillRecords, slashQuery ?? '', labels.slashTexts, recentSkillValues),
221
+ [labels.slashTexts, recentSkillValues, skillRecords, slashQuery]
222
+ );
223
+ const selectedModelOption = modelRecords.find((option) => option.value === snapshot.selectedModel);
224
+ const thinkingSupportedLevels = selectedModelOption?.thinkingCapability?.supported ?? [];
225
+ const resolvedStopHint = snapshot.stopDisabledReason === '__preparing__'
226
+ ? t('chatStopPreparing')
227
+ : snapshot.stopDisabledReason?.trim() || t('chatStopUnavailable');
228
+ const { handleFilesAdd, handleFileInputChange } = useChatInputBarAttachments({ attachmentSupported, inputBarRef, presenter });
229
+ const toolbarSelects = buildToolbarSelects({
230
+ allModelsLabel: labels.allModelsLabel,
231
+ hasModelOptions,
232
+ isModelOptionsLoading,
233
+ modelRecords,
234
+ presenter,
235
+ recentModelValues,
236
+ recentModelsLabel: labels.recentModelsLabel,
237
+ selectedModel: snapshot.selectedModel,
238
+ selectedThinkingLevel: snapshot.selectedThinkingLevel as ChatThinkingLevel | null,
239
+ thinkingSupportedLevels,
240
+ thinkingDefaultLevel: selectedModelOption?.thinkingCapability?.default ?? null
241
+ });
242
+ const skillPicker = buildSkillPicker({
243
+ allSkillsLabel: labels.allSkillsLabel,
244
+ presenter,
245
+ recentSkillGroupValues,
246
+ recentSkillValues,
247
+ recentSkillsLabel: labels.recentSkillsLabel,
248
+ skillRecords,
249
+ snapshot
250
+ });
251
+ const hasSendableDraft = snapshot.draft.trim().length > 0 || snapshot.attachments.length > 0 || deriveSelectedSkillsFromComposer(snapshot.composerNodes).length > 0;
243
252
 
244
253
  return (
245
254
  <>
@@ -256,7 +265,7 @@ export function ChatInputBarContainer() {
256
265
  slashMenu={{
257
266
  isLoading: snapshot.isSkillsLoading,
258
267
  items: slashItems,
259
- onSelectItem: (item) => {
268
+ onSelectItem: (item: { value?: string }) => {
260
269
  if (item.value) {
261
270
  presenter.chatInputManager.rememberSkillSelection(item.value);
262
271
  }
@@ -284,7 +293,7 @@ export function ChatInputBarContainer() {
284
293
  {
285
294
  key: 'attach',
286
295
  label: t('chatInputAttach'),
287
- icon: 'paperclip',
296
+ icon: 'paperclip' as const,
288
297
  iconOnly: true,
289
298
  disabled: !attachmentSupported || inputDisabled || snapshot.isSending,
290
299
  ...(attachmentSupported
@@ -298,10 +307,14 @@ export function ChatInputBarContainer() {
298
307
  ],
299
308
  skillPicker,
300
309
  actions: {
301
- sendError: snapshot.sendError,
310
+ sendError: runtimeAvailability.isBlocked ? null : snapshot.sendError,
302
311
  isSending: snapshot.isSending,
303
312
  canStopGeneration: snapshot.canStopGeneration,
304
- sendDisabled: !hasSendableDraft || !hasModelOptions || snapshot.sessionTypeUnavailable,
313
+ sendDisabled: isNcpChatSendDisabled({
314
+ snapshot,
315
+ hasSendableDraft,
316
+ isRuntimeBlocked: runtimeAvailability.isBlocked
317
+ }),
305
318
  stopDisabled: !snapshot.canStopGeneration,
306
319
  stopHint: resolvedStopHint,
307
320
  sendButtonLabel: t('chatSend'),
@@ -317,11 +330,7 @@ export function ChatInputBarContainer() {
317
330
  type="file"
318
331
  multiple
319
332
  className="hidden"
320
- onChange={async (event) => {
321
- const files = Array.from(event.target.files ?? []);
322
- event.currentTarget.value = '';
323
- await handleFilesAdd(files);
324
- }}
333
+ onChange={handleFileInputChange}
325
334
  />
326
335
  ) : null}
327
336
  </>
@@ -15,11 +15,11 @@ vi.mock("@nextclaw/agent-chat-ui", () => ({
15
15
  },
16
16
  }));
17
17
 
18
- vi.mock("@/components/providers/I18nProvider", () => ({
18
+ vi.mock("@/app/components/i18n-provider", () => ({
19
19
  useI18n: () => ({ language: captures.language }),
20
20
  }));
21
21
 
22
- vi.mock("@/lib/i18n", () => ({
22
+ vi.mock("@/shared/lib/i18n", () => ({
23
23
  formatDateTime: (value: string) => `formatted:${value}`,
24
24
  t: (key: string) => key,
25
25
  }));
@@ -10,12 +10,12 @@ import {
10
10
  adaptChatMessage,
11
11
  type ChatMessageAdapterTexts,
12
12
  type ChatMessageSource,
13
- } from "@/components/chat/adapters/chat-message.adapter";
14
- import { readInlineTokensFromMetadata } from "@/components/chat/chat-inline-token.utils";
15
- import { adaptNcpMessageToUiMessage } from "@/components/chat/ncp/ncp-session-adapter";
16
- import { AgentIdentityAvatar } from "@/components/common/agent-identity";
17
- import { useI18n } from "@/components/providers/I18nProvider";
18
- import { formatDateTime, t } from "@/lib/i18n";
13
+ } from "@/features/chat/utils/chat-message.utils";
14
+ import { readInlineTokensFromMetadata } from "@/features/chat/utils/chat-inline-token.utils";
15
+ import { adaptNcpMessageToUiMessage } from "@/features/chat/utils/ncp-session-adapter.utils";
16
+ import { AgentIdentityAvatar } from "@/shared/components/common/agent-identity";
17
+ import { useI18n } from "@/app/components/i18n-provider";
18
+ import { formatDateTime, t } from "@/shared/lib/i18n";
19
19
 
20
20
  type ChatMessageListContainerProps = {
21
21
  messages: readonly NcpMessage[];