@vibe-forge/client 2.0.0 → 3.0.0-alpha.0

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 (351) hide show
  1. package/AGENTS.md +4 -1
  2. package/dist/assets/{arc-CbOXL0l9.js → arc-1JbypnRY.js} +1 -1
  3. package/dist/assets/{blockDiagram-c4efeb88-CqxINvsS.js → blockDiagram-c4efeb88-jT5b9nId.js} +1 -1
  4. package/dist/assets/{c4Diagram-c83219d4-BKazU0hb.js → c4Diagram-c83219d4-KNPh-1ta.js} +1 -1
  5. package/dist/assets/channel-pzvjJnfd.js +1 -0
  6. package/dist/assets/{classDiagram-beda092f-fAFX5BpB.js → classDiagram-beda092f-vvXuOT3F.js} +1 -1
  7. package/dist/assets/{classDiagram-v2-2358418a-w1VkNGJj.js → classDiagram-v2-2358418a-vH4j7skr.js} +1 -1
  8. package/dist/assets/clone-CtWwIeUb.js +1 -0
  9. package/dist/assets/{createText-1719965b-CEinakVP.js → createText-1719965b-COeSYnf3.js} +1 -1
  10. package/dist/assets/{cssMode-DPqRki4y.js → cssMode-Doc7QRKn.js} +1 -1
  11. package/dist/assets/{edges-96097737-Cb0F1_3K.js → edges-96097737-D09v6R_r.js} +1 -1
  12. package/dist/assets/{erDiagram-0228fc6a-C-N2fx-J.js → erDiagram-0228fc6a-CbZ6rfxl.js} +1 -1
  13. package/dist/assets/{flowDb-c6c81e3f-D1Xz_8Gf.js → flowDb-c6c81e3f-CnZOzhdk.js} +1 -1
  14. package/dist/assets/{flowDiagram-50d868cf-DyPSZyAj.js → flowDiagram-50d868cf-jv-xWM2p.js} +1 -1
  15. package/dist/assets/flowDiagram-v2-4f6560a1-BiyrkIKs.js +1 -0
  16. package/dist/assets/{flowchart-elk-definition-6af322e1-Dr1DDXwE.js → flowchart-elk-definition-6af322e1-D8pf677G.js} +1 -1
  17. package/dist/assets/{freemarker2-C3DvPFaK.js → freemarker2-CL0o23Gj.js} +1 -1
  18. package/dist/assets/{ganttDiagram-a2739b55-DmvY1GRj.js → ganttDiagram-a2739b55-BAPQzC4u.js} +1 -1
  19. package/dist/assets/{gitGraphDiagram-82fe8481-CoXfPYYi.js → gitGraphDiagram-82fe8481-BI2x71m0.js} +1 -1
  20. package/dist/assets/{graph-BkDQy7Qt.js → graph-CZK4Bjpq.js} +1 -1
  21. package/dist/assets/{handlebars-BcTFdqjl.js → handlebars-CCG38Pg6.js} +1 -1
  22. package/dist/assets/{html-Dg-O6XFr.js → html-BddshTWG.js} +1 -1
  23. package/dist/assets/{htmlMode-B_wqYWvn.js → htmlMode-xKXiYcDz.js} +1 -1
  24. package/dist/assets/{index-5325376f-kxPTR3_e.js → index-5325376f-BWMTD8RU.js} +1 -1
  25. package/dist/assets/{index-wkhI4dr6.js → index-CBe7kDkV.js} +398 -377
  26. package/dist/assets/index-MWOwVzqE.css +32 -0
  27. package/dist/assets/{infoDiagram-8eee0895-BEvqkwPI.js → infoDiagram-8eee0895-CR78btIF.js} +1 -1
  28. package/dist/assets/{javascript-DhlOH8_z.js → javascript-BPlRHPjg.js} +1 -1
  29. package/dist/assets/{journeyDiagram-c64418c1-gKtLYmmp.js → journeyDiagram-c64418c1-DZRv6FKz.js} +1 -1
  30. package/dist/assets/{jsonMode-DxTbF9OD.js → jsonMode-BYLVfdkf.js} +1 -1
  31. package/dist/assets/{layout-CDaZEk6E.js → layout-BtudyPU2.js} +1 -1
  32. package/dist/assets/{line-DNRQu8iq.js → line-DgHXrIhS.js} +1 -1
  33. package/dist/assets/{linear-Cph9Z6_j.js → linear-DtBoKICx.js} +1 -1
  34. package/dist/assets/{liquid-ByZ6JgRG.js → liquid-DxBlJk0W.js} +1 -1
  35. package/dist/assets/{lspLanguageFeatures-DzvhkgnM.js → lspLanguageFeatures-DmKVpmeH.js} +1 -1
  36. package/dist/assets/{mdx-D8RGHTl6.js → mdx-DrScsd-w.js} +1 -1
  37. package/dist/assets/{mermaid.core-BgcryF__.js → mermaid.core-Cj_NJ_lZ.js} +4 -4
  38. package/dist/assets/{mindmap-definition-8da855dc-WrxK0FcB.js → mindmap-definition-8da855dc-CMXbwtsc.js} +1 -1
  39. package/dist/assets/{pieDiagram-a8764435-VsZBsiQy.js → pieDiagram-a8764435-Bd6rfpJv.js} +1 -1
  40. package/dist/assets/{python-CXVtk_cg.js → python-Crbi7B7n.js} +1 -1
  41. package/dist/assets/{quadrantDiagram-1e28029f-BVlgwOvU.js → quadrantDiagram-1e28029f-H-FdBQn6.js} +1 -1
  42. package/dist/assets/{razor-0tind7h2.js → razor-DHyrzIfE.js} +1 -1
  43. package/dist/assets/{requirementDiagram-08caed73-CpPMPoYp.js → requirementDiagram-08caed73-BSyCVDSG.js} +1 -1
  44. package/dist/assets/{sankeyDiagram-a04cb91d-Cm5nnRmc.js → sankeyDiagram-a04cb91d-S6E6BReg.js} +1 -1
  45. package/dist/assets/{sequenceDiagram-c5b8d532-DpMlJvJB.js → sequenceDiagram-c5b8d532-BMHY4KMj.js} +1 -1
  46. package/dist/assets/{stateDiagram-1ecb1508-DU1zc7vq.js → stateDiagram-1ecb1508-BMrMw6XR.js} +1 -1
  47. package/dist/assets/{stateDiagram-v2-c2b004d7-D-0RgmAp.js → stateDiagram-v2-c2b004d7-B5SIFUb_.js} +1 -1
  48. package/dist/assets/{styles-b4e223ce-BSO-yNWV.js → styles-b4e223ce-DqiXwnx3.js} +1 -1
  49. package/dist/assets/{styles-ca3715f6-CHnsn2Ro.js → styles-ca3715f6-jNxW2Db8.js} +1 -1
  50. package/dist/assets/{styles-d45a18b0-B-rVGjEq.js → styles-d45a18b0-C4nlfLcZ.js} +1 -1
  51. package/dist/assets/{svgDrawCommon-b86b1483-CA3Pl89f.js → svgDrawCommon-b86b1483-FIWFuZfb.js} +1 -1
  52. package/dist/assets/{timeline-definition-faaaa080-BcihLR6s.js → timeline-definition-faaaa080-CEQDoqdf.js} +1 -1
  53. package/dist/assets/{tsMode-D9GGa5Ur.js → tsMode-DnNy3rE9.js} +1 -1
  54. package/dist/assets/{typescript-BT9CK_EL.js → typescript-YBZ4vw5B.js} +1 -1
  55. package/dist/assets/{xml-DNO75J-T.js → xml-BJGGYD70.js} +1 -1
  56. package/dist/assets/{xychartDiagram-f5964ef8-DJTwe32X.js → xychartDiagram-f5964ef8-DUNOFOk0.js} +1 -1
  57. package/dist/assets/{yaml-7CVzhiP2.js → yaml-BMY4mu5s.js} +1 -1
  58. package/dist/index.html +8 -3
  59. package/dist/manifest.webmanifest +30 -0
  60. package/dist/pwa-icon-192.png +0 -0
  61. package/dist/pwa-icon-512.png +0 -0
  62. package/dist/sw.js +105 -0
  63. package/index.html +6 -1
  64. package/package.json +13 -13
  65. package/public/manifest.webmanifest +30 -0
  66. package/public/pwa-icon-192.png +0 -0
  67. package/public/pwa-icon-512.png +0 -0
  68. package/public/sw.js +105 -0
  69. package/src/App.tsx +13 -1
  70. package/src/api/README.md +1 -0
  71. package/src/api/adapters.ts +63 -0
  72. package/src/api/auth-token.ts +51 -0
  73. package/src/api/auth.ts +46 -0
  74. package/src/api/automation.ts +10 -0
  75. package/src/api/base.ts +20 -17
  76. package/src/api/config.ts +5 -1
  77. package/src/api/knowledge.ts +59 -0
  78. package/src/api/sessions.ts +35 -3
  79. package/src/api/skill-hub.ts +126 -0
  80. package/src/api/workspace.ts +33 -1
  81. package/src/api/worktree-environments.ts +53 -0
  82. package/src/api.ts +62 -7
  83. package/src/client-build-info.ts +19 -0
  84. package/src/components/ConfigView.scss +596 -28
  85. package/src/components/ConfigView.tsx +569 -138
  86. package/src/components/NavRail.scss +1 -2
  87. package/src/components/NavRail.tsx +33 -3
  88. package/src/components/Sidebar.scss +0 -44
  89. package/src/components/Sidebar.tsx +110 -37
  90. package/src/components/auth/AuthGate.scss +79 -0
  91. package/src/components/auth/AuthGate.tsx +174 -0
  92. package/src/components/automation-view/@components/AutomationTaskComposer.tsx +220 -0
  93. package/src/components/automation-view/@components/AutomationTriggerRow.tsx +192 -0
  94. package/src/components/automation-view/@hooks/use-automation-startup-options-data.tsx +289 -0
  95. package/src/components/automation-view/@hooks/use-automation-startup-static-options.ts +51 -0
  96. package/src/components/automation-view/@utils/sender-model-options.tsx +52 -0
  97. package/src/components/automation-view/@utils/startup-options.ts +26 -0
  98. package/src/components/automation-view/AutomationEmptyGuide.tsx +61 -0
  99. package/src/components/automation-view/AutomationEmptyLanding.scss +165 -0
  100. package/src/components/automation-view/AutomationEmptyLanding.tsx +211 -0
  101. package/src/components/automation-view/AutomationRuleDetailPreview.tsx +179 -0
  102. package/src/components/automation-view/PanelTitleActions.tsx +66 -0
  103. package/src/components/automation-view/RuleFormPanel.scss +172 -49
  104. package/src/components/automation-view/RuleFormPanel.tsx +196 -91
  105. package/src/components/automation-view/RuleSidebar.scss +128 -41
  106. package/src/components/automation-view/RuleSidebar.tsx +173 -89
  107. package/src/components/automation-view/RunHistoryPanel.scss +307 -72
  108. package/src/components/automation-view/RunHistoryPanel.tsx +185 -165
  109. package/src/components/automation-view/TaskList.scss +130 -64
  110. package/src/components/automation-view/TaskList.tsx +15 -31
  111. package/src/components/automation-view/TriggerList.scss +87 -8
  112. package/src/components/automation-view/TriggerList.tsx +14 -173
  113. package/src/components/automation-view/index.scss +165 -37
  114. package/src/components/automation-view/index.tsx +174 -87
  115. package/src/components/automation-view/types.ts +13 -0
  116. package/src/components/chat/AGENTS.md +3 -1
  117. package/src/components/chat/ChatHeader.tsx +56 -33
  118. package/src/components/chat/ChatHistoryView.tsx +254 -123
  119. package/src/components/chat/NewSessionGuide.scss +274 -204
  120. package/src/components/chat/NewSessionGuide.tsx +46 -111
  121. package/src/components/chat/NewSessionGuideStarterList.tsx +190 -0
  122. package/src/components/chat/NewSessionGuideStarterSection.tsx +121 -0
  123. package/src/components/chat/bottom-dock-constants.ts +4 -0
  124. package/src/components/chat/conversation-starter-apply.ts +181 -0
  125. package/src/components/chat/git-controls/ChatGitControls.scss +65 -0
  126. package/src/components/chat/git-controls/DraftGitControls.tsx +14 -0
  127. package/src/components/chat/git-controls/DraftWorktreeEnvironmentDropdown.tsx +115 -0
  128. package/src/components/chat/messages/MessageItem.tsx +21 -6
  129. package/src/components/chat/messages/MessageStatusNotice.tsx +12 -4
  130. package/src/components/chat/messages/build-chat-history-status-notices.ts +18 -13
  131. package/src/components/chat/messages/message-action-utils.ts +29 -0
  132. package/src/components/chat/new-session-guide-config.ts +19 -0
  133. package/src/components/chat/new-session-guide-items.ts +172 -0
  134. package/src/components/chat/new-session-guide-list-order.ts +58 -0
  135. package/src/components/chat/sender/@components/account-select/AccountSelectControl.scss +112 -0
  136. package/src/components/chat/sender/@components/account-select/AccountSelectControl.tsx +280 -0
  137. package/src/components/chat/sender/@components/account-select/AccountSelectDropdown.scss +155 -0
  138. package/src/components/chat/sender/@components/adapter-select/AdapterSelectControl.scss +51 -12
  139. package/src/components/chat/sender/@components/adapter-select/AdapterSelectDropdown.scss +14 -0
  140. package/src/components/chat/sender/@components/effort-select/EffortSelectControl.scss +36 -0
  141. package/src/components/chat/sender/@components/effort-select/EffortSelectControl.tsx +17 -12
  142. package/src/components/chat/sender/@components/model-select/ModelSelectControl.scss +62 -0
  143. package/src/components/chat/sender/@components/model-select/ModelSelectControl.tsx +17 -12
  144. package/src/components/chat/sender/@components/model-select/ModelSelectMenu.scss +2 -0
  145. package/src/components/chat/sender/@components/model-select/ModelSelectMenuLabels.scss +24 -0
  146. package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.scss +199 -0
  147. package/src/components/chat/sender/@components/permission-mode-control/PermissionModeControl.tsx +172 -0
  148. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.scss +1 -10
  149. package/src/components/chat/sender/@components/reference-actions/ReferenceActionsControl.tsx +16 -65
  150. package/src/components/chat/sender/@components/sender-body/SenderBody.tsx +13 -1
  151. package/src/components/chat/sender/@components/sender-header-controls/SenderHeaderControls.tsx +157 -0
  152. package/src/components/chat/sender/@components/sender-monaco-editor/monaco-runtime.ts +1 -17
  153. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectBase.scss +18 -2
  154. package/src/components/chat/sender/@components/sender-toolbar/SenderSelectShared.scss +18 -1
  155. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.scss +2 -0
  156. package/src/components/chat/sender/@components/sender-toolbar/SenderToolbar.tsx +40 -40
  157. package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.scss +215 -0
  158. package/src/components/chat/sender/@components/session-target/SenderSessionTargetBar.tsx +185 -0
  159. package/src/components/chat/sender/@core/build-sender-toolbar.ts +6 -0
  160. package/src/components/chat/sender/@core/create-sender-toolbar-handlers.ts +21 -1
  161. package/src/components/chat/sender/@core/get-sender-runtime-state.ts +3 -2
  162. package/src/components/chat/sender/@core/sender-toolbar-bindings.ts +12 -0
  163. package/src/components/chat/sender/@hooks/use-sender-controller.ts +56 -1
  164. package/src/components/chat/sender/@hooks/use-sender-reference-actions.ts +9 -66
  165. package/src/components/chat/sender/@types/sender-props.ts +18 -0
  166. package/src/components/chat/sender/@types/sender-toolbar-types.ts +8 -1
  167. package/src/components/chat/sender/@types/sender-types.ts +1 -3
  168. package/src/components/chat/sender/@utils/sender-constants.ts +1 -1
  169. package/src/components/chat/sender/Sender.scss +257 -2
  170. package/src/components/chat/sender/Sender.tsx +1 -0
  171. package/src/components/chat/status-bar/ChatStatusBar.scss +85 -0
  172. package/src/components/chat/status-bar/ChatStatusBar.tsx +48 -0
  173. package/src/components/chat/terminal/@components/TerminalManagerList.tsx +191 -0
  174. package/src/components/chat/terminal/@components/TerminalPane.scss +71 -0
  175. package/src/components/chat/terminal/@components/TerminalPane.tsx +137 -0
  176. package/src/components/chat/terminal/@components/TerminalPanelActions.tsx +75 -0
  177. package/src/components/chat/terminal/@hooks/use-terminal-instance.ts +36 -0
  178. package/src/components/chat/terminal/@hooks/use-terminal-session.ts +18 -21
  179. package/src/components/chat/terminal/@hooks/use-terminal-title-editor.ts +72 -0
  180. package/src/components/chat/terminal/@utils/terminal-keyboard.ts +141 -0
  181. package/src/components/chat/terminal/@utils/terminal-panes.ts +123 -0
  182. package/src/components/chat/terminal/ChatTerminalView.scss +310 -38
  183. package/src/components/chat/terminal/ChatTerminalView.tsx +151 -79
  184. package/src/components/chat/tools/core/ToolDiffViewer.tsx +3 -17
  185. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.scss +778 -0
  186. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawer.tsx +112 -0
  187. package/src/components/chat/workspace-drawer/ChatWorkspaceDrawerToolbar.tsx +183 -0
  188. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFileRow.tsx +75 -0
  189. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFiles.tsx +161 -0
  190. package/src/components/chat/workspace-drawer/WorkspaceDrawerChangedFolderTree.tsx +191 -0
  191. package/src/components/chat/workspace-drawer/WorkspaceDrawerTree.tsx +35 -0
  192. package/src/components/chat/workspace-drawer/WorkspaceDrawerTreeState.tsx +17 -0
  193. package/src/components/chat/workspace-drawer/changed-files-model.ts +152 -0
  194. package/src/components/chat/workspace-drawer/workspace-drawer-icons.ts +110 -0
  195. package/src/components/chat/workspace-file-editor/WorkspaceFileBreadcrumb.tsx +17 -0
  196. package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.scss +283 -0
  197. package/src/components/chat/workspace-file-editor/WorkspaceFileEditorView.tsx +165 -0
  198. package/src/components/chat/workspace-file-editor/WorkspaceFileTabs.tsx +135 -0
  199. package/src/components/chat/workspace-file-editor/use-workspace-file-editor-state.ts +113 -0
  200. package/src/components/chat/workspace-file-editor/workspace-file-editor-language.ts +55 -0
  201. package/src/components/composer-landing/ComposerLanding.scss +75 -0
  202. package/src/components/composer-landing/ComposerLanding.tsx +47 -0
  203. package/src/components/config/AGENTS.md +45 -0
  204. package/src/components/config/AdapterAccountsManager.scss +540 -0
  205. package/src/components/config/AdapterAccountsManager.tsx +846 -0
  206. package/src/components/config/AppSettingsPanel.tsx +85 -9
  207. package/src/components/config/ConfigAboutSection.scss +7 -1
  208. package/src/components/config/ConfigAboutSection.tsx +21 -3
  209. package/src/components/config/ConfigEditors.scss +12 -0
  210. package/src/components/config/ConfigFieldRow.scss +88 -4
  211. package/src/components/config/ConfigSectionForm.scss +88 -3
  212. package/src/components/config/ConfigSectionForm.tsx +948 -138
  213. package/src/components/config/ConfigSectionPanel.tsx +188 -12
  214. package/src/components/config/ConfigSourceSwitch.tsx +32 -18
  215. package/src/components/config/DetailCollectionFieldActions.tsx +63 -0
  216. package/src/components/config/DetailListField.tsx +413 -0
  217. package/src/components/config/McpServerItemEditor.tsx +154 -0
  218. package/src/components/config/RecommendedModelsItemEditor.tsx +146 -0
  219. package/src/components/config/WorktreeEnvironmentDetailView.tsx +126 -0
  220. package/src/components/config/WorktreeEnvironmentListView.tsx +126 -0
  221. package/src/components/config/WorktreeEnvironmentPanel.scss +430 -0
  222. package/src/components/config/WorktreeEnvironmentPanel.tsx +147 -0
  223. package/src/components/config/WorktreeEnvironmentScriptEditorCard.tsx +125 -0
  224. package/src/components/config/WorktreeEnvironmentScriptEditors.tsx +189 -0
  225. package/src/components/config/configConflict.ts +41 -0
  226. package/src/components/config/configDetail.ts +381 -0
  227. package/src/components/config/configSchema.ts +850 -179
  228. package/src/components/config/configUtils.ts +1 -1
  229. package/src/components/config/record-editors/RecordEditors.scss +187 -2
  230. package/src/components/config/record-editors/RecordJsonEditor.tsx +27 -2
  231. package/src/components/config/record-editors/SchemaObjectEditor.tsx +183 -0
  232. package/src/components/config/record-editors/SchemaRecordEditor.tsx +184 -0
  233. package/src/components/config/record-editors/index.tsx +2 -1
  234. package/src/components/config/record-editors/schemaRecordUtils.ts +55 -0
  235. package/src/components/config/use-worktree-environment-auto-save.ts +386 -0
  236. package/src/components/config/worktree-environment-panel-model.ts +108 -0
  237. package/src/components/dock-panel/DockPanel.scss +84 -17
  238. package/src/components/dock-panel/DockPanel.tsx +37 -34
  239. package/src/components/dock-panel/DockPanelHeader.tsx +65 -0
  240. package/src/components/dock-panel/use-dock-panel-fullscreen.ts +51 -0
  241. package/src/components/knowledge-base/KnowledgeBaseView.scss +276 -38
  242. package/src/components/knowledge-base/KnowledgeBaseView.tsx +252 -46
  243. package/src/components/knowledge-base/components/@hooks/use-skills-cli-modal-controller.ts +157 -0
  244. package/src/components/knowledge-base/components/@hooks/use-skills-tab-actions.ts +63 -0
  245. package/src/components/knowledge-base/components/ActionButton.scss +30 -4
  246. package/src/components/knowledge-base/components/ActionButton.tsx +13 -3
  247. package/src/components/knowledge-base/components/CreateSkillModal.tsx +59 -0
  248. package/src/components/knowledge-base/components/EmptyState.scss +4 -2
  249. package/src/components/knowledge-base/components/EntitiesTab.tsx +20 -20
  250. package/src/components/knowledge-base/components/EntityList.scss +3 -0
  251. package/src/components/knowledge-base/components/FilterBar.scss +1 -0
  252. package/src/components/knowledge-base/components/FilterBar.tsx +12 -8
  253. package/src/components/knowledge-base/components/FlowsTab.tsx +20 -20
  254. package/src/components/knowledge-base/components/KnowledgeBaseHeader.tsx +7 -6
  255. package/src/components/knowledge-base/components/KnowledgeContentControls.tsx +35 -0
  256. package/src/components/knowledge-base/components/KnowledgeList.scss +14 -3
  257. package/src/components/knowledge-base/components/KnowledgeMobilePanel.tsx +122 -0
  258. package/src/components/knowledge-base/components/KnowledgeSidebar.tsx +97 -0
  259. package/src/components/knowledge-base/components/LoadingState.scss +2 -1
  260. package/src/components/knowledge-base/components/ProjectSkillsList.tsx +79 -0
  261. package/src/components/knowledge-base/components/RuleList.scss +3 -0
  262. package/src/components/knowledge-base/components/RulesTab.tsx +31 -30
  263. package/src/components/knowledge-base/components/SectionHeader.scss +13 -1
  264. package/src/components/knowledge-base/components/SectionHeader.tsx +5 -3
  265. package/src/components/knowledge-base/components/SkillArchiveInput.tsx +43 -0
  266. package/src/components/knowledge-base/components/SkillHubResultItem.tsx +112 -0
  267. package/src/components/knowledge-base/components/SkillMarketResults.tsx +98 -0
  268. package/src/components/knowledge-base/components/SkillMarketView.tsx +198 -0
  269. package/src/components/knowledge-base/components/SkillMarketView.types.ts +28 -0
  270. package/src/components/knowledge-base/components/SkillRegistryErrors.tsx +21 -0
  271. package/src/components/knowledge-base/components/SkillRegistryModal.tsx +74 -0
  272. package/src/components/knowledge-base/components/SkillsCliModal.tsx +154 -0
  273. package/src/components/knowledge-base/components/SkillsTab.scss +424 -0
  274. package/src/components/knowledge-base/components/SkillsTab.tsx +166 -35
  275. package/src/components/knowledge-base/components/SkillsTabActions.tsx +88 -0
  276. package/src/components/knowledge-base/components/SpecList.scss +3 -0
  277. package/src/components/knowledge-base/components/TabContent.scss +4 -3
  278. package/src/components/knowledge-base/components/skill-hub-utils.ts +108 -0
  279. package/src/components/knowledge-base/components/use-skill-market-filters.ts +37 -0
  280. package/src/components/knowledge-base/components/use-skill-market-query-input.ts +44 -0
  281. package/src/components/knowledge-base/components/use-skill-market-search.ts +49 -0
  282. package/src/components/knowledge-base/components/use-skill-registry-modal.ts +68 -0
  283. package/src/components/monaco/monaco-runtime.ts +44 -0
  284. package/src/components/monaco/use-monaco-theme.ts +63 -0
  285. package/src/components/nav-rail-account-actions.tsx +104 -0
  286. package/src/components/server-connection/ServerConnectionGate.scss +356 -0
  287. package/src/components/server-connection/ServerConnectionGate.tsx +238 -0
  288. package/src/components/server-connection/ServerConnectionProfileModal.tsx +145 -0
  289. package/src/components/server-connection/ServerConnectionProfiles.tsx +113 -0
  290. package/src/components/server-connection/ServerConnectionUrlInput.tsx +85 -0
  291. package/src/components/sidebar/SidebarHeader.scss +5 -41
  292. package/src/components/sidebar/SidebarHeader.tsx +117 -91
  293. package/src/components/sidebar/SidebarHeaderSearchActions.tsx +24 -28
  294. package/src/components/sidebar/sidebar-search-visibility.ts +18 -0
  295. package/src/components/sidebar-list/SidebarListHeader.scss +246 -0
  296. package/src/components/sidebar-list/SidebarListHeader.tsx +146 -0
  297. package/src/components/workspace/ContextFilePicker.scss +9 -26
  298. package/src/components/workspace/ContextFilePicker.tsx +31 -113
  299. package/src/components/workspace/context-file-types.ts +36 -0
  300. package/src/components/workspace/project-file-tree/ProjectFileTree.scss +298 -0
  301. package/src/components/workspace/project-file-tree/ProjectFileTree.tsx +138 -0
  302. package/src/components/workspace/project-file-tree/ProjectFileTreeRow.tsx +167 -0
  303. package/src/components/workspace/project-file-tree/ProjectFileTreeRowContextMenu.tsx +106 -0
  304. package/src/components/workspace/project-file-tree/ProjectFileTreeRows.tsx +139 -0
  305. package/src/components/workspace/project-file-tree/project-file-tree-helpers.ts +101 -0
  306. package/src/components/workspace/project-file-tree/project-file-tree-icons.ts +93 -0
  307. package/src/components/workspace/project-file-tree/project-file-tree-types.ts +27 -0
  308. package/src/components/workspace/project-file-tree/use-project-file-tree-data.ts +197 -0
  309. package/src/components/workspace/project-file-tree/use-project-file-tree-selection.ts +144 -0
  310. package/src/hooks/chat/chat-session-target.ts +69 -0
  311. package/src/hooks/chat/chat-session-workspace-draft.ts +11 -4
  312. package/src/hooks/chat/interaction-state.ts +1 -0
  313. package/src/hooks/chat/optimistic-session-creation.ts +189 -0
  314. package/src/hooks/chat/use-chat-adapter-account-selection.tsx +156 -0
  315. package/src/hooks/chat/use-chat-route-bottom-panel.ts +181 -0
  316. package/src/hooks/chat/use-chat-route-deep-link-view.ts +33 -0
  317. package/src/hooks/chat/use-chat-session-actions.ts +259 -65
  318. package/src/hooks/chat/use-chat-session-messages.ts +71 -4
  319. package/src/hooks/chat/use-chat-session.ts +36 -1
  320. package/src/hooks/chat/workspace-file-panel-state.ts +43 -0
  321. package/src/hooks/session-subscription-cache.ts +25 -0
  322. package/src/hooks/use-chat-layout-query-state.ts +29 -0
  323. package/src/hooks/use-sender-header-query-state.ts +35 -0
  324. package/src/hooks/use-session-subscription.ts +17 -8
  325. package/src/hooks/useQueryParams.ts +91 -23
  326. package/src/i18n-resources.ts +44 -0
  327. package/src/i18n.ts +21 -6
  328. package/src/main.tsx +8 -0
  329. package/src/pwa.ts +46 -0
  330. package/src/resources/locales/en.json +741 -24
  331. package/src/resources/locales/zh.json +743 -26
  332. package/src/routes/ChatRoute.scss +110 -7
  333. package/src/routes/ChatRoute.tsx +11 -165
  334. package/src/routes/ChatRouteBottomPanel.tsx +47 -0
  335. package/src/routes/ChatRouteView.tsx +199 -0
  336. package/src/runtime-config.ts +155 -2
  337. package/src/server-connection-history.ts +179 -0
  338. package/src/store/index.ts +151 -3
  339. package/src/styles/global.scss +3 -0
  340. package/src/utils/mobile-viewport.ts +67 -0
  341. package/src/version-compatibility.ts +37 -0
  342. package/src/vite-env.d.ts +9 -0
  343. package/src/ws.ts +20 -9
  344. package/vite.config.ts +23 -1
  345. package/dist/assets/channel-Dnopc5A6.js +0 -1
  346. package/dist/assets/clone-sQthahUA.js +0 -1
  347. package/dist/assets/flowDiagram-v2-4f6560a1-OazrdWQO.js +0 -1
  348. package/dist/assets/index-o93dlo92.css +0 -32
  349. package/src/components/chat/NewSessionGuideCompactPanel.tsx +0 -130
  350. package/src/components/chat/NewSessionGuideGrid.tsx +0 -141
  351. package/src/components/chat/sender/@components/reference-actions/ReferencePermissionActionsPopover.tsx +0 -114
@@ -1,23 +1,51 @@
1
1
  import './KnowledgeBaseView.scss'
2
2
 
3
- import { App, Segmented } from 'antd'
3
+ import { App, Form } from 'antd'
4
4
  import React from 'react'
5
5
  import { useTranslation } from 'react-i18next'
6
6
  import useSWR from 'swr'
7
7
 
8
- import type { EntitySummary, RuleSummary, SpecSummary } from '#~/api.js'
8
+ import { createSkill, getApiErrorMessage } from '#~/api.js'
9
+ import type { EntitySummary, RuleSummary, SkillSummary, SpecSummary } from '#~/api.js'
9
10
  import { PageShell } from '#~/components/layout/PageShell.js'
10
11
  import { useResponsiveLayout } from '#~/hooks/use-responsive-layout'
11
12
  import { useQueryParams } from '#~/hooks/useQueryParams.js'
13
+ import { CreateSkillModal } from './components/CreateSkillModal.js'
14
+ import type { CreateSkillFormValues } from './components/CreateSkillModal.js'
12
15
  import { EntitiesTab } from './components/EntitiesTab.js'
13
16
  import { FlowsTab } from './components/FlowsTab.js'
17
+ import { KnowledgeContentControls } from './components/KnowledgeContentControls.js'
18
+ import { KnowledgeMobilePanel } from './components/KnowledgeMobilePanel.js'
19
+ import { KnowledgeSidebar } from './components/KnowledgeSidebar.js'
14
20
  import { RulesTab } from './components/RulesTab.js'
15
21
  import { SkillsTab } from './components/SkillsTab.js'
22
+ import {
23
+ ALL_REGISTRIES,
24
+ ALL_SKILL_SOURCES,
25
+ isSkillHubInstallFilter,
26
+ isSkillHubSortKey
27
+ } from './components/skill-hub-utils.js'
28
+ import type { SkillHubInstallFilter, SkillHubSortKey } from './components/skill-hub-utils.js'
16
29
 
17
30
  interface KnowledgeQueryParams extends Record<string, string> {
18
31
  kbTab: string
32
+ skillInstall: string
33
+ skillMarketSearch: string
34
+ skillProjectSearch: string
35
+ skillRegistry: string
36
+ skillSort: string
37
+ skillSource: string
38
+ skillView: string
19
39
  }
20
40
 
41
+ const toSkillViewMode = (value: string): 'project' | 'market' => value === 'market' ? 'market' : 'project'
42
+ const toSkillHubInstallFilter = (value: string): SkillHubInstallFilter => (
43
+ isSkillHubInstallFilter(value) ? value : 'all'
44
+ )
45
+ const toSkillHubSortKey = (value: string): SkillHubSortKey => (
46
+ isSkillHubSortKey(value) ? value : 'default'
47
+ )
48
+
21
49
  export function KnowledgeBaseView() {
22
50
  const { t } = useTranslation()
23
51
  const { message } = App.useApp()
@@ -37,6 +65,10 @@ export function KnowledgeBaseView() {
37
65
  isLoading: isRulesLoading,
38
66
  mutate: mutateRules
39
67
  } = useSWR<{ rules: RuleSummary[] }>('/api/ai/rules')
68
+ const {
69
+ data: skillsRes,
70
+ mutate: mutateSkills
71
+ } = useSWR<{ skills: SkillSummary[] }>('/api/ai/skills')
40
72
 
41
73
  const specs = specsRes?.specs ?? []
42
74
  const entities = entitiesRes?.entities ?? []
@@ -47,13 +79,71 @@ export function KnowledgeBaseView() {
47
79
  const [entityQuery, setEntityQuery] = React.useState('')
48
80
  const [entityTagFilter, setEntityTagFilter] = React.useState<string[]>([])
49
81
  const [ruleQuery, setRuleQuery] = React.useState('')
82
+ const [isKnowledgeSidebarCollapsed, setKnowledgeSidebarCollapsed] = React.useState(false)
83
+ const [isMobileKnowledgePanelOpen, setMobileKnowledgePanelOpen] = React.useState(false)
84
+ const [createSkillOpen, setCreateSkillOpen] = React.useState(false)
85
+ const [savingSkill, setSavingSkill] = React.useState(false)
86
+ const [createSkillForm] = Form.useForm<CreateSkillFormValues>()
50
87
 
51
88
  const { values, update } = useQueryParams<KnowledgeQueryParams>({
52
- keys: ['kbTab'],
89
+ keys: [
90
+ 'kbTab',
91
+ 'skillView',
92
+ 'skillProjectSearch',
93
+ 'skillMarketSearch',
94
+ 'skillRegistry',
95
+ 'skillSource',
96
+ 'skillInstall',
97
+ 'skillSort'
98
+ ],
53
99
  defaults: {
54
- kbTab: 'skills'
100
+ kbTab: 'skills',
101
+ skillView: 'project',
102
+ skillProjectSearch: '',
103
+ skillMarketSearch: '',
104
+ skillRegistry: ALL_REGISTRIES,
105
+ skillSource: ALL_SKILL_SOURCES,
106
+ skillInstall: 'all',
107
+ skillSort: 'default'
108
+ },
109
+ omit: {
110
+ skillView: value => value === 'project',
111
+ skillProjectSearch: value => value === '',
112
+ skillMarketSearch: value => value === '',
113
+ skillRegistry: value => value === ALL_REGISTRIES,
114
+ skillSource: value => value === ALL_SKILL_SOURCES,
115
+ skillInstall: value => value === 'all',
116
+ skillSort: value => value === 'default'
55
117
  }
56
118
  })
119
+ const skillViewMode = toSkillViewMode(values.skillView)
120
+ const skillInstallFilter = toSkillHubInstallFilter(values.skillInstall)
121
+ const skillSortKey = toSkillHubSortKey(values.skillSort)
122
+ const skillProjectQuery = values.skillProjectSearch
123
+ const skillMarketQuery = values.skillMarketSearch
124
+ const skillRegistry = values.skillRegistry || ALL_REGISTRIES
125
+ const skillSourceFilter = values.skillSource || ALL_SKILL_SOURCES
126
+ const updateSkillProjectQuery = React.useCallback((value: string) => {
127
+ update({ skillProjectSearch: value })
128
+ }, [update])
129
+ const updateSkillViewMode = React.useCallback((value: 'project' | 'market') => {
130
+ update({ skillView: value })
131
+ }, [update])
132
+ const updateSkillMarketQuery = React.useCallback((value: string) => {
133
+ update({ skillMarketSearch: value })
134
+ }, [update])
135
+ const updateSkillRegistry = React.useCallback((value: string) => {
136
+ update({ skillRegistry: value })
137
+ }, [update])
138
+ const updateSkillSourceFilter = React.useCallback((value: string) => {
139
+ update({ skillSource: value })
140
+ }, [update])
141
+ const updateSkillInstallFilter = React.useCallback((value: SkillHubInstallFilter) => {
142
+ update({ skillInstall: value })
143
+ }, [update])
144
+ const updateSkillSortKey = React.useCallback((value: SkillHubSortKey) => {
145
+ update({ skillSort: value })
146
+ }, [update])
57
147
 
58
148
  const specTagOptions = React.useMemo(() => {
59
149
  const tags = new Set<string>()
@@ -112,7 +202,7 @@ export function KnowledgeBaseView() {
112
202
  }, [ruleQuery, rules])
113
203
 
114
204
  const handleRefresh = async () => {
115
- await Promise.all([mutateSpecs(), mutateEntities(), mutateRules()])
205
+ await Promise.all([mutateSpecs(), mutateEntities(), mutateRules(), mutateSkills()])
116
206
  void message.success(t('knowledge.actions.refreshed'))
117
207
  }
118
208
 
@@ -133,11 +223,28 @@ export function KnowledgeBaseView() {
133
223
  }
134
224
 
135
225
  const handleCreateSkill = () => {
136
- message.info(t('knowledge.skills.createHint'))
226
+ createSkillForm.resetFields()
227
+ setCreateSkillOpen(true)
137
228
  }
138
229
 
139
- const handleImportSkill = () => {
140
- message.info(t('knowledge.skills.importHint'))
230
+ const handleSaveSkill = async () => {
231
+ const values = await createSkillForm.validateFields()
232
+ setSavingSkill(true)
233
+ try {
234
+ await createSkill({
235
+ name: values.name,
236
+ description: values.description,
237
+ body: values.body
238
+ })
239
+ setCreateSkillOpen(false)
240
+ createSkillForm.resetFields()
241
+ await mutateSkills()
242
+ void message.success(t('knowledge.skills.createSuccess'))
243
+ } catch (error) {
244
+ void message.error(getApiErrorMessage(error, t('knowledge.skills.createFailed')))
245
+ } finally {
246
+ setSavingSkill(false)
247
+ }
141
248
  }
142
249
 
143
250
  const handleCreateRule = () => {
@@ -148,7 +255,26 @@ export function KnowledgeBaseView() {
148
255
  message.info(t('knowledge.rules.importHint'))
149
256
  }
150
257
 
258
+ const isCompactView = isCompactLayout || isTouchInteraction
259
+ const getContentControls = (onCreate: () => void) =>
260
+ isCompactView
261
+ ? (
262
+ <KnowledgeContentControls
263
+ onCreate={onCreate}
264
+ onExpandSidebar={() => setMobileKnowledgePanelOpen(true)}
265
+ />
266
+ )
267
+ : isKnowledgeSidebarCollapsed
268
+ ? (
269
+ <KnowledgeContentControls
270
+ onCreate={onCreate}
271
+ onExpandSidebar={() => setKnowledgeSidebarCollapsed(false)}
272
+ />
273
+ )
274
+ : undefined
275
+
151
276
  const skillCount = React.useMemo(() => {
277
+ if (skillsRes?.skills != null) return skillsRes.skills.length
152
278
  const names = new Set<string>()
153
279
  specs.forEach(spec => {
154
280
  spec.skills?.forEach(skill => names.add(skill))
@@ -157,7 +283,7 @@ export function KnowledgeBaseView() {
157
283
  entity.skills?.forEach(skill => names.add(skill))
158
284
  })
159
285
  return names.size
160
- }, [entities, specs])
286
+ }, [entities, skillsRes?.skills, specs])
161
287
 
162
288
  const sections = [
163
289
  {
@@ -168,9 +294,22 @@ export function KnowledgeBaseView() {
168
294
  count: skillCount,
169
295
  content: (
170
296
  <SkillsTab
297
+ installFilter={skillInstallFilter}
298
+ leading={getContentControls(handleCreateSkill)}
299
+ marketQuery={skillMarketQuery}
300
+ projectQuery={skillProjectQuery}
301
+ registry={skillRegistry}
302
+ sortKey={skillSortKey}
303
+ sourceFilter={skillSourceFilter}
304
+ viewMode={skillViewMode}
171
305
  onRefresh={handleRefresh}
172
306
  onCreate={handleCreateSkill}
173
- onImport={handleImportSkill}
307
+ onInstallFilterChange={updateSkillInstallFilter}
308
+ onMarketQueryChange={updateSkillMarketQuery}
309
+ onRegistryChange={updateSkillRegistry}
310
+ onSortChange={updateSkillSortKey}
311
+ onSourceFilterChange={updateSkillSourceFilter}
312
+ onViewModeChange={updateSkillViewMode}
174
313
  />
175
314
  )
176
315
  },
@@ -184,7 +323,9 @@ export function KnowledgeBaseView() {
184
323
  <EntitiesTab
185
324
  entities={entities}
186
325
  filteredEntities={filteredEntities}
326
+ hideContentSearch={isCompactView}
187
327
  isLoading={isEntitiesLoading}
328
+ leading={getContentControls(handleCreateEntity)}
188
329
  query={entityQuery}
189
330
  tagOptions={entityTagOptions}
190
331
  tagFilter={entityTagFilter}
@@ -206,7 +347,9 @@ export function KnowledgeBaseView() {
206
347
  <FlowsTab
207
348
  specs={specs}
208
349
  filteredSpecs={filteredSpecs}
350
+ hideContentSearch={isCompactView}
209
351
  isLoading={isSpecsLoading}
352
+ leading={getContentControls(handleCreateSpec)}
210
353
  query={specQuery}
211
354
  tagOptions={specTagOptions}
212
355
  tagFilter={specTagFilter}
@@ -228,7 +371,9 @@ export function KnowledgeBaseView() {
228
371
  <RulesTab
229
372
  rules={rules}
230
373
  filteredRules={filteredRules}
374
+ hideContentSearch={isCompactView}
231
375
  isLoading={isRulesLoading}
376
+ leading={getContentControls(handleCreateRule)}
232
377
  query={ruleQuery}
233
378
  onRefresh={handleRefresh}
234
379
  onQueryChange={setRuleQuery}
@@ -245,7 +390,72 @@ export function KnowledgeBaseView() {
245
390
  () => sections.find(section => section.key === activeSectionKey) ?? sections[0],
246
391
  [activeSectionKey, sections]
247
392
  )
248
- const isCompactView = isCompactLayout || isTouchInteraction
393
+ const activeSearchValue = activeSectionKey === 'skills'
394
+ ? skillProjectQuery
395
+ : activeSectionKey === 'entities'
396
+ ? entityQuery
397
+ : activeSectionKey === 'flows'
398
+ ? specQuery
399
+ : activeSectionKey === 'rules'
400
+ ? ruleQuery
401
+ : ''
402
+ const activeSearchPlaceholder = activeSectionKey === 'skills'
403
+ ? t('knowledge.skills.searchProject')
404
+ : t('knowledge.filters.searchActive')
405
+ const showMobileSearch = !(activeSectionKey === 'skills' && skillViewMode === 'market')
406
+
407
+ React.useEffect(() => {
408
+ if (!isCompactView) {
409
+ setMobileKnowledgePanelOpen(false)
410
+ }
411
+ }, [isCompactView])
412
+
413
+ const handleActiveSearchChange = (value: string) => {
414
+ if (activeSectionKey === 'skills') {
415
+ updateSkillProjectQuery(value)
416
+ return
417
+ }
418
+ if (activeSectionKey === 'entities') {
419
+ setEntityQuery(value)
420
+ return
421
+ }
422
+ if (activeSectionKey === 'flows') {
423
+ setSpecQuery(value)
424
+ return
425
+ }
426
+ if (activeSectionKey === 'rules') {
427
+ setRuleQuery(value)
428
+ }
429
+ }
430
+
431
+ const handleSidebarCreate = () => {
432
+ if (isCompactView) {
433
+ setMobileKnowledgePanelOpen(false)
434
+ }
435
+
436
+ if (activeSectionKey === 'skills') {
437
+ handleCreateSkill()
438
+ return
439
+ }
440
+ if (activeSectionKey === 'entities') {
441
+ handleCreateEntity()
442
+ return
443
+ }
444
+ if (activeSectionKey === 'flows') {
445
+ handleCreateSpec()
446
+ return
447
+ }
448
+ if (activeSectionKey === 'rules') {
449
+ handleCreateRule()
450
+ }
451
+ }
452
+
453
+ const handleSelectSection = (key: string) => {
454
+ update({ kbTab: key })
455
+ if (isCompactView) {
456
+ setMobileKnowledgePanelOpen(false)
457
+ }
458
+ }
249
459
 
250
460
  React.useEffect(() => {
251
461
  if (values.kbTab !== activeSectionKey) {
@@ -260,47 +470,43 @@ export function KnowledgeBaseView() {
260
470
  >
261
471
  {isCompactView
262
472
  ? (
263
- <div className='knowledge-base-view__mobile-switcher-shell'>
264
- <Segmented
265
- block
266
- className='knowledge-base-view__mobile-switcher'
267
- value={activeSectionKey}
268
- onChange={(value) => update({ kbTab: value as string })}
269
- options={sections.map((section) => ({
270
- label: `${section.label} ${section.count}`,
271
- value: section.key
272
- }))}
273
- />
274
- </div>
473
+ <KnowledgeMobilePanel
474
+ activeKey={activeSectionKey}
475
+ open={isMobileKnowledgePanelOpen}
476
+ searchPlaceholder={activeSearchPlaceholder}
477
+ searchValue={activeSearchValue}
478
+ sections={sections}
479
+ showSearch={showMobileSearch}
480
+ onClose={() => setMobileKnowledgePanelOpen(false)}
481
+ onCreate={handleSidebarCreate}
482
+ onSearchChange={handleActiveSearchChange}
483
+ onSelect={handleSelectSection}
484
+ />
275
485
  )
276
486
  : (
277
- <div className='knowledge-base-view__left'>
278
- <div className='knowledge-base-view__sidebar'>
279
- <div className='knowledge-base-view__nav-list'>
280
- {sections.map((section) => (
281
- <button
282
- key={section.key}
283
- type='button'
284
- className={`knowledge-base-view__nav-item ${section.key === activeSectionKey ? 'is-active' : ''}`}
285
- onClick={() => update({ kbTab: section.key })}
286
- >
287
- <span className='material-symbols-rounded knowledge-base-view__nav-icon'>{section.icon}</span>
288
- <span className='knowledge-base-view__nav-main'>
289
- <span className='knowledge-base-view__nav-row'>
290
- <span className='knowledge-base-view__nav-label'>{section.label}</span>
291
- <span className='knowledge-base-view__nav-count'>{section.count}</span>
292
- </span>
293
- <span className='knowledge-base-view__nav-desc'>{section.description}</span>
294
- </span>
295
- </button>
296
- ))}
297
- </div>
298
- </div>
299
- </div>
487
+ <KnowledgeSidebar
488
+ activeKey={activeSectionKey}
489
+ collapsed={isKnowledgeSidebarCollapsed}
490
+ isCompact={isCompactView}
491
+ searchPlaceholder={activeSearchPlaceholder}
492
+ searchValue={activeSearchValue}
493
+ sections={sections}
494
+ onCreate={handleSidebarCreate}
495
+ onSearchChange={handleActiveSearchChange}
496
+ onSelect={handleSelectSection}
497
+ onToggleCollapsed={() => setKnowledgeSidebarCollapsed(prev => !prev)}
498
+ />
300
499
  )}
301
500
  <div className='knowledge-base-view__right'>
302
501
  <div className='knowledge-base-view__right-body'>{activeSection?.content}</div>
303
502
  </div>
503
+ <CreateSkillModal
504
+ open={createSkillOpen}
505
+ saving={savingSkill}
506
+ form={createSkillForm}
507
+ onSave={() => void handleSaveSkill()}
508
+ onClose={() => setCreateSkillOpen(false)}
509
+ />
304
510
  </PageShell>
305
511
  )
306
512
  }
@@ -0,0 +1,157 @@
1
+ import React from 'react'
2
+
3
+ import { Form } from 'antd'
4
+ import type { MessageInstance } from 'antd/es/message/interface'
5
+ import type { TFunction } from 'i18next'
6
+
7
+ import type { SkillHubItem } from '#~/api.js'
8
+ import { getApiErrorMessage, installSkillsCliItem, searchSkillsCli } from '#~/api.js'
9
+ import type { SkillsCliFormValues } from '../SkillsCliModal'
10
+
11
+ const SKILLS_CLI_INITIAL_LIMIT = 100
12
+ const SKILLS_CLI_LIMIT_STEP = 100
13
+ const SKILLS_CLI_MAX_LIMIT = 500
14
+
15
+ const trimOptionalString = (value: string | undefined) => {
16
+ const normalizedValue = value?.trim()
17
+ return normalizedValue == null || normalizedValue === '' ? undefined : normalizedValue
18
+ }
19
+
20
+ export const useSkillsCliModalController = (params: {
21
+ message: MessageInstance
22
+ mutateSkills: () => Promise<unknown>
23
+ t: TFunction
24
+ }) => {
25
+ const [open, setOpen] = React.useState(false)
26
+ const [searching, setSearching] = React.useState(false)
27
+ const [loadingMore, setLoadingMore] = React.useState(false)
28
+ const [installingId, setInstallingId] = React.useState<string | null>(null)
29
+ const [items, setItems] = React.useState<SkillHubItem[]>([])
30
+ const [error, setError] = React.useState<string | null>(null)
31
+ const [hasMore, setHasMore] = React.useState(false)
32
+ const [hasSearched, setHasSearched] = React.useState(false)
33
+ const [limit, setLimit] = React.useState(SKILLS_CLI_INITIAL_LIMIT)
34
+ const [resetKey, setResetKey] = React.useState('')
35
+ const [form] = Form.useForm<SkillsCliFormValues>()
36
+
37
+ const resolveRequest = React.useCallback(async () => {
38
+ try {
39
+ await form.validateFields(['source'])
40
+ } catch {
41
+ return undefined
42
+ }
43
+
44
+ const values = form.getFieldsValue()
45
+ const source = values.source.trim()
46
+ return {
47
+ source,
48
+ query: trimOptionalString(values.query),
49
+ registry: trimOptionalString(values.registry)
50
+ }
51
+ }, [form])
52
+
53
+ const runSearch = React.useCallback(async (nextLimit: number) => {
54
+ const request = await resolveRequest()
55
+ if (request == null) return false
56
+
57
+ const result = await searchSkillsCli({
58
+ limit: nextLimit,
59
+ source: request.source,
60
+ ...(request.query != null ? { query: request.query } : {}),
61
+ ...(request.registry != null ? { registry: request.registry } : {})
62
+ })
63
+
64
+ setHasSearched(true)
65
+ setLimit(nextLimit)
66
+ setItems(result.items)
67
+ setError(result.error ?? null)
68
+ setHasMore(result.hasMore === true && nextLimit < SKILLS_CLI_MAX_LIMIT)
69
+ setResetKey([request.source, request.query ?? '', request.registry ?? '', String(nextLimit)].join('\0'))
70
+ return true
71
+ }, [resolveRequest])
72
+
73
+ const handleSearch = React.useCallback(async () => {
74
+ setSearching(true)
75
+ setLoadingMore(false)
76
+ try {
77
+ await runSearch(SKILLS_CLI_INITIAL_LIMIT)
78
+ } catch (error) {
79
+ void params.message.error(getApiErrorMessage(error, params.t('knowledge.skills.skillsCliSearchFailed')))
80
+ } finally {
81
+ setSearching(false)
82
+ }
83
+ }, [params, runSearch])
84
+
85
+ const handleLoadMore = React.useCallback(async () => {
86
+ const nextLimit = Math.min(limit + SKILLS_CLI_LIMIT_STEP, SKILLS_CLI_MAX_LIMIT)
87
+ if (nextLimit === limit) return
88
+
89
+ setLoadingMore(true)
90
+ try {
91
+ await runSearch(nextLimit)
92
+ } catch (error) {
93
+ void params.message.error(getApiErrorMessage(error, params.t('knowledge.skills.skillsCliSearchFailed')))
94
+ } finally {
95
+ setLoadingMore(false)
96
+ }
97
+ }, [limit, params, runSearch])
98
+
99
+ const handleInstall = React.useCallback(async (item: SkillHubItem) => {
100
+ const request = await resolveRequest()
101
+ if (request == null) return
102
+
103
+ setInstallingId(item.id)
104
+ try {
105
+ await installSkillsCliItem({
106
+ source: request.source,
107
+ skill: item.installRef ?? item.name,
108
+ force: item.installed,
109
+ ...(request.registry != null ? { registry: request.registry } : {})
110
+ })
111
+ await params.mutateSkills()
112
+ try {
113
+ await runSearch(limit)
114
+ } catch {
115
+ // Keep the install success state even if refreshing the source list fails afterwards.
116
+ }
117
+ void params.message.success(params.t('knowledge.skills.installSuccess'))
118
+ } catch (error) {
119
+ void params.message.error(getApiErrorMessage(error, params.t('knowledge.skills.installFailed')))
120
+ } finally {
121
+ setInstallingId(null)
122
+ }
123
+ }, [limit, params, resolveRequest, runSearch])
124
+
125
+ const handleClose = React.useCallback(() => {
126
+ setOpen(false)
127
+ setSearching(false)
128
+ setLoadingMore(false)
129
+ setInstallingId(null)
130
+ setItems([])
131
+ setError(null)
132
+ setHasMore(false)
133
+ setHasSearched(false)
134
+ setLimit(SKILLS_CLI_INITIAL_LIMIT)
135
+ setResetKey('')
136
+ form.resetFields()
137
+ }, [form])
138
+
139
+ return {
140
+ form,
141
+ hasMore,
142
+ hasSearched,
143
+ installingId,
144
+ items,
145
+ limit,
146
+ loadingMore,
147
+ open,
148
+ resetKey,
149
+ searching,
150
+ searchError: error,
151
+ setOpen,
152
+ handleClose,
153
+ handleInstall,
154
+ handleLoadMore,
155
+ handleSearch
156
+ }
157
+ }
@@ -0,0 +1,63 @@
1
+ import React from 'react'
2
+
3
+ import type { MessageInstance } from 'antd/es/message/interface'
4
+ import type { TFunction } from 'i18next'
5
+
6
+ import type { SkillHubItem } from '#~/api.js'
7
+ import { getApiErrorMessage, importSkillArchive, installSkillHubItem } from '#~/api.js'
8
+
9
+ export const useSkillsTabActions = (params: {
10
+ marketMutate: () => Promise<unknown>
11
+ message: MessageInstance
12
+ mutateConfig: () => Promise<unknown>
13
+ mutateSkills: () => Promise<unknown>
14
+ onRefresh: () => void | Promise<void>
15
+ t: TFunction
16
+ }) => {
17
+ const importInputRef = React.useRef<HTMLInputElement | null>(null)
18
+ const [installingId, setInstallingId] = React.useState<string | null>(null)
19
+ const [importing, setImporting] = React.useState(false)
20
+
21
+ const handleRefresh = React.useCallback(async () => {
22
+ await Promise.all([params.mutateSkills(), params.marketMutate(), params.mutateConfig(), params.onRefresh()])
23
+ }, [params])
24
+
25
+ const handleInstall = React.useCallback(async (item: SkillHubItem) => {
26
+ setInstallingId(item.id)
27
+ try {
28
+ await installSkillHubItem({
29
+ registry: item.registry,
30
+ plugin: item.installRef ?? item.name,
31
+ force: item.installed
32
+ })
33
+ await Promise.all([params.marketMutate(), params.mutateSkills()])
34
+ void params.message.success(params.t('knowledge.skills.installSuccess'))
35
+ } catch (error) {
36
+ void params.message.error(getApiErrorMessage(error, params.t('knowledge.skills.installFailed')))
37
+ } finally {
38
+ setInstallingId(null)
39
+ }
40
+ }, [params])
41
+
42
+ const handleImportArchive = React.useCallback(async (file: File) => {
43
+ setImporting(true)
44
+ try {
45
+ const result = await importSkillArchive(file)
46
+ await Promise.all([params.mutateSkills(), params.onRefresh()])
47
+ void params.message.success(params.t('knowledge.skills.importSuccess', { count: result.fileCount }))
48
+ } catch (error) {
49
+ void params.message.error(getApiErrorMessage(error, params.t('knowledge.skills.importFailed')))
50
+ } finally {
51
+ setImporting(false)
52
+ }
53
+ }, [params])
54
+
55
+ return {
56
+ importInputRef,
57
+ importing,
58
+ installingId,
59
+ handleImportArchive,
60
+ handleInstall,
61
+ handleRefresh
62
+ }
63
+ }
@@ -1,9 +1,35 @@
1
- .knowledge-base-view__action-button {
1
+ .ant-btn.knowledge-base-view__action-button {
2
2
  display: inline-flex;
3
3
  align-items: center;
4
+ justify-content: center;
4
5
  gap: 6px;
5
- height: 28px;
6
- padding: 0 10px;
7
- border-radius: 6px;
6
+ height: 28px !important;
7
+ min-height: 28px !important;
8
+ padding: 0 10px !important;
9
+ border-radius: 6px !important;
8
10
  font-size: 12px;
11
+ line-height: 1;
12
+ }
13
+
14
+ .ant-btn.knowledge-base-view__action-button--icon-only {
15
+ width: 28px !important;
16
+ min-width: 28px !important;
17
+ max-width: 28px !important;
18
+ aspect-ratio: 1 / 1;
19
+ padding: 0 !important;
20
+ }
21
+
22
+ .knowledge-base-view__action-button--icon-only .ant-btn-icon {
23
+ display: inline-flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ line-height: 1;
27
+ }
28
+
29
+ .knowledge-base-view__action-button--icon-only .material-symbols-rounded {
30
+ display: inline-flex;
31
+ align-items: center;
32
+ justify-content: center;
33
+ font-size: 18px;
34
+ line-height: 1;
9
35
  }