@hualinge/relay-web 1.0.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 (332) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/dist/assets/AgentsPage-2u2kFBCH.js +68 -0
  4. package/dist/assets/AgentsPage-2u2kFBCH.js.map +1 -0
  5. package/dist/assets/AgentsPage-BGbbVmeL.css +1 -0
  6. package/dist/assets/Alert-D88Fk6to.js +2 -0
  7. package/dist/assets/Alert-D88Fk6to.js.map +1 -0
  8. package/dist/assets/AppModal-BYZTSuch.js +2 -0
  9. package/dist/assets/AppModal-BYZTSuch.js.map +1 -0
  10. package/dist/assets/CenteredLoadingState-DHor-9vF.js +2 -0
  11. package/dist/assets/CenteredLoadingState-DHor-9vF.js.map +1 -0
  12. package/dist/assets/ChannelsPage-CbI0kqkd.js +2 -0
  13. package/dist/assets/ChannelsPage-CbI0kqkd.js.map +1 -0
  14. package/dist/assets/EmptyDataState-6mNx2Xhl.js +2 -0
  15. package/dist/assets/EmptyDataState-6mNx2Xhl.js.map +1 -0
  16. package/dist/assets/HelpPrompt-BPzDcC8F.js +2 -0
  17. package/dist/assets/HelpPrompt-BPzDcC8F.js.map +1 -0
  18. package/dist/assets/HomePage-t78sDDUj.js +2 -0
  19. package/dist/assets/HomePage-t78sDDUj.js.map +1 -0
  20. package/dist/assets/InspirationPage-BTqLpcHY.js +3 -0
  21. package/dist/assets/InspirationPage-BTqLpcHY.js.map +1 -0
  22. package/dist/assets/ModelsPage-YF0gpUxy.js +2 -0
  23. package/dist/assets/ModelsPage-YF0gpUxy.js.map +1 -0
  24. package/dist/assets/NameInitialIcon-DP-6_HQY.js +7 -0
  25. package/dist/assets/NameInitialIcon-DP-6_HQY.js.map +1 -0
  26. package/dist/assets/NoSearchResultsState-BiiYdZ_Z.js +2 -0
  27. package/dist/assets/NoSearchResultsState-BiiYdZ_Z.js.map +1 -0
  28. package/dist/assets/OverflowTooltip-CE5PjAb-.js +2 -0
  29. package/dist/assets/OverflowTooltip-CE5PjAb-.js.map +1 -0
  30. package/dist/assets/PasswordField-DmzjtnCg.js +2 -0
  31. package/dist/assets/PasswordField-DmzjtnCg.js.map +1 -0
  32. package/dist/assets/RefreshButton-BzYzeo5A.js +2 -0
  33. package/dist/assets/RefreshButton-BzYzeo5A.js.map +1 -0
  34. package/dist/assets/RightContentHeader-DoNDQ9Lo.js +3 -0
  35. package/dist/assets/RightContentHeader-DoNDQ9Lo.js.map +1 -0
  36. package/dist/assets/SchedulePage-CfW6lZVI.js +2 -0
  37. package/dist/assets/SchedulePage-CfW6lZVI.js.map +1 -0
  38. package/dist/assets/SearchInput-tux8xXH1.js +2 -0
  39. package/dist/assets/SearchInput-tux8xXH1.js.map +1 -0
  40. package/dist/assets/SkillAvatar-DwGvsY4f.js +2 -0
  41. package/dist/assets/SkillAvatar-DwGvsY4f.js.map +1 -0
  42. package/dist/assets/SkillsPage-ppqwKMvj.js +2 -0
  43. package/dist/assets/SkillsPage-ppqwKMvj.js.map +1 -0
  44. package/dist/assets/SkillsTab-c_As1DIr.css +1 -0
  45. package/dist/assets/SkillsTab-kY7MNdxy.js +2 -0
  46. package/dist/assets/SkillsTab-kY7MNdxy.js.map +1 -0
  47. package/dist/assets/Tab-FE0F2EQP.js +2 -0
  48. package/dist/assets/Tab-FE0F2EQP.js.map +1 -0
  49. package/dist/assets/ThreadPage-B0jElW5R.js +53 -0
  50. package/dist/assets/ThreadPage-B0jElW5R.js.map +1 -0
  51. package/dist/assets/UploadSkillModal-DHZL12vm.js +8 -0
  52. package/dist/assets/UploadSkillModal-DHZL12vm.js.map +1 -0
  53. package/dist/assets/XlsxDocumentPreview-BY-ht09K.js +5 -0
  54. package/dist/assets/XlsxDocumentPreview-BY-ht09K.js.map +1 -0
  55. package/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js +2 -0
  56. package/dist/assets/_commonjs-dynamic-modules-TDtrdbi3.js.map +1 -0
  57. package/dist/assets/chat-input-options-CpkOtPgQ.js +2 -0
  58. package/dist/assets/chat-input-options-CpkOtPgQ.js.map +1 -0
  59. package/dist/assets/docx-preview-zfB-orwa.js +28 -0
  60. package/dist/assets/docx-preview-zfB-orwa.js.map +1 -0
  61. package/dist/assets/exceljs.min-BY7KKJsM.js +58 -0
  62. package/dist/assets/exceljs.min-BY7KKJsM.js.map +1 -0
  63. package/dist/assets/helpers-CCilgpNy.js +2 -0
  64. package/dist/assets/helpers-CCilgpNy.js.map +1 -0
  65. package/dist/assets/hub-agent-editor.client-2DmCRGuY.js +2 -0
  66. package/dist/assets/hub-agent-editor.client-2DmCRGuY.js.map +1 -0
  67. package/dist/assets/hub-agent-editor.payload-D4sgJRSH.js +4 -0
  68. package/dist/assets/hub-agent-editor.payload-D4sgJRSH.js.map +1 -0
  69. package/dist/assets/hub-tag-editor-BBdd-aHK.js +2 -0
  70. package/dist/assets/hub-tag-editor-BBdd-aHK.js.map +1 -0
  71. package/dist/assets/index-Bed0I5IL.css +1 -0
  72. package/dist/assets/index-Bxf2_cvh.js +2 -0
  73. package/dist/assets/index-Bxf2_cvh.js.map +1 -0
  74. package/dist/assets/index-Cb4fQgom.js +103 -0
  75. package/dist/assets/index-Cb4fQgom.js.map +1 -0
  76. package/dist/assets/index-DQ2vVjmV.js +30 -0
  77. package/dist/assets/index-DQ2vVjmV.js.map +1 -0
  78. package/dist/assets/index-UBJEdbMO.js +2 -0
  79. package/dist/assets/index-UBJEdbMO.js.map +1 -0
  80. package/dist/assets/jszip.min-DPdj3o0t.js +13 -0
  81. package/dist/assets/jszip.min-DPdj3o0t.js.map +1 -0
  82. package/dist/assets/quick-actions-DzZE-zyP.js +2 -0
  83. package/dist/assets/quick-actions-DzZE-zyP.js.map +1 -0
  84. package/dist/assets/skill-options-cache-D1BJGTCU.js +2 -0
  85. package/dist/assets/skill-options-cache-D1BJGTCU.js.map +1 -0
  86. package/dist/assets/status-helpers-BILdm2MI.js +2 -0
  87. package/dist/assets/status-helpers-BILdm2MI.js.map +1 -0
  88. package/dist/assets/thread-title-Cerb2mHa.js +2 -0
  89. package/dist/assets/thread-title-Cerb2mHa.js.map +1 -0
  90. package/dist/assets/thread-utils-Ct3yp4R3.js +2 -0
  91. package/dist/assets/thread-utils-Ct3yp4R3.js.map +1 -0
  92. package/dist/assets/useAgentData-D-k9cXfg.js +2 -0
  93. package/dist/assets/useAgentData-D-k9cXfg.js.map +1 -0
  94. package/dist/assets/useEscapeKey-CEQ6-8GR.js +2 -0
  95. package/dist/assets/useEscapeKey-CEQ6-8GR.js.map +1 -0
  96. package/dist/assets/useExpertCatalog-BZdw1CYs.js +2 -0
  97. package/dist/assets/useExpertCatalog-BZdw1CYs.js.map +1 -0
  98. package/dist/assets/usePromptBlocks-5sz8Qh51.js +2 -0
  99. package/dist/assets/usePromptBlocks-5sz8Qh51.js.map +1 -0
  100. package/dist/assets/useSocket-YigidotN.css +1 -0
  101. package/dist/assets/useSocket-y3-zWhVL.js +11 -0
  102. package/dist/assets/useSocket-y3-zWhVL.js.map +1 -0
  103. package/dist/assets/utils--_pbLpCq.js +2 -0
  104. package/dist/assets/utils--_pbLpCq.js.map +1 -0
  105. package/dist/assets/vad-web-C_R267y1.js +2 -0
  106. package/dist/assets/vad-web-C_R267y1.js.map +1 -0
  107. package/dist/avatars/agent-avatar-1.png +0 -0
  108. package/dist/avatars/agent-avatar-2.png +0 -0
  109. package/dist/avatars/agent-avatar-3.png +0 -0
  110. package/dist/avatars/agent-avatar-4.png +0 -0
  111. package/dist/avatars/agent-avatar-5.png +0 -0
  112. package/dist/avatars/agent-avatar-6.png +0 -0
  113. package/dist/avatars/agent-avatar-7.png +0 -0
  114. package/dist/avatars/agent-avatar-8.png +0 -0
  115. package/dist/avatars/agent-avatar-9.png +0 -0
  116. package/dist/avatars/agentteams.png +0 -0
  117. package/dist/avatars/antig-opus.png +0 -0
  118. package/dist/avatars/antigravity.png +0 -0
  119. package/dist/avatars/assistant.svg +17 -0
  120. package/dist/avatars/codex-kawaii.png +0 -0
  121. package/dist/avatars/codex.png +0 -0
  122. package/dist/avatars/codex_box.png +0 -0
  123. package/dist/avatars/codex_iquid.png +0 -0
  124. package/dist/avatars/dare.png +0 -0
  125. package/dist/avatars/gemini-kawaii.png +0 -0
  126. package/dist/avatars/gemini.png +0 -0
  127. package/dist/avatars/gemini25.png +0 -0
  128. package/dist/avatars/gpt52.png +0 -0
  129. package/dist/avatars/jiuwenclaw.png +0 -0
  130. package/dist/avatars/office.svg +17 -0
  131. package/dist/avatars/opencode.png +0 -0
  132. package/dist/avatars/opus-45.png +0 -0
  133. package/dist/avatars/opus-kawaii.png +0 -0
  134. package/dist/avatars/opus.png +0 -0
  135. package/dist/avatars/sonnet.png +0 -0
  136. package/dist/favicon.ico +0 -0
  137. package/dist/icons/arrow-left.svg +3 -0
  138. package/dist/icons/arrow-right.svg +3 -0
  139. package/dist/icons/attach.svg +9 -0
  140. package/dist/icons/chart/dislike.svg +3 -0
  141. package/dist/icons/chart/disliked.svg +3 -0
  142. package/dist/icons/chart/folder.svg +15 -0
  143. package/dist/icons/chart/home-loading.webp +0 -0
  144. package/dist/icons/chart/like.svg +3 -0
  145. package/dist/icons/chart/liked.svg +5 -0
  146. package/dist/icons/chart/loading.svg +26 -0
  147. package/dist/icons/chart/success.svg +7 -0
  148. package/dist/icons/check-line.svg +3 -0
  149. package/dist/icons/chevron-left.svg +3 -0
  150. package/dist/icons/chevron-right.svg +3 -0
  151. package/dist/icons/collapse.svg +14 -0
  152. package/dist/icons/common-delete.svg +4 -0
  153. package/dist/icons/common-folder.svg +4 -0
  154. package/dist/icons/copy.svg +4 -0
  155. package/dist/icons/cross-line.svg +4 -0
  156. package/dist/icons/data-analysis.svg +7 -0
  157. package/dist/icons/data-visualization.svg +10 -0
  158. package/dist/icons/deep-research.svg +4 -0
  159. package/dist/icons/document-processing.svg +5 -0
  160. package/dist/icons/edit.svg +4 -0
  161. package/dist/icons/expand.svg +6 -0
  162. package/dist/icons/expert-debate.svg +4 -0
  163. package/dist/icons/eye.svg +4 -0
  164. package/dist/icons/favicon.svg +7 -0
  165. package/dist/icons/file-docx.svg +60 -0
  166. package/dist/icons/file-folder.svg +4 -0
  167. package/dist/icons/file-gitignore.svg +35 -0
  168. package/dist/icons/file-html.svg +6 -0
  169. package/dist/icons/file-ini.svg +63 -0
  170. package/dist/icons/file-json.svg +4 -0
  171. package/dist/icons/file-md.svg +68 -0
  172. package/dist/icons/file-py.svg +4 -0
  173. package/dist/icons/file-sh.svg +7 -0
  174. package/dist/icons/file-txt.svg +37 -0
  175. package/dist/icons/file-zip.svg +21 -0
  176. package/dist/icons/file.svg +4 -0
  177. package/dist/icons/files-csv.svg +14 -0
  178. package/dist/icons/files-docx.svg +10 -0
  179. package/dist/icons/files-pdf.svg +14 -0
  180. package/dist/icons/files-ppt.svg +14 -0
  181. package/dist/icons/files-txt.svg +16 -0
  182. package/dist/icons/files-xlsx.svg +14 -0
  183. package/dist/icons/financial-services.svg +8 -0
  184. package/dist/icons/flie-html.svg +60 -0
  185. package/dist/icons/guided-mode.svg +9 -0
  186. package/dist/icons/icon-192x192.png +0 -0
  187. package/dist/icons/icon-512x512.png +0 -0
  188. package/dist/icons/icon-arrow-down.svg +4 -0
  189. package/dist/icons/icon-arrow-up.svg +4 -0
  190. package/dist/icons/icon-clear-all.svg +3 -0
  191. package/dist/icons/icon-close.svg +4 -0
  192. package/dist/icons/icon-code.svg +38 -0
  193. package/dist/icons/icon-drag-file.svg +26 -0
  194. package/dist/icons/icon-help.svg +4 -0
  195. package/dist/icons/icon-md.svg +53 -0
  196. package/dist/icons/icon-refresh.svg +4 -0
  197. package/dist/icons/icon-toggle.svg +6 -0
  198. package/dist/icons/icon-top.svg +7 -0
  199. package/dist/icons/icon-upload.svg +5 -0
  200. package/dist/icons/information.svg +6 -0
  201. package/dist/icons/inspiration/icon-excel.svg +14 -0
  202. package/dist/icons/inspiration/icon-inspiration.svg +5 -0
  203. package/dist/icons/inspiration/icon-markdown.svg +12 -0
  204. package/dist/icons/inspiration/icon-word.svg +10 -0
  205. package/dist/icons/link.svg +6 -0
  206. package/dist/icons/lock.svg +4 -0
  207. package/dist/icons/menu/agents.svg +39 -0
  208. package/dist/icons/menu/channels.svg +4 -0
  209. package/dist/icons/menu/icon-inspiration.svg +5 -0
  210. package/dist/icons/menu/models.svg +4 -0
  211. package/dist/icons/menu/new-chat.svg +59 -0
  212. package/dist/icons/menu/schedule.svg +4 -0
  213. package/dist/icons/menu/skills.svg +4 -0
  214. package/dist/icons/message-error.svg +6 -0
  215. package/dist/icons/message-prompt.svg +9 -0
  216. package/dist/icons/message-success.svg +6 -0
  217. package/dist/icons/message-warn.svg +8 -0
  218. package/dist/icons/more-trigger.svg +4 -0
  219. package/dist/icons/nss/1.svg +14 -0
  220. package/dist/icons/nss/2.svg +14 -0
  221. package/dist/icons/nss/3.svg +14 -0
  222. package/dist/icons/outline.svg +6 -0
  223. package/dist/icons/query_the_optical_power_border.svg +99 -0
  224. package/dist/icons/schedule.svg +4 -0
  225. package/dist/icons/settings-feedback/feedback-bug.svg +20 -0
  226. package/dist/icons/settings-feedback/feedback-file.svg +4 -0
  227. package/dist/icons/settings-feedback/feedback-idea.svg +14 -0
  228. package/dist/icons/settings-feedback/settings-gear.svg +4 -0
  229. package/dist/icons/settings-feedback/settings-link.svg +4 -0
  230. package/dist/icons/settings-feedback/settings-memory.svg +7 -0
  231. package/dist/icons/settings-feedback/settings-privacy.svg +37 -0
  232. package/dist/icons/settings-feedback/settings-search.svg +2 -0
  233. package/dist/icons/slides.svg +4 -0
  234. package/dist/icons/status/info-error.svg +9 -0
  235. package/dist/icons/style-template.svg +11 -0
  236. package/dist/icons/tool-error.svg +4 -0
  237. package/dist/icons/userprofile/help.svg +5 -0
  238. package/dist/icons/userprofile/keep-awake.svg +4 -0
  239. package/dist/icons/userprofile/question.svg +4 -0
  240. package/dist/icons/userprofile/security.svg +7 -0
  241. package/dist/icons/userprofile/style-template.svg +11 -0
  242. package/dist/icons/userprofile/theme.svg +14 -0
  243. package/dist/icons/userprofile/usage.svg +4 -0
  244. package/dist/icons/userprofile/version.svg +85 -0
  245. package/dist/icons/video-generation.svg +4 -0
  246. package/dist/images/OfficeClaw.svg +21 -0
  247. package/dist/images/add.svg +4 -0
  248. package/dist/images/agent-management-icons/agent-check.svg +23 -0
  249. package/dist/images/agent-management-icons/agent-close.svg +4 -0
  250. package/dist/images/agent-management-icons/agent-collab.svg +4 -0
  251. package/dist/images/agent-management-icons/agent-delete.svg +18 -0
  252. package/dist/images/agent-management-icons/agent-edit.svg +18 -0
  253. package/dist/images/agent-management-icons/agent-more.svg +4 -0
  254. package/dist/images/agent-management-icons/agent-persona.svg +4 -0
  255. package/dist/images/agent-management-icons/agent-random-avatar.svg +39 -0
  256. package/dist/images/agent-management-icons/agent-refresh.svg +4 -0
  257. package/dist/images/agent-management-icons/agent-skills.svg +4 -0
  258. package/dist/images/agent-management-icons/agent-template.svg +12 -0
  259. package/dist/images/agent-management-icons/anchor-current.svg +5 -0
  260. package/dist/images/agent-management-icons/anchor-other.svg +4 -0
  261. package/dist/images/chat-empty-agent.svg +12 -0
  262. package/dist/images/chat-empty-im.svg +14 -0
  263. package/dist/images/connectors/dingtalk.png +0 -0
  264. package/dist/images/connectors/dingtalk.svg +18 -0
  265. package/dist/images/connectors/feishu.png +0 -0
  266. package/dist/images/connectors/feishu.svg +12 -0
  267. package/dist/images/connectors/imessage.png +0 -0
  268. package/dist/images/connectors/wecom-agent.png +0 -0
  269. package/dist/images/connectors/wecom-bot.png +0 -0
  270. package/dist/images/connectors/weixin.png +0 -0
  271. package/dist/images/connectors/weixin.svg +19 -0
  272. package/dist/images/connectors/xiaoyi.png +0 -0
  273. package/dist/images/connectors/xiaoyi.svg +12 -0
  274. package/dist/images/create-agent-random-avatar.svg +39 -0
  275. package/dist/images/deepseek.svg +1 -0
  276. package/dist/images/default-ppt-template.png +0 -0
  277. package/dist/images/file-browser-tree/code.svg +60 -0
  278. package/dist/images/file-browser-tree/gitignore.svg +35 -0
  279. package/dist/images/file-browser-tree/image.svg +12 -0
  280. package/dist/images/file-browser-tree/markdown.svg +68 -0
  281. package/dist/images/file-browser-tree/pdf.svg +4 -0
  282. package/dist/images/file-browser-tree/ppt.svg +4 -0
  283. package/dist/images/file-browser-tree/public-file.svg +37 -0
  284. package/dist/images/file-browser-tree/word.svg +60 -0
  285. package/dist/images/file-browser-tree/xlsx.svg +4 -0
  286. package/dist/images/html-preview-toolbar/copy.svg +4 -0
  287. package/dist/images/html-preview-toolbar/open-external.svg +4 -0
  288. package/dist/images/html-preview-toolbar/refresh.svg +4 -0
  289. package/dist/images/information.svg +4 -0
  290. package/dist/images/inspiration/blue-bg.png +0 -0
  291. package/dist/images/inspiration/doc-example.png +0 -0
  292. package/dist/images/inspiration/excel-example.png +0 -0
  293. package/dist/images/inspiration/green-bg.png +0 -0
  294. package/dist/images/inspiration/markdown-example.png +0 -0
  295. package/dist/images/inspiration/orange-bg.png +0 -0
  296. package/dist/images/inspiration/purple-bg.png +0 -0
  297. package/dist/images/inspiration/task-bg.png +0 -0
  298. package/dist/images/inspiration-bg.png +0 -0
  299. package/dist/images/inspiration-products/default.svg +11 -0
  300. package/dist/images/invitation-background-4x.png +0 -0
  301. package/dist/images/kimi.svg +1 -0
  302. package/dist/images/link-blue.svg +4 -0
  303. package/dist/images/link.svg +4 -0
  304. package/dist/images/lobster.svg +118 -0
  305. package/dist/images/login1.svg +93 -0
  306. package/dist/images/login2.svg +80 -0
  307. package/dist/images/login3.svg +44 -0
  308. package/dist/images/login4.svg +18 -0
  309. package/dist/images/mode-default-icon.svg +22 -0
  310. package/dist/images/no-data.svg +26 -0
  311. package/dist/images/no-search-results.svg +25 -0
  312. package/dist/images/ppt-preview/placeholder-main.webp +0 -0
  313. package/dist/images/ppt-preview/placeholder-thumb.webp +0 -0
  314. package/dist/images/ppt-template/dark-tech.png +0 -0
  315. package/dist/images/ppt-template/huawei.png +0 -0
  316. package/dist/images/ppt-template/light-tech.png +0 -0
  317. package/dist/images/ppt-template/paper-humanities.png +0 -0
  318. package/dist/images/ppt-template/template-default.png +0 -0
  319. package/dist/images/ppt-template/template-error.png +0 -0
  320. package/dist/images/ppt-template/template-generate-bg.svg +9639 -0
  321. package/dist/images/qwen.svg +1 -0
  322. package/dist/images/task-list/empty-state.svg +4 -0
  323. package/dist/images/task-list.svg +1 -0
  324. package/dist/images/vendor.svg +4 -0
  325. package/dist/images/version-bg.svg +85 -0
  326. package/dist/images/version.svg +9 -0
  327. package/dist/images/zhipu.svg +1 -0
  328. package/dist/index.html +74 -0
  329. package/dist/loading-point-style.webp +0 -0
  330. package/dist/loading-small.webp +0 -0
  331. package/dist/manifest.json +25 -0
  332. package/package.json +126 -0
@@ -0,0 +1,2 @@
1
+ import{j as e}from"./index-Cb4fQgom.js";function u(){return e.jsx("svg",{className:"h-4 w-4 shrink-0",viewBox:"0 0 16 16",fill:"currentColor","aria-hidden":"true",children:e.jsx("path",{d:"M1.72656 7.17676C1.72656 4.13919 4.189 1.67676 7.22656 1.67676C10.2641 1.67676 12.7266 4.13919 12.7266 7.17676C12.7266 8.50784 12.2537 9.72845 11.4668 10.6798L14.2009 13.3786C14.3974 13.5726 14.3995 13.8892 14.2055 14.0857C14.033 14.2604 13.7637 14.2814 13.568 14.1477L10.7625 11.3897C9.80641 12.1929 8.57299 12.6768 7.22656 12.6768C4.189 12.6768 1.72656 10.2143 1.72656 7.17676ZM11.7266 7.17676C11.7266 4.69147 9.71184 2.67676 7.22656 2.67676C4.74128 2.67676 2.72656 4.69147 2.72656 7.17676C2.72656 9.66205 4.74128 11.6768 7.22656 11.6768C9.71184 11.6768 11.7266 9.66205 11.7266 7.17676Z",fillRule:"evenodd"})})}function d(){return e.jsx("svg",{className:"h-4 w-4 shrink-0",viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M4 4L12 12M12 4L4 12",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function x({value:t,onChange:a,onClear:n,inputClassName:s,wrapperClassName:i,clearAriaLabel:o="清除搜索",...l}){const c=!!n&&t.length>0;return e.jsxs("div",{className:["relative",i].filter(Boolean).join(" "),children:[e.jsxs("span",{className:"pointer-events-none absolute left-3 top-1/2 inline-flex -translate-y-1/2 items-center text-[var(--text-muted)]","data-testid":"search-input-leading-icon",children:[e.jsx(u,{}),e.jsx("span",{className:"ml-1 h-4 w-0","aria-hidden":"true"})]}),e.jsx("input",{...l,value:t,onChange:r=>a(r.target.value,r),className:["search-input-control ui-input w-full px-8",s].filter(Boolean).join(" ")}),c&&e.jsx("button",{type:"button",onClick:n,className:"absolute right-3 top-1/2 inline-flex h-4 w-4 -translate-y-1/2 items-center justify-center text-[var(--text-disabled)] transition-colors hover:text-[var(--text-primary)]","aria-label":o,"data-testid":"search-input-clear-button",children:e.jsx(d,{})})]})}export{x as S};
2
+ //# sourceMappingURL=SearchInput-tux8xXH1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchInput-tux8xXH1.js","sources":["../../src/components/shared/SearchInput.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport type { ChangeEvent, InputHTMLAttributes } from 'react';\n\ntype NativeInputProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'>;\n\ninterface SearchInputProps extends NativeInputProps {\n value: string;\n onChange: (value: string, event: ChangeEvent<HTMLInputElement>) => void;\n onClear?: () => void;\n inputClassName?: string;\n wrapperClassName?: string;\n clearAriaLabel?: string;\n}\n\nfunction SearchIcon() {\n return (\n <svg className=\"h-4 w-4 shrink-0\" viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\">\n <path\n d=\"M1.72656 7.17676C1.72656 4.13919 4.189 1.67676 7.22656 1.67676C10.2641 1.67676 12.7266 4.13919 12.7266 7.17676C12.7266 8.50784 12.2537 9.72845 11.4668 10.6798L14.2009 13.3786C14.3974 13.5726 14.3995 13.8892 14.2055 14.0857C14.033 14.2604 13.7637 14.2814 13.568 14.1477L10.7625 11.3897C9.80641 12.1929 8.57299 12.6768 7.22656 12.6768C4.189 12.6768 1.72656 10.2143 1.72656 7.17676ZM11.7266 7.17676C11.7266 4.69147 9.71184 2.67676 7.22656 2.67676C4.74128 2.67676 2.72656 4.69147 2.72656 7.17676C2.72656 9.66205 4.74128 11.6768 7.22656 11.6768C9.71184 11.6768 11.7266 9.66205 11.7266 7.17676Z\"\n fillRule=\"evenodd\"\n />\n </svg>\n );\n}\n\nfunction ClearIcon() {\n return (\n <svg className=\"h-4 w-4 shrink-0\" viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M4 4L12 12M12 4L4 12\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\nexport function SearchInput({\n value,\n onChange,\n onClear,\n inputClassName,\n wrapperClassName,\n clearAriaLabel = '清除搜索',\n ...rest\n}: SearchInputProps) {\n const showClear = Boolean(onClear) && value.length > 0;\n\n return (\n <div className={['relative', wrapperClassName].filter(Boolean).join(' ')}>\n <span\n className=\"pointer-events-none absolute left-3 top-1/2 inline-flex -translate-y-1/2 items-center text-[var(--text-muted)]\"\n data-testid=\"search-input-leading-icon\"\n >\n <SearchIcon />\n <span className=\"ml-1 h-4 w-0\" aria-hidden=\"true\" />\n </span>\n <input\n {...rest}\n value={value}\n onChange={(event) => onChange(event.target.value, event)}\n className={['search-input-control ui-input w-full px-8', inputClassName].filter(Boolean).join(' ')}\n />\n {showClear && (\n <button\n type=\"button\"\n onClick={onClear}\n className=\"absolute right-3 top-1/2 inline-flex h-4 w-4 -translate-y-1/2 items-center justify-center text-[var(--text-disabled)] transition-colors hover:text-[var(--text-primary)]\"\n aria-label={clearAriaLabel}\n data-testid=\"search-input-clear-button\"\n >\n <ClearIcon />\n </button>\n )}\n </div>\n );\n}\n"],"names":["SearchIcon","jsx","ClearIcon","SearchInput","value","onChange","onClear","inputClassName","wrapperClassName","clearAriaLabel","rest","showClear","jsxs","event"],"mappings":"wCAqBA,SAASA,GAAa,CACpB,OACEC,EAAAA,IAAC,OAAI,UAAU,mBAAmB,QAAQ,YAAY,KAAK,eAAe,cAAY,OACpF,SAAAA,EAAAA,IAAC,OAAA,CACC,EAAE,+kBACF,SAAS,SAAA,CAAA,EAEb,CAEJ,CAEA,SAASC,GAAY,CACnB,OACED,EAAAA,IAAC,OAAI,UAAU,mBAAmB,QAAQ,YAAY,KAAK,OAAO,cAAY,OAC5E,SAAAA,EAAAA,IAAC,OAAA,CACC,EAAE,uBACF,OAAO,eACP,YAAY,MACZ,cAAc,QACd,eAAe,OAAA,CAAA,EAEnB,CAEJ,CAEO,SAASE,EAAY,CAC1B,MAAAC,EACA,SAAAC,EACA,QAAAC,EACA,eAAAC,EACA,iBAAAC,EACA,eAAAC,EAAiB,OACjB,GAAGC,CACL,EAAqB,CACnB,MAAMC,EAAY,EAAQL,GAAYF,EAAM,OAAS,EAErD,OACEQ,EAAAA,KAAC,MAAA,CAAI,UAAW,CAAC,WAAYJ,CAAgB,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,EACrE,SAAA,CAAAI,EAAAA,KAAC,OAAA,CACC,UAAU,iHACV,cAAY,4BAEZ,SAAA,CAAAX,EAAAA,IAACD,EAAA,EAAW,EACZC,EAAAA,IAAC,OAAA,CAAK,UAAU,eAAe,cAAY,MAAA,CAAO,CAAA,CAAA,CAAA,EAEpDA,EAAAA,IAAC,QAAA,CACE,GAAGS,EACJ,MAAAN,EACA,SAAWS,GAAUR,EAASQ,EAAM,OAAO,MAAOA,CAAK,EACvD,UAAW,CAAC,4CAA6CN,CAAc,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,CAAA,CAAA,EAElGI,GACCV,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASK,EACT,UAAU,2KACV,aAAYG,EACZ,cAAY,4BAEZ,eAACP,EAAA,CAAA,CAAU,CAAA,CAAA,CACb,EAEJ,CAEJ"}
@@ -0,0 +1,2 @@
1
+ import{j as n}from"./index-Cb4fQgom.js";import{N as s}from"./NameInitialIcon-DP-6_HQY.js";function c({avatarName:o,avatarUrl:r,className:i="",dataTestId:t}){const e=r==null?void 0:r.trim();return e?n.jsx("img",{src:e,alt:`${o} avatar`,"data-testid":t,className:`h-12 w-12 shrink-0 rounded-[10px] border border-[var(--border-default)] object-cover shadow-sm ${i}`.trim()}):n.jsx(s,{name:o,className:i,dataTestId:t})}export{c as S};
2
+ //# sourceMappingURL=SkillAvatar-DwGvsY4f.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillAvatar-DwGvsY4f.js","sources":["../../src/components/skills-panel/components/SkillAvatar.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { NameInitialIcon } from '../../NameInitialIcon';\n\nexport function SkillAvatar({\n avatarName,\n avatarUrl,\n className = '',\n dataTestId,\n}: {\n avatarName: string;\n avatarUrl?: string | null;\n className?: string;\n dataTestId?: string;\n}) {\n const normalizedAvatarUrl = avatarUrl?.trim();\n\n if (normalizedAvatarUrl) {\n return (\n <img\n src={normalizedAvatarUrl}\n alt={`${avatarName} avatar`}\n data-testid={dataTestId}\n className={`h-12 w-12 shrink-0 rounded-[10px] border border-[var(--border-default)] object-cover shadow-sm ${className}`.trim()}\n />\n );\n }\n\n return <NameInitialIcon name={avatarName} className={className} dataTestId={dataTestId} />;\n}\n"],"names":["SkillAvatar","avatarName","avatarUrl","className","dataTestId","normalizedAvatarUrl","jsx","NameInitialIcon"],"mappings":"0FAQO,SAASA,EAAY,CAC1B,WAAAC,EACA,UAAAC,EACA,UAAAC,EAAY,GACZ,WAAAC,CACF,EAKG,CACD,MAAMC,EAAsBH,GAAA,YAAAA,EAAW,OAEvC,OAAIG,EAEAC,EAAAA,IAAC,MAAA,CACC,IAAKD,EACL,IAAK,GAAGJ,CAAU,UAClB,cAAaG,EACb,UAAW,kGAAkGD,CAAS,GAAG,KAAA,CAAK,CAAA,EAK7HG,EAAAA,IAACC,EAAA,CAAgB,KAAMN,EAAY,UAAAE,EAAsB,WAAAC,EAAwB,CAC1F"}
@@ -0,0 +1,2 @@
1
+ import{r as a,j as e,u as ee,B as $}from"./index-Cb4fQgom.js";import{u as te}from"./useEscapeKey-CEQ6-8GR.js";import{O as E,a as P}from"./OverflowTooltip-CE5PjAb-.js";import{n as se}from"./skill-options-cache-D1BJGTCU.js";import{A as ae}from"./AppModal-BYZTSuch.js";import{s as le,S as ne,C as ie}from"./SkillsTab-kY7MNdxy.js";import{C as B}from"./CenteredLoadingState-DHor-9vF.js";import{S as re}from"./SkillAvatar-DwGvsY4f.js";import{U as ce}from"./UploadSkillModal-DHZL12vm.js";import"./EmptyDataState-6mNx2Xhl.js";import"./NoSearchResultsState-BiiYdZ_Z.js";import"./SearchInput-tux8xXH1.js";import"./NameInitialIcon-DP-6_HQY.js";import"./Alert-D88Fk6to.js";const K={".gitignore":"/icons/file-gitignore.svg"},X={".docx":"/icons/file-docx.svg",".html":"/icons/file-html.svg",".ini":"/icons/file-ini.svg",".json":"/icons/file-json.svg",".md":"/icons/file-md.svg",".py":"/icons/file-py.svg",".sh":"/icons/file-sh.svg",".txt":"/icons/file-txt.svg"},oe="/icons/file-folder.svg",G="/icons/file-html.svg",de="免责声明",ue="请注意:该外部技能来源于第三方,使用外部技能时,您承诺将严格遵守第三方的相关条款。华为云不对第三方产品的合规性和安全性保证,请您在使用前慎重考虑并评估风险。",xe=new Set([".png",".jpg",".jpeg",".gif",".webp",".bmp",".ico",".avif"]);function fe(s){return le(s)}function me(s){return s?"已启用":"已停用"}function Z(s){var l;for(const i of s){if(i.type==="file")return i.path;if((l=i.children)!=null&&l.length){const t=Z(i.children);if(t)return t}}return null}function H(s,l){var i;for(const t of s){if(t.path===l)return t;if((i=t.children)!=null&&i.length){const r=H(t.children,l);if(r)return r}}return null}function J(s){if(s.type==="directory")return oe;const t=(s.path.split("/").filter(Boolean).at(-1)??s.name).toLowerCase();if(K[t])return K[t];const r=t.lastIndexOf(".");if(r>0){const x=t.slice(r);if(X[x])return X[x]}return G}function pe(s){if(!s)return!1;const l=s.toLowerCase(),i=l.lastIndexOf(".");return i<0?!1:xe.has(l.slice(i))}function U({label:s,value:l,className:i=""}){return e.jsxs("div",{className:`space-y-2 ${i}`.trim(),children:[e.jsx("p",{className:"text-xs font-medium tracking-[0.02em] text-[var(--text-label-secondary)]",children:s}),typeof l=="string"?e.jsx("p",{className:"text-xs leading-6 text-[var(--text-primary)]",children:l}):l]})}function V({nodes:s,selectedPath:l,onSelect:i,depth:t=0}){return e.jsx("ul",{className:"space-y-1.5",children:s.map(r=>{var x;return e.jsxs("li",{children:[e.jsxs("button",{type:"button",onClick:()=>i(r),className:`flex w-full items-center gap-2 rounded-[10px] px-3 py-[7px] text-left text-sm transition ${l===r.path?"bg-[var(--surface-card-muted)]":""}`,style:{paddingLeft:`${t*18+12}px`},children:[e.jsx("span",{className:`inline-flex h-5 min-w-5 items-center justify-center overflow-hidden rounded-[6px] ${l===r.path?"opacity-100":"opacity-90"}`,children:e.jsx("img",{src:J(r),alt:"","aria-hidden":"true","data-testid":"skill-detail-file-tree-icon","data-path":r.path,className:"h-4 w-4 shrink-0 object-contain"})}),e.jsx("span",{className:"min-w-0 flex-1 text-xs",children:r.name})]}),(x=r.children)!=null&&x.length?e.jsx(V,{nodes:r.children,selectedPath:l,onSelect:i,depth:t+1}):null]},r.path)})})}function he({skillName:s,avatarUrl:l,onBack:i}){var F,M,D;const[t,r]=a.useState(null),[x,N]=a.useState(null),[C,w]=a.useState(!0),[c,h]=a.useState(null),[o,f]=a.useState(null),[j,y]=a.useState(!1),[S,g]=a.useState(null),[T,L]=a.useState({});a.useEffect(()=>{const n=new AbortController;return(async()=>{w(!0),N(null);try{const u=await P(`/api/skills/detail?name=${encodeURIComponent(s)}`,{signal:n.signal});if(!u.ok){const A=await u.json().catch(()=>({}));N(A.error??`加载失败 (${u.status})`),r(null);return}const v=await u.json();r(v)}catch(u){if(u instanceof DOMException&&u.name==="AbortError")return;N("网络错误"),r(null)}finally{n.signal.aborted||w(!1)}})(),()=>n.abort()},[s]);const _=a.useMemo(()=>{var n;return((n=t==null?void 0:t.triggers)==null?void 0:n.join(", "))||"--"},[t==null?void 0:t.triggers]),d=((F=t==null?void 0:t.category)==null?void 0:F.trim())||"其他",m=(t==null?void 0:t.name)??s,p=((M=t==null?void 0:t.description)==null?void 0:M.trim())||"--",k=(t==null?void 0:t.source)==="external",z=a.useMemo(()=>{var n;return c?c.split("/").filter(Boolean).at(-1)??c:(n=t==null?void 0:t.fileTree)!=null&&n.length?"请选择文件":"暂无文件"},[t==null?void 0:t.fileTree,c]),b=a.useMemo(()=>{var n;return!((n=t==null?void 0:t.fileTree)!=null&&n.length)||!c?null:H(t.fileTree,c)},[t==null?void 0:t.fileTree,c]),O=a.useMemo(()=>pe(c),[c]);a.useEffect(()=>{const n=t==null?void 0:t.fileTree;if(!(n!=null&&n.length)){h(null);return}h(I=>{var u;return I??Z(n)??((u=n[0])==null?void 0:u.path)??null})},[t]),a.useEffect(()=>{f(null),g(null),L({})},[s]),a.useEffect(()=>{if(!c){f(null),g(null);return}if(O){f({path:c,content:"暂不支持图片预览",size:(b==null?void 0:b.size)??0,mime:"image/*",truncated:!1}),g(null),y(!1);return}const n=T[c];if(n){f(n),g(null),y(!1);return}const I=new AbortController;return(async()=>{y(!0),g(null);try{const v=await P(`/api/skills/file?name=${encodeURIComponent(s)}&path=${encodeURIComponent(c)}`,{signal:I.signal});if(!v.ok){const R=await v.json().catch(()=>({}));f(null),g(R.error??`加载文件失败 (${v.status})`);return}const A=await v.json();f(A),L(R=>({...R,[c]:A}))}catch(v){if(v instanceof DOMException&&v.name==="AbortError")return;f(null),g("文件预览加载失败")}finally{I.signal.aborted||y(!1)}})(),()=>I.abort()},[T,b==null?void 0:b.size,c,O,s]);const Q=n=>{n.type==="file"&&h(n.path)};return C?e.jsx(B,{}):e.jsxs("div",{className:"flex h-full min-h-0 flex-col","data-testid":"skill-detail-panel",children:[e.jsx("div",{className:"shrink-0 pb-6",children:e.jsxs("div",{className:"flex min-w-0 items-center gap-2 text-sm text-[var(--text-muted)]",children:[e.jsx("button",{type:"button",onClick:i,"data-testid":"skill-detail-breadcrumb-back",className:"transition hover:underline shrink-0",children:"我的技能"}),e.jsx("span",{children:"/"}),e.jsx(E,{content:m,className:"min-w-0",children:e.jsx("span",{className:"block truncate font-medium text-[var(--text-primary)]","data-testid":"skill-detail-breadcrumb-title",children:m})})]})}),e.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto",children:[x?e.jsx("p",{className:"ui-status-error mb-4 rounded-[var(--radius-md)] px-3 py-2 text-sm",children:x}):null,t?e.jsxs("div",{className:"flex min-h-0 flex-col gap-8 pb-2",children:[e.jsx("section",{className:"shrink-0 space-y-5",children:e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx(re,{avatarName:s,avatarUrl:l,dataTestId:"skill-detail-avatar",className:"h-[56px] w-[56px] rounded-[14px]"}),e.jsxs("div",{className:"min-w-0 flex-1 flex flex-col gap-1",children:[e.jsx(E,{content:m,className:"w-full",children:e.jsx("h2",{className:"max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-[20px] font-semibold leading-[30px] text-[var(--text-primary)]","data-testid":"skill-detail-title",children:m})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-xs text-[var(--text-secondary)]",children:[e.jsx("span",{className:"ui-badge-muted","data-testid":"skill-detail-category-badge",children:d}),e.jsx("span",{className:"ui-badge-muted","data-testid":"skill-detail-source-badge",children:fe(t.source)}),e.jsx("span",{className:"ui-badge-muted","data-testid":"skill-detail-status-badge",children:me(t.enabled)})]})]})]})}),e.jsxs("section",{className:"shrink-0 space-y-5","data-testid":"skill-detail-basic-info",children:[e.jsx("h3",{className:"text-base font-semibold text-[var(--text-primary)]",children:"基础信息"}),e.jsxs("div",{className:"grid gap-x-8 gap-y-5 md:grid-cols-3",children:[e.jsx(U,{label:"名称",value:m}),e.jsx(U,{label:"触发词",value:e.jsx(E,{content:_,className:"w-full",children:e.jsx("p",{className:"line-clamp-2 min-h-[44px] text-xs leading-6",children:_})})}),e.jsx(U,{label:"描述",value:e.jsx(E,{content:p,className:"w-full",children:e.jsx("p",{className:"line-clamp-2 min-h-[44px] text-xs leading-6",children:p})})})]})]}),e.jsxs("section",{className:"shrink-0 space-y-3","data-testid":"skill-detail-file-workspace",children:[e.jsx("h3",{className:"text-base font-semibold text-[var(--text-primary)]",children:"文件目录"}),e.jsx("div",{className:"flex h-[440px] overflow-hidden rounded-[20px] border border-[var(--border-default)] bg-[var(--surface-card)]",children:e.jsxs("div",{className:"flex min-h-0 flex-1 flex-col md:flex-row",children:[e.jsxs("aside",{className:"flex w-full shrink-0 flex-col border-b border-[var(--border-default)] bg-[var(--surface-panel)] md:w-[280px] md:border-b-0 md:border-r",children:[e.jsxs("div",{className:"border-b border-[var(--border-default)] px-4 py-3 flex items-center gap-2",children:[e.jsx("img",{src:"/icons/file.svg",className:"h-4 w-4 shrink-0 object-contain"}),e.jsx("div",{className:"text-xs",children:"File"})]}),e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto px-3 py-3",children:(D=t.fileTree)!=null&&D.length?e.jsx(V,{nodes:t.fileTree,selectedPath:c,onSelect:Q}):e.jsx("p",{className:"px-2 py-4 text-sm text-[var(--text-muted)]",children:"暂无文件结构数据。"})})]}),e.jsxs("div",{className:"flex min-h-0 min-w-0 flex-1 flex-col bg-[var(--surface-card)]",children:[e.jsx("div",{className:"border-b border-[var(--border-default)] px-5 py-3 text-xs",children:e.jsxs("div",{className:"grid min-w-0 grid-cols-[minmax(0,1fr)_fit-content(200px)] items-center gap-3",children:[e.jsxs("div",{className:"flex min-w-0 items-center gap-2 overflow-hidden",children:[e.jsx("img",{src:b?J(b):G,alt:"","aria-hidden":"true","data-testid":"skill-detail-preview-header-icon",className:"h-4 w-4 shrink-0 object-contain"}),e.jsx(E,{content:z,className:"min-w-0 overflow-hidden",children:e.jsx("div",{className:"w-full min-w-0 truncate",children:z})})]}),o?e.jsx(E,{content:`${o.mime} · ${o.size} B`,className:"min-w-0 overflow-hidden",children:e.jsx("div",{className:"w-full min-w-0 truncate text-right text-xs text-[var(--text-muted)]",children:`${o.mime} · ${o.size} B`})}):null]})}),e.jsxs("div",{className:"min-h-0 flex-1 overflow-y-auto px-5 py-5",children:[j?e.jsx("div",{className:"flex h-full min-h-0 items-center justify-center","data-testid":"skill-detail-preview-loading-shell",children:e.jsx(B,{})}):null,!j&&S?e.jsx("p",{className:"ui-status-error rounded-[var(--radius-md)] px-3 py-2 text-sm",children:S}):null,!j&&!S&&o?e.jsxs("div",{className:"space-y-3","data-testid":"skill-detail-file-preview",children:[o.truncated?e.jsx("p",{className:"rounded-[12px] border border-[var(--border-default)] bg-[var(--surface-panel)] px-3 py-2 text-xs text-[var(--text-muted)]",children:"文件内容过长,当前仅展示前 1MB。"}):null,e.jsx("pre",{className:"overflow-x-auto whitespace-pre-wrap break-words font-sans text-sm leading-6",style:{overflowWrap:"anywhere"},children:o.content})]}):null,!j&&!S&&!o?e.jsx("p",{className:"text-sm text-[var(--text-muted)]",children:"请选择要预览的文件。"}):null]})]})]})})]}),k?e.jsxs("section",{className:"shrink-0 space-y-3","data-testid":"skill-detail-disclaimer",children:[e.jsx("h3",{className:"text-base font-semibold text-[var(--text-primary)]",children:de}),e.jsx("div",{className:"rounded-[16px] border border-[var(--border-default)] bg-[var(--surface-panel)] p-6",children:e.jsx("p",{className:"text-xs leading-6 text-[var(--text-secondary)]",children:ue})})]}):null]}):null]})]})}const ge="我的技能",ve="技能广场",je="技能上传成功",W="office-claw:skills-plaza-risk-ack:v1",q="cat-cafe:skills-plaza-risk-ack:v1",be="风险提示",we="请注意,部分技能来源于第三方,当您使用第三方外部技能时,您承诺将严格遵守第三方的相关条款(包括但不限于license协议)。华为云不对第三方产品的合规性和安全性保证,请您使用前慎重考虑并评估风险。",ye="更新成功",Y="更新失败";function Se(){if(typeof window>"u")return!1;try{return window.localStorage.getItem(W)==="1"?!0:window.localStorage.getItem(q)==="1"}catch{return!1}}function Ne(){if(!(typeof window>"u"))try{window.localStorage.setItem(W,"1");try{window.localStorage.removeItem(q)}catch{}}catch{}}function ke(){const s=ee(d=>d.addToast),[l,i]=a.useState("installed"),[t,r]=a.useState(!1),[x,N]=a.useState(0),[C,w]=a.useState(null),[c,h]=a.useState(!1),[o,f]=a.useState(new Set),[j,y]=a.useState(null),S=a.useRef(!1);te({enabled:c,onEscape:()=>h(!1)});const g=()=>{if(w(null),Se()){i("plaza");return}h(!0)},T=()=>{Ne(),h(!1),i("plaza")};a.useEffect(()=>{l!=="installed"||S.current||(S.current=!0,(async()=>{try{const d=await P("/api/skills/check-updates",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({force:!1})});if(!d.ok)return;const p=(await d.json()).updates??[];f(new Set(p.map(k=>k.name).filter(Boolean)))}catch{}})())},[l]);const L=a.useCallback(async d=>{if(!(j||!o.has(d))){y(d);try{const m=await P("/api/skills/update",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:d})});if(!m.ok){const p=await m.json().catch(()=>({}));s({type:"error",title:Y,message:p.error??`HTTP ${m.status}`,duration:5e3});return}f(p=>{const k=new Set(p);return k.delete(d),k}),se(),N(p=>p+1),s({type:"success",title:ye,message:`"${d}" 已更新`,duration:4e3})}catch{s({type:"error",title:Y,message:"网络错误,请重试",duration:5e3})}finally{y(null)}}},[s,o,j]),_=a.useMemo(()=>o,[o]);return C?e.jsx("div",{className:"ui-page-shell gap-2 overflow-hidden",children:e.jsx(he,{skillName:C.skillName,avatarUrl:C.avatarUrl,onBack:()=>w(null)})}):e.jsxs("div",{className:"ui-page-shell gap-2 overflow-hidden",children:[e.jsx(ce,{open:t,onClose:()=>r(!1),onSuccess:()=>{i("installed"),w(null),N(d=>d+1),s({type:"success",title:"上传成功",message:je,duration:4e3})}}),e.jsx(ae,{open:c,onClose:()=>h(!1),title:be,panelClassName:"w-[550px]",disableBackdropClose:!0,showCloseButton:!0,children:e.jsxs("div",{className:"space-y-4 pt-[18px]",children:[e.jsx("p",{className:"text-[12px] leading-[18px] text-[var(--text-secondary)]",children:we}),e.jsxs("div",{className:"flex items-center justify-end gap-2",children:[e.jsx($,{variant:"default",onClick:()=>h(!1),children:"取消"}),e.jsx($,{variant:"major",onClick:T,children:"我已同意"})]})]})}),e.jsx("div",{className:"ui-page-header-inline items-start border-b",children:e.jsxs("div",{className:"flex flex-col gap-1",children:[e.jsxs("div",{className:"flex items-center gap-5",children:[e.jsx("button",{type:"button",onClick:()=>i("installed"),className:`ui-tab-trigger ${l==="installed"?"ui-tab-trigger-active":""}`,children:ge}),e.jsx("button",{type:"button",onClick:()=>{g()},className:`ui-tab-trigger ${l==="plaza"?"ui-tab-trigger-active":""}`,children:ve})]}),e.jsx("div",{className:"ui-tab-indicator w-[56px]",style:{transform:l==="plaza"?"translateX(78px)":"translateX(0)"}})]})}),e.jsx("div",{className:"flex-1 min-h-0 overflow-hidden",children:l==="plaza"?e.jsx(ne,{}):e.jsx(ie,{onImport:()=>r(!0),onSelectSkill:w,onUpdateSkill:L,skillUpdates:_,updatingSkillId:j,refreshSignal:x})})]})}function De(){return e.jsx("div",{className:"h-full overflow-hidden ui-shell-surface px-8 py-8",children:e.jsx(ke,{})})}export{De as default};
2
+ //# sourceMappingURL=SkillsPage-ppqwKMvj.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsPage-ppqwKMvj.js","sources":["../../src/components/skills-panel/components/SkillDetailView.tsx","../../src/components/skills-panel/SkillsPanel.tsx","../../src/pages/SkillsPage.tsx"],"sourcesContent":["/*\n *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n\"use client\";\n\nimport { type ReactNode, useEffect, useMemo, useState } from \"react\";\nimport { apiFetch } from \"@/utils/api-client\";\nimport { skillSourceToLabel } from \"@/utils/skill-source-label\";\nimport { CenteredLoadingState } from \"../../shared/CenteredLoadingState\";\nimport { OverflowTooltip } from \"../../shared/OverflowTooltip\";\nimport { SkillAvatar } from \"./SkillAvatar\";\n\ninterface SkillDetailFileTreeNode {\n name: string;\n path: string;\n type: \"file\" | \"directory\";\n size?: number;\n children?: SkillDetailFileTreeNode[];\n}\n\ninterface SkillDetailResponse {\n id: string;\n name: string;\n description?: string;\n triggers?: string[];\n category?: string;\n source: \"builtin\" | \"external\";\n enabled: boolean;\n installedAt?: string;\n mounts?: Record<string, boolean>;\n fileTree?: SkillDetailFileTreeNode[];\n agents: Record<string, boolean>;\n}\n\ninterface SkillFilePreviewResponse {\n path: string;\n content: string;\n size: number;\n mime: string;\n truncated: boolean;\n}\n\nconst SPECIAL_FILE_ICON_MAP: Record<string, string> = {\n \".gitignore\": \"/icons/file-gitignore.svg\",\n};\n\nconst FILE_EXTENSION_ICON_MAP: Record<string, string> = {\n \".docx\": \"/icons/file-docx.svg\",\n \".html\": \"/icons/file-html.svg\",\n \".ini\": \"/icons/file-ini.svg\",\n \".json\": \"/icons/file-json.svg\",\n \".md\": \"/icons/file-md.svg\",\n \".py\": \"/icons/file-py.svg\",\n \".sh\": \"/icons/file-sh.svg\",\n \".txt\": \"/icons/file-txt.svg\",\n};\n\nconst DIRECTORY_ICON_SRC = \"/icons/file-folder.svg\";\nconst DEFAULT_FILE_ICON_SRC = \"/icons/file-html.svg\";\nconst DISCLAIMER_TITLE = \"免责声明\";\nconst THIRD_PARTY_DISCLAIMER_TEXT =\n \"请注意:该外部技能来源于第三方,使用外部技能时,您承诺将严格遵守第三方的相关条款。华为云不对第三方产品的合规性和安全性保证,请您在使用前慎重考虑并评估风险。\";\nconst IMAGE_FILE_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".webp\",\n \".bmp\",\n \".ico\",\n \".avif\",\n]);\n\nfunction sourceLabel(source: SkillDetailResponse[\"source\"]): string {\n return skillSourceToLabel(source);\n}\n\nfunction statusLabel(value: boolean): string {\n return value ? \"已启用\" : \"已停用\";\n}\n\nfunction formatInstalledAt(value?: string): string {\n if (!value) return \"未知\";\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return value;\n return date.toLocaleString(\"zh-CN\", { hour12: false });\n}\n\nfunction findFirstFile(nodes: SkillDetailFileTreeNode[]): string | null {\n for (const node of nodes) {\n if (node.type === \"file\") return node.path;\n if (node.children?.length) {\n const nestedPath = findFirstFile(node.children);\n if (nestedPath) return nestedPath;\n }\n }\n return null;\n}\n\nfunction findNodeByPath(\n nodes: SkillDetailFileTreeNode[],\n targetPath: string,\n): SkillDetailFileTreeNode | null {\n for (const node of nodes) {\n if (node.path === targetPath) return node;\n if (node.children?.length) {\n const nestedNode = findNodeByPath(node.children, targetPath);\n if (nestedNode) return nestedNode;\n }\n }\n return null;\n}\n\nfunction getFileTreeIconSrc(node: SkillDetailFileTreeNode): string {\n if (node.type === \"directory\") return DIRECTORY_ICON_SRC;\n\n const segments = node.path.split(\"/\").filter(Boolean);\n const fileName = segments.at(-1) ?? node.name;\n const normalizedFileName = fileName.toLowerCase();\n\n if (SPECIAL_FILE_ICON_MAP[normalizedFileName]) {\n return SPECIAL_FILE_ICON_MAP[normalizedFileName];\n }\n\n const extensionIndex = normalizedFileName.lastIndexOf(\".\");\n if (extensionIndex > 0) {\n const extension = normalizedFileName.slice(extensionIndex);\n if (FILE_EXTENSION_ICON_MAP[extension]) {\n return FILE_EXTENSION_ICON_MAP[extension];\n }\n }\n\n return DEFAULT_FILE_ICON_SRC;\n}\n\nfunction isImageFilePath(filePath: string | null): boolean {\n if (!filePath) return false;\n\n const normalizedPath = filePath.toLowerCase();\n const extensionIndex = normalizedPath.lastIndexOf(\".\");\n if (extensionIndex < 0) return false;\n\n return IMAGE_FILE_EXTENSIONS.has(normalizedPath.slice(extensionIndex));\n}\n\nfunction BasicInfoField({\n label,\n value,\n className = \"\",\n}: {\n label: string;\n value: ReactNode;\n className?: string;\n}) {\n return (\n <div className={`space-y-2 ${className}`.trim()}>\n <p className=\"text-xs font-medium tracking-[0.02em] text-[var(--text-label-secondary)]\">\n {label}\n </p>\n {typeof value === \"string\" ? (\n <p className=\"text-xs leading-6 text-[var(--text-primary)]\">{value}</p>\n ) : (\n value\n )}\n </div>\n );\n}\n\nfunction FileTreeBranch({\n nodes,\n selectedPath,\n onSelect,\n depth = 0,\n}: {\n nodes: SkillDetailFileTreeNode[];\n selectedPath: string | null;\n onSelect: (node: SkillDetailFileTreeNode) => void;\n depth?: number;\n}) {\n return (\n <ul className=\"space-y-1.5\">\n {nodes.map((node) => (\n <li key={node.path}>\n <button\n type=\"button\"\n onClick={() => onSelect(node)}\n className={`flex w-full items-center gap-2 rounded-[10px] px-3 py-[7px] text-left text-sm transition ${\n selectedPath === node.path ? \"bg-[var(--surface-card-muted)]\" : \"\"\n }`}\n style={{ paddingLeft: `${depth * 18 + 12}px` }}\n >\n <span\n className={`inline-flex h-5 min-w-5 items-center justify-center overflow-hidden rounded-[6px] ${\n selectedPath === node.path ? \"opacity-100\" : \"opacity-90\"\n }`}\n >\n <img\n src={getFileTreeIconSrc(node)}\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"skill-detail-file-tree-icon\"\n data-path={node.path}\n className=\"h-4 w-4 shrink-0 object-contain\"\n />\n </span>\n <span className=\"min-w-0 flex-1 text-xs\">{node.name}</span>\n </button>\n {node.children?.length ? (\n <FileTreeBranch\n nodes={node.children}\n selectedPath={selectedPath}\n onSelect={onSelect}\n depth={depth + 1}\n />\n ) : null}\n </li>\n ))}\n </ul>\n );\n}\n\nexport function SkillDetailView({\n skillName,\n avatarUrl,\n onBack,\n}: {\n skillName: string;\n avatarUrl?: string | null;\n onBack: () => void;\n}) {\n const [detail, setDetail] = useState<SkillDetailResponse | null>(null);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [selectedPath, setSelectedPath] = useState<string | null>(null);\n const [filePreview, setFilePreview] =\n useState<SkillFilePreviewResponse | null>(null);\n const [filePreviewLoading, setFilePreviewLoading] = useState(false);\n const [filePreviewError, setFilePreviewError] = useState<string | null>(null);\n const [previewCache, setPreviewCache] = useState<\n Record<string, SkillFilePreviewResponse>\n >({});\n\n useEffect(() => {\n const controller = new AbortController();\n\n const loadDetail = async () => {\n setLoading(true);\n setError(null);\n try {\n const res = await apiFetch(\n `/api/skills/detail?name=${encodeURIComponent(skillName)}`,\n {\n signal: controller.signal,\n },\n );\n if (!res.ok) {\n const payload = (await res.json().catch(() => ({}))) as {\n error?: string;\n };\n setError(payload.error ?? `加载失败 (${res.status})`);\n setDetail(null);\n return;\n }\n const data = (await res.json()) as SkillDetailResponse;\n setDetail(data);\n } catch (loadError) {\n if (\n loadError instanceof DOMException &&\n loadError.name === \"AbortError\"\n )\n return;\n setError(\"网络错误\");\n setDetail(null);\n } finally {\n if (!controller.signal.aborted) {\n setLoading(false);\n }\n }\n };\n\n void loadDetail();\n\n return () => controller.abort();\n }, [skillName]);\n\n const triggerLabel = useMemo(\n () => detail?.triggers?.join(\", \") || \"--\",\n [detail?.triggers],\n );\n const categoryLabel = detail?.category?.trim() || \"其他\";\n const resolvedTitle = detail?.name ?? skillName;\n const resolvedDescription = detail?.description?.trim() || \"--\";\n const hasDisclaimer = detail?.source === \"external\";\n const selectedFileLabel = useMemo(() => {\n if (!selectedPath)\n return detail?.fileTree?.length ? \"请选择文件\" : \"暂无文件\";\n return selectedPath.split(\"/\").filter(Boolean).at(-1) ?? selectedPath;\n }, [detail?.fileTree, selectedPath]);\n const selectedFileNode = useMemo(() => {\n if (!detail?.fileTree?.length || !selectedPath) return null;\n return findNodeByPath(detail.fileTree, selectedPath);\n }, [detail?.fileTree, selectedPath]);\n const selectedPathIsImage = useMemo(() => isImageFilePath(selectedPath), [selectedPath]);\n\n useEffect(() => {\n const fileTree = detail?.fileTree;\n if (!fileTree?.length) {\n setSelectedPath(null);\n return;\n }\n setSelectedPath(\n (current) =>\n current ?? findFirstFile(fileTree) ?? fileTree[0]?.path ?? null,\n );\n }, [detail]);\n\n useEffect(() => {\n setFilePreview(null);\n setFilePreviewError(null);\n setPreviewCache({});\n }, [skillName]);\n\n useEffect(() => {\n if (!selectedPath) {\n setFilePreview(null);\n setFilePreviewError(null);\n return;\n }\n\n if (selectedPathIsImage) {\n setFilePreview({\n path: selectedPath,\n content: \"暂不支持图片预览\",\n size: selectedFileNode?.size ?? 0,\n mime: \"image/*\",\n truncated: false,\n });\n setFilePreviewError(null);\n setFilePreviewLoading(false);\n return;\n }\n\n const cachedPreview = previewCache[selectedPath];\n if (cachedPreview) {\n setFilePreview(cachedPreview);\n setFilePreviewError(null);\n setFilePreviewLoading(false);\n return;\n }\n\n const controller = new AbortController();\n\n const loadFilePreview = async () => {\n setFilePreviewLoading(true);\n setFilePreviewError(null);\n try {\n const res = await apiFetch(\n `/api/skills/file?name=${encodeURIComponent(skillName)}&path=${encodeURIComponent(selectedPath)}`,\n {\n signal: controller.signal,\n },\n );\n if (!res.ok) {\n const payload = (await res.json().catch(() => ({}))) as {\n error?: string;\n };\n setFilePreview(null);\n setFilePreviewError(payload.error ?? `加载文件失败 (${res.status})`);\n return;\n }\n const data = (await res.json()) as SkillFilePreviewResponse;\n setFilePreview(data);\n setPreviewCache((current) => ({ ...current, [selectedPath]: data }));\n } catch (loadError) {\n if (\n loadError instanceof DOMException &&\n loadError.name === \"AbortError\"\n )\n return;\n setFilePreview(null);\n setFilePreviewError(\"文件预览加载失败\");\n } finally {\n if (!controller.signal.aborted) {\n setFilePreviewLoading(false);\n }\n }\n };\n\n void loadFilePreview();\n\n return () => controller.abort();\n }, [previewCache, selectedFileNode?.size, selectedPath, selectedPathIsImage, skillName]);\n\n const handleSelectNode = (node: SkillDetailFileTreeNode) => {\n if (node.type !== \"file\") return;\n setSelectedPath(node.path);\n };\n\n if (loading) return <CenteredLoadingState />;\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-col\"\n data-testid=\"skill-detail-panel\"\n >\n <div className=\"shrink-0 pb-6\">\n <div className=\"flex min-w-0 items-center gap-2 text-sm text-[var(--text-muted)]\">\n <button\n type=\"button\"\n onClick={onBack}\n data-testid=\"skill-detail-breadcrumb-back\"\n className=\"transition hover:underline shrink-0\"\n >\n 我的技能\n </button>\n <span>/</span>\n <OverflowTooltip content={resolvedTitle} className=\"min-w-0\">\n <span\n className=\"block truncate font-medium text-[var(--text-primary)]\"\n data-testid=\"skill-detail-breadcrumb-title\"\n >\n {resolvedTitle}\n </span>\n </OverflowTooltip>\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\">\n {error ? (\n <p className=\"ui-status-error mb-4 rounded-[var(--radius-md)] px-3 py-2 text-sm\">\n {error}\n </p>\n ) : null}\n\n {detail ? (\n <div className=\"flex min-h-0 flex-col gap-8 pb-2\">\n <section className=\"shrink-0 space-y-5\">\n <div className=\"flex items-start gap-4\">\n <SkillAvatar\n avatarName={skillName}\n avatarUrl={avatarUrl}\n dataTestId=\"skill-detail-avatar\"\n className=\"h-[56px] w-[56px] rounded-[14px]\"\n />\n <div className=\"min-w-0 flex-1 flex flex-col gap-1\">\n <OverflowTooltip content={resolvedTitle} className=\"w-full\">\n <h2\n className=\"max-w-full overflow-hidden text-ellipsis whitespace-nowrap text-[20px] font-semibold leading-[30px] text-[var(--text-primary)]\"\n data-testid=\"skill-detail-title\"\n >\n {resolvedTitle}\n </h2>\n </OverflowTooltip>\n <div className=\"flex flex-wrap items-center gap-2 text-xs text-[var(--text-secondary)]\">\n <span\n className=\"ui-badge-muted\"\n data-testid=\"skill-detail-category-badge\"\n >\n {categoryLabel}\n </span>\n <span\n className=\"ui-badge-muted\"\n data-testid=\"skill-detail-source-badge\"\n >\n {sourceLabel(detail.source)}\n </span>\n <span\n className=\"ui-badge-muted\"\n data-testid=\"skill-detail-status-badge\"\n >\n {statusLabel(detail.enabled)}\n </span>\n </div>\n </div>\n </div>\n </section>\n <section\n className=\"shrink-0 space-y-5\"\n data-testid=\"skill-detail-basic-info\"\n >\n <h3 className=\"text-base font-semibold text-[var(--text-primary)]\">\n 基础信息\n </h3>\n <div className=\"grid gap-x-8 gap-y-5 md:grid-cols-3\">\n <BasicInfoField label=\"名称\" value={resolvedTitle} />\n <BasicInfoField\n label=\"触发词\"\n value={\n <OverflowTooltip content={triggerLabel} className=\"w-full\">\n <p className=\"line-clamp-2 min-h-[44px] text-xs leading-6\">\n {triggerLabel}\n </p>\n </OverflowTooltip>\n }\n />\n <BasicInfoField\n label=\"描述\"\n value={\n <OverflowTooltip\n content={resolvedDescription}\n className=\"w-full\"\n >\n <p className=\"line-clamp-2 min-h-[44px] text-xs leading-6\">\n {resolvedDescription}\n </p>\n </OverflowTooltip>\n }\n />\n </div>\n </section>\n <section\n className=\"shrink-0 space-y-3\"\n data-testid=\"skill-detail-file-workspace\"\n >\n <h3 className=\"text-base font-semibold text-[var(--text-primary)]\">\n 文件目录\n </h3>\n <div\n className={`flex h-[440px] overflow-hidden rounded-[20px] border border-[var(--border-default)] bg-[var(--surface-card)]`}\n >\n <div className=\"flex min-h-0 flex-1 flex-col md:flex-row\">\n <aside className=\"flex w-full shrink-0 flex-col border-b border-[var(--border-default)] bg-[var(--surface-panel)] md:w-[280px] md:border-b-0 md:border-r\">\n <div className=\"border-b border-[var(--border-default)] px-4 py-3 flex items-center gap-2\">\n <img src=\"/icons/file.svg\" className=\"h-4 w-4 shrink-0 object-contain\" />\n <div className=\"text-xs\">File</div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-3 py-3\">\n {detail.fileTree?.length ? (\n <FileTreeBranch\n nodes={detail.fileTree}\n selectedPath={selectedPath}\n onSelect={handleSelectNode}\n />\n ) : (\n <p className=\"px-2 py-4 text-sm text-[var(--text-muted)]\">\n 暂无文件结构数据。\n </p>\n )}\n </div>\n </aside>\n <div className=\"flex min-h-0 min-w-0 flex-1 flex-col bg-[var(--surface-card)]\">\n <div className=\"border-b border-[var(--border-default)] px-5 py-3 text-xs\">\n <div className=\"grid min-w-0 grid-cols-[minmax(0,1fr)_fit-content(200px)] items-center gap-3\">\n <div className=\"flex min-w-0 items-center gap-2 overflow-hidden\">\n <img\n src={\n selectedFileNode\n ? getFileTreeIconSrc(selectedFileNode)\n : DEFAULT_FILE_ICON_SRC\n }\n alt=\"\"\n aria-hidden=\"true\"\n data-testid=\"skill-detail-preview-header-icon\"\n className=\"h-4 w-4 shrink-0 object-contain\"\n />\n <OverflowTooltip content={selectedFileLabel} className=\"min-w-0 overflow-hidden\">\n <div className=\"w-full min-w-0 truncate\">{selectedFileLabel}</div>\n </OverflowTooltip>\n </div>\n {filePreview ? (\n <OverflowTooltip\n content={`${filePreview.mime} · ${filePreview.size} B`}\n className=\"min-w-0 overflow-hidden\"\n >\n <div className=\"w-full min-w-0 truncate text-right text-xs text-[var(--text-muted)]\">\n {`${filePreview.mime} · ${filePreview.size} B`}\n </div>\n </OverflowTooltip>\n ) : null}\n </div>\n </div>\n <div className=\"min-h-0 flex-1 overflow-y-auto px-5 py-5\">\n {filePreviewLoading ? (\n <div\n className=\"flex h-full min-h-0 items-center justify-center\"\n data-testid=\"skill-detail-preview-loading-shell\"\n >\n <CenteredLoadingState />\n </div>\n ) : null}\n {!filePreviewLoading && filePreviewError ? (\n <p className=\"ui-status-error rounded-[var(--radius-md)] px-3 py-2 text-sm\">\n {filePreviewError}\n </p>\n ) : null}\n {!filePreviewLoading &&\n !filePreviewError &&\n filePreview ? (\n <div\n className=\"space-y-3\"\n data-testid=\"skill-detail-file-preview\"\n >\n {filePreview.truncated ? (\n <p className=\"rounded-[12px] border border-[var(--border-default)] bg-[var(--surface-panel)] px-3 py-2 text-xs text-[var(--text-muted)]\">\n 文件内容过长,当前仅展示前 1MB。\n </p>\n ) : null}\n <pre\n className=\"overflow-x-auto whitespace-pre-wrap break-words font-sans text-sm leading-6\"\n style={{ overflowWrap: \"anywhere\" }}\n >\n {filePreview.content}\n </pre>\n </div>\n ) : null}\n {!filePreviewLoading &&\n !filePreviewError &&\n !filePreview ? (\n <p className=\"text-sm text-[var(--text-muted)]\">\n 请选择要预览的文件。\n </p>\n ) : null}\n </div>\n </div>\n </div>\n </div>\n </section>\n {hasDisclaimer ? (\n <section\n className=\"shrink-0 space-y-3\"\n data-testid=\"skill-detail-disclaimer\"\n >\n <h3 className=\"text-base font-semibold text-[var(--text-primary)]\">\n {DISCLAIMER_TITLE}\n </h3>\n <div className=\"rounded-[16px] border border-[var(--border-default)] bg-[var(--surface-panel)] p-6\">\n <p className=\"text-xs leading-6 text-[var(--text-secondary)]\">\n {THIRD_PARTY_DISCLAIMER_TEXT}\n </p>\n </div>\n </section>\n ) : null}\n </div>\n ) : null}\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useEscapeKey } from '@/hooks/useEscapeKey';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { notifySkillOptionsChanged } from '@/utils/skill-options-cache';\nimport { Button } from '../shared/Button';\nimport { AppModal } from '../AppModal';\nimport { CapabilityTab, type SelectedSkillSummary } from './components/CapabilityTab';\nimport { SkillsTab } from './components/SkillsTab';\nimport { SkillDetailView } from './components/SkillDetailView';\nimport { UploadSkillModal } from './components/UploadSkillModal';\n\nconst INSTALLED = '我的技能';\nconst SKILL_PLAZA = '技能广场';\nconst UPLOAD_SUCCESS_LABEL = '技能上传成功';\nconst SKILL_PLAZA_RISK_ACK_KEY = 'office-claw:skills-plaza-risk-ack:v1';\nconst LEGACY_SKILL_PLAZA_RISK_ACK_KEY = 'cat-cafe:skills-plaza-risk-ack:v1';\nconst RISK_TITLE = '风险提示';\nconst RISK_MESSAGE =\n '请注意,部分技能来源于第三方,当您使用第三方外部技能时,您承诺将严格遵守第三方的相关条款(包括但不限于license协议)。华为云不对第三方产品的合规性和安全性保证,请您使用前慎重考虑并评估风险。';\nconst UPDATE_SUCCESS_TITLE = '更新成功';\nconst UPDATE_FAILURE_TITLE = '更新失败';\n\nfunction hasSkillPlazaRiskAgreed(): boolean {\n if (typeof window === 'undefined') return false;\n try {\n const v = window.localStorage.getItem(SKILL_PLAZA_RISK_ACK_KEY);\n if (v === '1') return true;\n return window.localStorage.getItem(LEGACY_SKILL_PLAZA_RISK_ACK_KEY) === '1';\n } catch {\n return false;\n }\n}\n\nfunction markSkillPlazaRiskAgreed(): void {\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.setItem(SKILL_PLAZA_RISK_ACK_KEY, '1');\n try {\n window.localStorage.removeItem(LEGACY_SKILL_PLAZA_RISK_ACK_KEY);\n } catch {\n /* ignore */\n }\n } catch {\n // ignore storage failure\n }\n}\n\nexport function SkillsPanel() {\n const addToast = useToastStore((s) => s.addToast);\n const [activeTab, setActiveTab] = useState<'installed' | 'plaza'>('installed');\n const [showUpload, setShowUpload] = useState(false);\n const [capabilityRefreshSignal, setCapabilityRefreshSignal] = useState(0);\n const [selectedSkill, setSelectedSkill] = useState<SelectedSkillSummary | null>(null);\n const [showSkillPlazaRiskModal, setShowSkillPlazaRiskModal] = useState(false);\n const [pendingUpdateNames, setPendingUpdateNames] = useState<Set<string>>(new Set());\n const [updatingSkillId, setUpdatingSkillId] = useState<string | null>(null);\n const updateCheckStartedRef = useRef(false);\n\n useEscapeKey({\n enabled: showSkillPlazaRiskModal,\n onEscape: () => setShowSkillPlazaRiskModal(false),\n });\n\n const handleOpenSkillPlaza = () => {\n setSelectedSkill(null);\n if (hasSkillPlazaRiskAgreed()) {\n setActiveTab('plaza');\n return;\n }\n setShowSkillPlazaRiskModal(true);\n };\n\n const handleAgreeSkillPlazaRisk = () => {\n markSkillPlazaRiskAgreed();\n setShowSkillPlazaRiskModal(false);\n setActiveTab('plaza');\n };\n\n useEffect(() => {\n if (activeTab !== 'installed' || updateCheckStartedRef.current) return;\n updateCheckStartedRef.current = true;\n\n void (async () => {\n try {\n const res = await apiFetch('/api/skills/check-updates', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ force: false }),\n });\n if (!res.ok) return;\n const data = (await res.json()) as { updates?: { name: string }[] };\n const updates = data.updates ?? [];\n setPendingUpdateNames(new Set(updates.map((skill) => skill.name).filter(Boolean)));\n } catch {\n // Update checks are best-effort and must not block the installed skills page.\n }\n })();\n }, [activeTab]);\n\n const handleUpdateSkill = useCallback(async (skillName: string) => {\n if (updatingSkillId || !pendingUpdateNames.has(skillName)) return;\n setUpdatingSkillId(skillName);\n try {\n const res = await apiFetch('/api/skills/update', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: skillName }),\n });\n if (!res.ok) {\n const payload = (await res.json().catch(() => ({}))) as { error?: string };\n addToast({\n type: 'error',\n title: UPDATE_FAILURE_TITLE,\n message: payload.error ?? `HTTP ${res.status}`,\n duration: 5000,\n });\n return;\n }\n setPendingUpdateNames((current) => {\n const next = new Set(current);\n next.delete(skillName);\n return next;\n });\n notifySkillOptionsChanged();\n setCapabilityRefreshSignal((value) => value + 1);\n addToast({\n type: 'success',\n title: UPDATE_SUCCESS_TITLE,\n message: `\"${skillName}\" 已更新`,\n duration: 4000,\n });\n } catch {\n addToast({\n type: 'error',\n title: UPDATE_FAILURE_TITLE,\n message: '网络错误,请重试',\n duration: 5000,\n });\n } finally {\n setUpdatingSkillId(null);\n }\n }, [addToast, pendingUpdateNames, updatingSkillId]);\n\n const skillUpdates = useMemo(() => pendingUpdateNames, [pendingUpdateNames]);\n\n if (selectedSkill) {\n return (\n <div className=\"ui-page-shell gap-2 overflow-hidden\">\n <SkillDetailView\n skillName={selectedSkill.skillName}\n avatarUrl={selectedSkill.avatarUrl}\n onBack={() => setSelectedSkill(null)}\n />\n </div>\n );\n }\n\n return (\n <div className=\"ui-page-shell gap-2 overflow-hidden\">\n <UploadSkillModal\n open={showUpload}\n onClose={() => setShowUpload(false)}\n onSuccess={() => {\n setActiveTab('installed');\n setSelectedSkill(null);\n setCapabilityRefreshSignal((value) => value + 1);\n addToast({\n type: 'success',\n title: '上传成功',\n message: UPLOAD_SUCCESS_LABEL,\n duration: 4000,\n });\n }}\n />\n <AppModal\n open={showSkillPlazaRiskModal}\n onClose={() => setShowSkillPlazaRiskModal(false)}\n title={RISK_TITLE}\n panelClassName=\"w-[550px]\"\n disableBackdropClose\n showCloseButton={true}\n >\n <div className=\"space-y-4 pt-[18px]\">\n <p className=\"text-[12px] leading-[18px] text-[var(--text-secondary)]\">{RISK_MESSAGE}</p>\n <div className=\"flex items-center justify-end gap-2\">\n <Button variant=\"default\" onClick={() => setShowSkillPlazaRiskModal(false)}>\n 取消\n </Button>\n <Button variant=\"major\" onClick={handleAgreeSkillPlazaRisk}>\n 我已同意\n </Button>\n </div>\n </div>\n </AppModal>\n\n <div className=\"ui-page-header-inline items-start border-b\">\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex items-center gap-5\">\n <button\n type=\"button\"\n onClick={() => setActiveTab('installed')}\n className={`ui-tab-trigger ${activeTab === 'installed' ? 'ui-tab-trigger-active' : ''}`}\n >\n {INSTALLED}\n </button>\n <button\n type=\"button\"\n onClick={() => {\n handleOpenSkillPlaza();\n }}\n className={`ui-tab-trigger ${activeTab === 'plaza' ? 'ui-tab-trigger-active' : ''}`}\n >\n {SKILL_PLAZA}\n </button>\n </div>\n <div\n className=\"ui-tab-indicator w-[56px]\"\n style={{ transform: activeTab === 'plaza' ? 'translateX(78px)' : 'translateX(0)' }}\n />\n </div>\n </div>\n\n <div className=\"flex-1 min-h-0 overflow-hidden\">\n {activeTab === 'plaza' ? (\n <SkillsTab />\n ) : (\n <CapabilityTab\n onImport={() => setShowUpload(true)}\n onSelectSkill={setSelectedSkill}\n onUpdateSkill={handleUpdateSkill}\n skillUpdates={skillUpdates}\n updatingSkillId={updatingSkillId}\n refreshSignal={capabilityRefreshSignal}\n />\n )}\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { SkillsPanel } from '@/components/skills-panel/SkillsPanel';\n\nexport default function SkillsPage() {\n return (\n <div className=\"h-full overflow-hidden ui-shell-surface px-8 py-8\">\n <SkillsPanel />\n </div>\n );\n}\n"],"names":["SPECIAL_FILE_ICON_MAP","FILE_EXTENSION_ICON_MAP","DIRECTORY_ICON_SRC","DEFAULT_FILE_ICON_SRC","DISCLAIMER_TITLE","THIRD_PARTY_DISCLAIMER_TEXT","IMAGE_FILE_EXTENSIONS","sourceLabel","source","skillSourceToLabel","statusLabel","value","findFirstFile","nodes","node","_a","nestedPath","findNodeByPath","targetPath","nestedNode","getFileTreeIconSrc","normalizedFileName","extensionIndex","extension","isImageFilePath","filePath","normalizedPath","BasicInfoField","label","className","jsx","FileTreeBranch","selectedPath","onSelect","depth","jsxs","SkillDetailView","skillName","avatarUrl","onBack","detail","setDetail","useState","error","setError","loading","setLoading","setSelectedPath","filePreview","setFilePreview","filePreviewLoading","setFilePreviewLoading","filePreviewError","setFilePreviewError","previewCache","setPreviewCache","useEffect","controller","res","apiFetch","payload","data","loadError","triggerLabel","useMemo","categoryLabel","resolvedTitle","resolvedDescription","_b","hasDisclaimer","selectedFileLabel","selectedFileNode","selectedPathIsImage","fileTree","current","cachedPreview","handleSelectNode","CenteredLoadingState","OverflowTooltip","SkillAvatar","_c","INSTALLED","SKILL_PLAZA","UPLOAD_SUCCESS_LABEL","SKILL_PLAZA_RISK_ACK_KEY","LEGACY_SKILL_PLAZA_RISK_ACK_KEY","RISK_TITLE","RISK_MESSAGE","UPDATE_SUCCESS_TITLE","UPDATE_FAILURE_TITLE","hasSkillPlazaRiskAgreed","markSkillPlazaRiskAgreed","SkillsPanel","addToast","useToastStore","s","activeTab","setActiveTab","showUpload","setShowUpload","capabilityRefreshSignal","setCapabilityRefreshSignal","selectedSkill","setSelectedSkill","showSkillPlazaRiskModal","setShowSkillPlazaRiskModal","pendingUpdateNames","setPendingUpdateNames","updatingSkillId","setUpdatingSkillId","updateCheckStartedRef","useRef","useEscapeKey","handleOpenSkillPlaza","handleAgreeSkillPlazaRisk","updates","skill","handleUpdateSkill","useCallback","next","notifySkillOptionsChanged","skillUpdates","UploadSkillModal","AppModal","Button","SkillsTab","CapabilityTab","SkillsPage"],"mappings":"qpBA6CA,MAAMA,EAAgD,CACpD,aAAc,2BAChB,EAEMC,EAAkD,CACtD,QAAS,uBACT,QAAS,uBACT,OAAQ,sBACR,QAAS,uBACT,MAAO,qBACP,MAAO,qBACP,MAAO,qBACP,OAAQ,qBACV,EAEMC,GAAqB,yBACrBC,EAAwB,uBACxBC,GAAmB,OACnBC,GACJ,iFACIC,OAA4B,IAAI,CACpC,OACA,OACA,QACA,OACA,QACA,OACA,OACA,OACF,CAAC,EAED,SAASC,GAAYC,EAA+C,CAClE,OAAOC,GAAmBD,CAAM,CAClC,CAEA,SAASE,GAAYC,EAAwB,CAC3C,OAAOA,EAAQ,MAAQ,KACzB,CASA,SAASC,EAAcC,EAAiD,OACtE,UAAWC,KAAQD,EAAO,CACxB,GAAIC,EAAK,OAAS,OAAQ,OAAOA,EAAK,KACtC,IAAIC,EAAAD,EAAK,WAAL,MAAAC,EAAe,OAAQ,CACzB,MAAMC,EAAaJ,EAAcE,EAAK,QAAQ,EAC9C,GAAIE,EAAY,OAAOA,CACzB,CACF,CACA,OAAO,IACT,CAEA,SAASC,EACPJ,EACAK,EACgC,OAChC,UAAWJ,KAAQD,EAAO,CACxB,GAAIC,EAAK,OAASI,EAAY,OAAOJ,EACrC,IAAIC,EAAAD,EAAK,WAAL,MAAAC,EAAe,OAAQ,CACzB,MAAMI,EAAaF,EAAeH,EAAK,SAAUI,CAAU,EAC3D,GAAIC,EAAY,OAAOA,CACzB,CACF,CACA,OAAO,IACT,CAEA,SAASC,EAAmBN,EAAuC,CACjE,GAAIA,EAAK,OAAS,YAAa,OAAOZ,GAItC,MAAMmB,GAFWP,EAAK,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAC1B,GAAG,EAAE,GAAKA,EAAK,MACL,YAAA,EAEpC,GAAId,EAAsBqB,CAAkB,EAC1C,OAAOrB,EAAsBqB,CAAkB,EAGjD,MAAMC,EAAiBD,EAAmB,YAAY,GAAG,EACzD,GAAIC,EAAiB,EAAG,CACtB,MAAMC,EAAYF,EAAmB,MAAMC,CAAc,EACzD,GAAIrB,EAAwBsB,CAAS,EACnC,OAAOtB,EAAwBsB,CAAS,CAE5C,CAEA,OAAOpB,CACT,CAEA,SAASqB,GAAgBC,EAAkC,CACzD,GAAI,CAACA,EAAU,MAAO,GAEtB,MAAMC,EAAiBD,EAAS,YAAA,EAC1BH,EAAiBI,EAAe,YAAY,GAAG,EACrD,OAAIJ,EAAiB,EAAU,GAExBhB,GAAsB,IAAIoB,EAAe,MAAMJ,CAAc,CAAC,CACvE,CAEA,SAASK,EAAe,CACtB,MAAAC,EACA,MAAAjB,EACA,UAAAkB,EAAY,EACd,EAIG,CACD,cACG,MAAA,CAAI,UAAW,aAAaA,CAAS,GAAG,OACvC,SAAA,CAAAC,EAAAA,IAAC,IAAA,CAAE,UAAU,2EACV,SAAAF,EACH,EACC,OAAOjB,GAAU,SAChBmB,EAAAA,IAAC,KAAE,UAAU,+CAAgD,WAAM,EAEnEnB,CAAA,EAEJ,CAEJ,CAEA,SAASoB,EAAe,CACtB,MAAAlB,EACA,aAAAmB,EACA,SAAAC,EACA,MAAAC,EAAQ,CACV,EAKG,CACD,OACEJ,EAAAA,IAAC,MAAG,UAAU,cACX,WAAM,IAAKhB,GAAA,OACVqB,OAAAA,EAAAA,KAAC,KAAA,CACC,SAAA,CAAAA,EAAAA,KAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMF,EAASnB,CAAI,EAC5B,UAAW,4FACTkB,IAAiBlB,EAAK,KAAO,iCAAmC,EAClE,GACA,MAAO,CAAE,YAAa,GAAGoB,EAAQ,GAAK,EAAE,IAAA,EAExC,SAAA,CAAAJ,EAAAA,IAAC,OAAA,CACC,UAAW,qFACTE,IAAiBlB,EAAK,KAAO,cAAgB,YAC/C,GAEA,SAAAgB,EAAAA,IAAC,MAAA,CACC,IAAKV,EAAmBN,CAAI,EAC5B,IAAI,GACJ,cAAY,OACZ,cAAY,8BACZ,YAAWA,EAAK,KAChB,UAAU,iCAAA,CAAA,CACZ,CAAA,EAEFgB,EAAAA,IAAC,OAAA,CAAK,UAAU,yBAA0B,WAAK,IAAA,CAAK,CAAA,CAAA,CAAA,GAErDf,EAAAD,EAAK,WAAL,MAAAC,EAAe,OACde,EAAAA,IAACC,EAAA,CACC,MAAOjB,EAAK,SACZ,aAAAkB,EACA,SAAAC,EACA,MAAOC,EAAQ,CAAA,CAAA,EAEf,IAAA,CAAA,EAhCGpB,EAAK,IAiCd,EACD,EACH,CAEJ,CAEO,SAASsB,GAAgB,CAC9B,UAAAC,EACA,UAAAC,EACA,OAAAC,CACF,EAIG,WACD,KAAM,CAACC,EAAQC,CAAS,EAAIC,EAAAA,SAAqC,IAAI,EAC/D,CAACC,EAAOC,CAAQ,EAAIF,EAAAA,SAAwB,IAAI,EAChD,CAACG,EAASC,CAAU,EAAIJ,EAAAA,SAAS,EAAI,EACrC,CAACV,EAAce,CAAe,EAAIL,EAAAA,SAAwB,IAAI,EAC9D,CAACM,EAAaC,CAAc,EAChCP,EAAAA,SAA0C,IAAI,EAC1C,CAACQ,EAAoBC,CAAqB,EAAIT,EAAAA,SAAS,EAAK,EAC5D,CAACU,EAAkBC,CAAmB,EAAIX,EAAAA,SAAwB,IAAI,EACtE,CAACY,EAAcC,CAAe,EAAIb,EAAAA,SAEtC,CAAA,CAAE,EAEJc,EAAAA,UAAU,IAAM,CACd,MAAMC,EAAa,IAAI,gBAqCvB,OAnCmB,SAAY,CAC7BX,EAAW,EAAI,EACfF,EAAS,IAAI,EACb,GAAI,CACF,MAAMc,EAAM,MAAMC,EAChB,2BAA2B,mBAAmBtB,CAAS,CAAC,GACxD,CACE,OAAQoB,EAAW,MAAA,CACrB,EAEF,GAAI,CAACC,EAAI,GAAI,CACX,MAAME,EAAW,MAAMF,EAAI,KAAA,EAAO,MAAM,KAAO,CAAA,EAAG,EAGlDd,EAASgB,EAAQ,OAAS,SAASF,EAAI,MAAM,GAAG,EAChDjB,EAAU,IAAI,EACd,MACF,CACA,MAAMoB,EAAQ,MAAMH,EAAI,KAAA,EACxBjB,EAAUoB,CAAI,CAChB,OAASC,EAAW,CAClB,GACEA,aAAqB,cACrBA,EAAU,OAAS,aAEnB,OACFlB,EAAS,MAAM,EACfH,EAAU,IAAI,CAChB,QAAA,CACOgB,EAAW,OAAO,SACrBX,EAAW,EAAK,CAEpB,CACF,GAEK,EAEE,IAAMW,EAAW,MAAA,CAC1B,EAAG,CAACpB,CAAS,CAAC,EAEd,MAAM0B,EAAeC,EAAAA,QACnB,IAAA,OAAM,QAAAjD,EAAAyB,GAAA,YAAAA,EAAQ,WAAR,YAAAzB,EAAkB,KAAK,QAAS,MACtC,CAACyB,GAAA,YAAAA,EAAQ,QAAQ,CAAA,EAEbyB,IAAgBlD,EAAAyB,GAAA,YAAAA,EAAQ,WAAR,YAAAzB,EAAkB,SAAU,KAC5CmD,GAAgB1B,GAAA,YAAAA,EAAQ,OAAQH,EAChC8B,IAAsBC,EAAA5B,GAAA,YAAAA,EAAQ,cAAR,YAAA4B,EAAqB,SAAU,KACrDC,GAAgB7B,GAAA,YAAAA,EAAQ,UAAW,WACnC8B,EAAoBN,EAAAA,QAAQ,IAAM,OACtC,OAAKhC,EAEEA,EAAa,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,GAAG,EAAE,GAAKA,GADhDjB,EAAAyB,GAAA,YAAAA,EAAQ,WAAR,MAAAzB,EAAkB,OAAS,QAAU,MAEhD,EAAG,CAACyB,GAAA,YAAAA,EAAQ,SAAUR,CAAY,CAAC,EAC7BuC,EAAmBP,EAAAA,QAAQ,IAAM,OACrC,MAAI,GAACjD,EAAAyB,GAAA,YAAAA,EAAQ,WAAR,MAAAzB,EAAkB,SAAU,CAACiB,EAAqB,KAChDf,EAAeuB,EAAO,SAAUR,CAAY,CACrD,EAAG,CAACQ,GAAA,YAAAA,EAAQ,SAAUR,CAAY,CAAC,EAC7BwC,EAAsBR,EAAAA,QAAQ,IAAMxC,GAAgBQ,CAAY,EAAG,CAACA,CAAY,CAAC,EAEvFwB,EAAAA,UAAU,IAAM,CACd,MAAMiB,EAAWjC,GAAA,YAAAA,EAAQ,SACzB,GAAI,EAACiC,GAAA,MAAAA,EAAU,QAAQ,CACrB1B,EAAgB,IAAI,EACpB,MACF,CACAA,EACG2B,UACC,OAAAA,GAAW9D,EAAc6D,CAAQ,KAAK1D,EAAA0D,EAAS,CAAC,IAAV,YAAA1D,EAAa,OAAQ,KAAA,CAEjE,EAAG,CAACyB,CAAM,CAAC,EAEXgB,EAAAA,UAAU,IAAM,CACdP,EAAe,IAAI,EACnBI,EAAoB,IAAI,EACxBE,EAAgB,CAAA,CAAE,CACpB,EAAG,CAAClB,CAAS,CAAC,EAEdmB,EAAAA,UAAU,IAAM,CACd,GAAI,CAACxB,EAAc,CACjBiB,EAAe,IAAI,EACnBI,EAAoB,IAAI,EACxB,MACF,CAEA,GAAImB,EAAqB,CACvBvB,EAAe,CACb,KAAMjB,EACN,QAAS,WACT,MAAMuC,GAAA,YAAAA,EAAkB,OAAQ,EAChC,KAAM,UACN,UAAW,EAAA,CACZ,EACDlB,EAAoB,IAAI,EACxBF,EAAsB,EAAK,EAC3B,MACF,CAEA,MAAMwB,EAAgBrB,EAAatB,CAAY,EAC/C,GAAI2C,EAAe,CACjB1B,EAAe0B,CAAa,EAC5BtB,EAAoB,IAAI,EACxBF,EAAsB,EAAK,EAC3B,MACF,CAEA,MAAMM,EAAa,IAAI,gBAsCvB,OApCwB,SAAY,CAClCN,EAAsB,EAAI,EAC1BE,EAAoB,IAAI,EACxB,GAAI,CACF,MAAMK,EAAM,MAAMC,EAChB,yBAAyB,mBAAmBtB,CAAS,CAAC,SAAS,mBAAmBL,CAAY,CAAC,GAC/F,CACE,OAAQyB,EAAW,MAAA,CACrB,EAEF,GAAI,CAACC,EAAI,GAAI,CACX,MAAME,EAAW,MAAMF,EAAI,KAAA,EAAO,MAAM,KAAO,CAAA,EAAG,EAGlDT,EAAe,IAAI,EACnBI,EAAoBO,EAAQ,OAAS,WAAWF,EAAI,MAAM,GAAG,EAC7D,MACF,CACA,MAAMG,EAAQ,MAAMH,EAAI,KAAA,EACxBT,EAAeY,CAAI,EACnBN,EAAiBmB,IAAa,CAAE,GAAGA,EAAS,CAAC1C,CAAY,EAAG6B,CAAA,EAAO,CACrE,OAASC,EAAW,CAClB,GACEA,aAAqB,cACrBA,EAAU,OAAS,aAEnB,OACFb,EAAe,IAAI,EACnBI,EAAoB,UAAU,CAChC,QAAA,CACOI,EAAW,OAAO,SACrBN,EAAsB,EAAK,CAE/B,CACF,GAEK,EAEE,IAAMM,EAAW,MAAA,CAC1B,EAAG,CAACH,EAAciB,GAAA,YAAAA,EAAkB,KAAMvC,EAAcwC,EAAqBnC,CAAS,CAAC,EAEvF,MAAMuC,EAAoB9D,GAAkC,CACtDA,EAAK,OAAS,QAClBiC,EAAgBjC,EAAK,IAAI,CAC3B,EAEA,OAAI+B,EAAgBf,MAAC+C,EAAA,CAAA,CAAqB,EAGxC1C,EAAAA,KAAC,MAAA,CACC,UAAU,+BACV,cAAY,qBAEZ,SAAA,CAAAL,EAAAA,IAAC,OAAI,UAAU,gBACb,SAAAK,EAAAA,KAAC,MAAA,CAAI,UAAU,mEACb,SAAA,CAAAL,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAASS,EACT,cAAY,+BACZ,UAAU,sCACX,SAAA,MAAA,CAAA,EAGDT,EAAAA,IAAC,QAAK,SAAA,GAAA,CAAC,EACPA,EAAAA,IAACgD,EAAA,CAAgB,QAASZ,EAAe,UAAU,UACjD,SAAApC,EAAAA,IAAC,OAAA,CACC,UAAU,wDACV,cAAY,gCAEX,SAAAoC,CAAA,CAAA,CACH,CACF,CAAA,CAAA,CACF,CAAA,CACF,EAEA/B,EAAAA,KAAC,MAAA,CAAI,UAAU,iCACZ,SAAA,CAAAQ,EACCb,EAAAA,IAAC,IAAA,CAAE,UAAU,oEACV,WACH,EACE,KAEHU,EACCL,EAAAA,KAAC,MAAA,CAAI,UAAU,mCACb,SAAA,CAAAL,EAAAA,IAAC,WAAQ,UAAU,qBACjB,SAAAK,EAAAA,KAAC,MAAA,CAAI,UAAU,yBACb,SAAA,CAAAL,EAAAA,IAACiD,GAAA,CACC,WAAY1C,EACZ,UAAAC,EACA,WAAW,sBACX,UAAU,kCAAA,CAAA,EAEZH,EAAAA,KAAC,MAAA,CAAI,UAAU,qCACb,SAAA,CAAAL,EAAAA,IAACgD,EAAA,CAAgB,QAASZ,EAAe,UAAU,SACjD,SAAApC,EAAAA,IAAC,KAAA,CACC,UAAU,iIACV,cAAY,qBAEX,SAAAoC,CAAA,CAAA,EAEL,EACA/B,EAAAA,KAAC,MAAA,CAAI,UAAU,yEACb,SAAA,CAAAL,EAAAA,IAAC,OAAA,CACC,UAAU,iBACV,cAAY,8BAEX,SAAAmC,CAAA,CAAA,EAEHnC,EAAAA,IAAC,OAAA,CACC,UAAU,iBACV,cAAY,4BAEX,SAAAvB,GAAYiC,EAAO,MAAM,CAAA,CAAA,EAE5BV,EAAAA,IAAC,OAAA,CACC,UAAU,iBACV,cAAY,4BAEX,SAAApB,GAAY8B,EAAO,OAAO,CAAA,CAAA,CAC7B,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CACF,EACAL,EAAAA,KAAC,UAAA,CACC,UAAU,qBACV,cAAY,0BAEZ,SAAA,CAAAL,EAAAA,IAAC,KAAA,CAAG,UAAU,qDAAqD,SAAA,OAEnE,EACAK,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAL,EAAAA,IAACH,EAAA,CAAe,MAAM,KAAK,MAAOuC,EAAe,EACjDpC,EAAAA,IAACH,EAAA,CACC,MAAM,MACN,MACEG,EAAAA,IAACgD,EAAA,CAAgB,QAASf,EAAc,UAAU,SAChD,SAAAjC,EAAAA,IAAC,IAAA,CAAE,UAAU,8CACV,SAAAiC,CAAA,CACH,CAAA,CACF,CAAA,CAAA,EAGJjC,EAAAA,IAACH,EAAA,CACC,MAAM,KACN,MACEG,EAAAA,IAACgD,EAAA,CACC,QAASX,EACT,UAAU,SAEV,SAAArC,EAAAA,IAAC,IAAA,CAAE,UAAU,8CACV,SAAAqC,CAAA,CACH,CAAA,CAAA,CACF,CAAA,CAEJ,CAAA,CACF,CAAA,CAAA,CAAA,EAEFhC,EAAAA,KAAC,UAAA,CACC,UAAU,qBACV,cAAY,8BAEZ,SAAA,CAAAL,EAAAA,IAAC,KAAA,CAAG,UAAU,qDAAqD,SAAA,OAEnE,EACAA,EAAAA,IAAC,MAAA,CACC,UAAW,+GAEX,SAAAK,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACb,SAAA,CAAAA,EAAAA,KAAC,QAAA,CAAM,UAAU,yIACf,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,4EACb,SAAA,CAAAL,EAAAA,IAAC,MAAA,CAAI,IAAI,kBAAkB,UAAU,kCAAkC,EACvEA,EAAAA,IAAC,MAAA,CAAI,UAAU,UAAU,SAAA,MAAA,CAAI,CAAA,EAC/B,QACC,MAAA,CAAI,UAAU,2CACZ,UAAAkD,EAAAxC,EAAO,WAAP,MAAAwC,EAAiB,OAChBlD,EAAAA,IAACC,EAAA,CACC,MAAOS,EAAO,SACd,aAAAR,EACA,SAAU4C,CAAA,CAAA,EAGZ9C,EAAAA,IAAC,IAAA,CAAE,UAAU,6CAA6C,qBAE1D,CAAA,CAEJ,CAAA,EACF,EACAK,EAAAA,KAAC,MAAA,CAAI,UAAU,gEACb,SAAA,CAAAL,EAAAA,IAAC,OAAI,UAAU,4DACb,SAAAK,EAAAA,KAAC,MAAA,CAAI,UAAU,+EACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,kDACb,SAAA,CAAAL,EAAAA,IAAC,MAAA,CACC,IACEyC,EACInD,EAAmBmD,CAAgB,EACnCpE,EAEN,IAAI,GACJ,cAAY,OACZ,cAAY,mCACZ,UAAU,iCAAA,CAAA,EAEZ2B,EAAAA,IAACgD,EAAA,CAAgB,QAASR,EAAmB,UAAU,0BACrD,SAAAxC,EAAAA,IAAC,MAAA,CAAI,UAAU,0BAA2B,SAAAwC,CAAA,CAAkB,CAAA,CAC9D,CAAA,EACF,EACCtB,EACClB,EAAAA,IAACgD,EAAA,CACC,QAAS,GAAG9B,EAAY,IAAI,MAAMA,EAAY,IAAI,KAClD,UAAU,0BAEV,SAAAlB,EAAAA,IAAC,MAAA,CAAI,UAAU,sEACZ,SAAA,GAAGkB,EAAY,IAAI,MAAMA,EAAY,IAAI,IAAA,CAC5C,CAAA,CAAA,EAEA,IAAA,CAAA,CACN,CAAA,CACF,EACAb,EAAAA,KAAC,MAAA,CAAI,UAAU,2CACZ,SAAA,CAAAe,EACCpB,EAAAA,IAAC,MAAA,CACC,UAAU,kDACV,cAAY,qCAEZ,eAAC+C,EAAA,CAAA,CAAqB,CAAA,CAAA,EAEtB,KACH,CAAC3B,GAAsBE,EACtBtB,EAAAA,IAAC,KAAE,UAAU,+DACV,WACH,EACE,KACH,CAACoB,GACF,CAACE,GACDJ,EACEb,EAAAA,KAAC,MAAA,CACC,UAAU,YACV,cAAY,4BAEX,SAAA,CAAAa,EAAY,UACXlB,EAAAA,IAAC,IAAA,CAAE,UAAU,4HAA4H,8BAEzI,EACE,KACJA,EAAAA,IAAC,MAAA,CACC,UAAU,8EACV,MAAO,CAAE,aAAc,UAAA,EAEtB,SAAAkB,EAAY,OAAA,CAAA,CACf,CAAA,CAAA,EAEA,KACH,CAACE,GACF,CAACE,GACD,CAACJ,EACClB,EAAAA,IAAC,IAAA,CAAE,UAAU,mCAAmC,SAAA,YAAA,CAEhD,EACE,IAAA,CAAA,CACN,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,EAEDuC,EACClC,EAAAA,KAAC,UAAA,CACC,UAAU,qBACV,cAAY,0BAEZ,SAAA,CAAAL,EAAAA,IAAC,KAAA,CAAG,UAAU,qDACX,SAAA1B,GACH,EACA0B,EAAAA,IAAC,OAAI,UAAU,qFACb,eAAC,IAAA,CAAE,UAAU,iDACV,SAAAzB,EAAA,CACH,CAAA,CACF,CAAA,CAAA,CAAA,EAEA,IAAA,CAAA,CACN,EACE,IAAA,CAAA,CACN,CAAA,CAAA,CAAA,CAGN,CC5mBA,MAAM4E,GAAY,OACZC,GAAc,OACdC,GAAuB,SACvBC,EAA2B,uCAC3BC,EAAkC,oCAClCC,GAAa,OACbC,GACJ,qGACIC,GAAuB,OACvBC,EAAuB,OAE7B,SAASC,IAAmC,CAC1C,GAAI,OAAO,OAAW,IAAa,MAAO,GAC1C,GAAI,CAEF,OADU,OAAO,aAAa,QAAQN,CAAwB,IACpD,IAAY,GACf,OAAO,aAAa,QAAQC,CAA+B,IAAM,GAC1E,MAAQ,CACN,MAAO,EACT,CACF,CAEA,SAASM,IAAiC,CACxC,GAAI,SAAO,OAAW,KACtB,GAAI,CACF,OAAO,aAAa,QAAQP,EAA0B,GAAG,EACzD,GAAI,CACF,OAAO,aAAa,WAAWC,CAA+B,CAChE,MAAQ,CAER,CACF,MAAQ,CAER,CACF,CAEO,SAASO,IAAc,CAC5B,MAAMC,EAAWC,GAAeC,GAAMA,EAAE,QAAQ,EAC1C,CAACC,EAAWC,CAAY,EAAIvD,EAAAA,SAAgC,WAAW,EACvE,CAACwD,EAAYC,CAAa,EAAIzD,EAAAA,SAAS,EAAK,EAC5C,CAAC0D,EAAyBC,CAA0B,EAAI3D,EAAAA,SAAS,CAAC,EAClE,CAAC4D,EAAeC,CAAgB,EAAI7D,EAAAA,SAAsC,IAAI,EAC9E,CAAC8D,EAAyBC,CAA0B,EAAI/D,EAAAA,SAAS,EAAK,EACtE,CAACgE,EAAoBC,CAAqB,EAAIjE,EAAAA,SAAsB,IAAI,GAAK,EAC7E,CAACkE,EAAiBC,CAAkB,EAAInE,EAAAA,SAAwB,IAAI,EACpEoE,EAAwBC,EAAAA,OAAO,EAAK,EAE1CC,GAAa,CACX,QAASR,EACT,SAAU,IAAMC,EAA2B,EAAK,CAAA,CACjD,EAED,MAAMQ,EAAuB,IAAM,CAEjC,GADAV,EAAiB,IAAI,EACjBb,KAA2B,CAC7BO,EAAa,OAAO,EACpB,MACF,CACAQ,EAA2B,EAAI,CACjC,EAEMS,EAA4B,IAAM,CACtCvB,GAAA,EACAc,EAA2B,EAAK,EAChCR,EAAa,OAAO,CACtB,EAEAzC,EAAAA,UAAU,IAAM,CACVwC,IAAc,aAAec,EAAsB,UACvDA,EAAsB,QAAU,IAE1B,SAAY,CAChB,GAAI,CACF,MAAMpD,EAAM,MAAMC,EAAS,4BAA6B,CACtD,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAA,EAC3B,KAAM,KAAK,UAAU,CAAE,MAAO,GAAO,CAAA,CACtC,EACD,GAAI,CAACD,EAAI,GAAI,OAEb,MAAMyD,GADQ,MAAMzD,EAAI,KAAA,GACH,SAAW,CAAA,EAChCiD,EAAsB,IAAI,IAAIQ,EAAQ,IAAKC,GAAUA,EAAM,IAAI,EAAE,OAAO,OAAO,CAAC,CAAC,CACnF,MAAQ,CAER,CACF,GAAA,EACF,EAAG,CAACpB,CAAS,CAAC,EAEd,MAAMqB,EAAoBC,cAAY,MAAOjF,GAAsB,CACjE,GAAI,EAAAuE,GAAmB,CAACF,EAAmB,IAAIrE,CAAS,GACxD,CAAAwE,EAAmBxE,CAAS,EAC5B,GAAI,CACF,MAAMqB,EAAM,MAAMC,EAAS,qBAAsB,CAC/C,OAAQ,OACR,QAAS,CAAE,eAAgB,kBAAA,EAC3B,KAAM,KAAK,UAAU,CAAE,KAAMtB,EAAW,CAAA,CACzC,EACD,GAAI,CAACqB,EAAI,GAAI,CACX,MAAME,EAAW,MAAMF,EAAI,KAAA,EAAO,MAAM,KAAO,CAAA,EAAG,EAClDmC,EAAS,CACP,KAAM,QACN,MAAOJ,EACP,QAAS7B,EAAQ,OAAS,QAAQF,EAAI,MAAM,GAC5C,SAAU,GAAA,CACX,EACD,MACF,CACAiD,EAAuBjC,GAAY,CACjC,MAAM6C,EAAO,IAAI,IAAI7C,CAAO,EAC5B,OAAA6C,EAAK,OAAOlF,CAAS,EACdkF,CACT,CAAC,EACDC,GAAA,EACAnB,EAA4B1F,GAAUA,EAAQ,CAAC,EAC/CkF,EAAS,CACP,KAAM,UACN,MAAOL,GACP,QAAS,IAAInD,CAAS,QACtB,SAAU,GAAA,CACX,CACH,MAAQ,CACNwD,EAAS,CACP,KAAM,QACN,MAAOJ,EACP,QAAS,WACT,SAAU,GAAA,CACX,CACH,QAAA,CACEoB,EAAmB,IAAI,CACzB,EACF,EAAG,CAAChB,EAAUa,EAAoBE,CAAe,CAAC,EAE5Ca,EAAezD,EAAAA,QAAQ,IAAM0C,EAAoB,CAACA,CAAkB,CAAC,EAE3E,OAAIJ,EAEAxE,EAAAA,IAAC,MAAA,CAAI,UAAU,sCACb,SAAAA,EAAAA,IAACM,GAAA,CACC,UAAWkE,EAAc,UACzB,UAAWA,EAAc,UACzB,OAAQ,IAAMC,EAAiB,IAAI,CAAA,CAAA,EAEvC,EAKFpE,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAL,EAAAA,IAAC4F,GAAA,CACC,KAAMxB,EACN,QAAS,IAAMC,EAAc,EAAK,EAClC,UAAW,IAAM,CACfF,EAAa,WAAW,EACxBM,EAAiB,IAAI,EACrBF,EAA4B1F,GAAUA,EAAQ,CAAC,EAC/CkF,EAAS,CACP,KAAM,UACN,MAAO,OACP,QAASV,GACT,SAAU,GAAA,CACX,CACH,CAAA,CAAA,EAEFrD,EAAAA,IAAC6F,GAAA,CACC,KAAMnB,EACN,QAAS,IAAMC,EAA2B,EAAK,EAC/C,MAAOnB,GACP,eAAe,YACf,qBAAoB,GACpB,gBAAiB,GAEjB,SAAAnD,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAL,EAAAA,IAAC,IAAA,CAAE,UAAU,0DAA2D,SAAAyD,GAAa,EACrFpD,EAAAA,KAAC,MAAA,CAAI,UAAU,sCACb,SAAA,CAAAL,EAAAA,IAAC8F,EAAA,CAAO,QAAQ,UAAU,QAAS,IAAMnB,EAA2B,EAAK,EAAG,SAAA,IAAA,CAE5E,QACCmB,EAAA,CAAO,QAAQ,QAAQ,QAASV,EAA2B,SAAA,MAAA,CAE5D,CAAA,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAAA,QAGD,MAAA,CAAI,UAAU,6CACb,SAAA/E,EAAAA,KAAC,MAAA,CAAI,UAAU,sBACb,SAAA,CAAAA,EAAAA,KAAC,MAAA,CAAI,UAAU,0BACb,SAAA,CAAAL,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAMmE,EAAa,WAAW,EACvC,UAAW,kBAAkBD,IAAc,YAAc,wBAA0B,EAAE,GAEpF,SAAAf,EAAA,CAAA,EAEHnD,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,QAAS,IAAM,CACbmF,EAAA,CACF,EACA,UAAW,kBAAkBjB,IAAc,QAAU,wBAA0B,EAAE,GAEhF,SAAAd,EAAA,CAAA,CACH,EACF,EACApD,EAAAA,IAAC,MAAA,CACC,UAAU,4BACV,MAAO,CAAE,UAAWkE,IAAc,QAAU,mBAAqB,eAAA,CAAgB,CAAA,CACnF,CAAA,CACF,CAAA,CACF,EAEAlE,EAAAA,IAAC,OAAI,UAAU,iCACZ,aAAc,QACbA,EAAAA,IAAC+F,KAAU,EAEX/F,EAAAA,IAACgG,GAAA,CACC,SAAU,IAAM3B,EAAc,EAAI,EAClC,cAAeI,EACf,cAAec,EACf,aAAAI,EACA,gBAAAb,EACA,cAAeR,CAAA,CAAA,CACjB,CAEJ,CAAA,EACF,CAEJ,CC/OA,SAAwB2B,IAAa,CACnC,aACG,MAAA,CAAI,UAAU,oDACb,SAAAjG,MAAC8D,KAAY,EACf,CAEJ"}
@@ -0,0 +1 @@
1
+ ._skillGrid_emmae_7{display:grid;gap:var(--space-7);grid-template-columns:repeat(auto-fit,minmax(min(100%,280px),1fr))}._card_emmae_13{display:flex;justify-content:space-between;min-height:194px;flex-direction:column;gap:var(--space-7);padding:24px}._header_emmae_22{display:flex;align-items:flex-start;gap:var(--space-5)}._content_emmae_28{min-width:0;flex:1 1 auto}._title_emmae_33{font-size:var(--font-size-lg);line-height:24px;font-weight:var(--font-weight-bold);color:var(--text-primary)}._description_emmae_40{display:-webkit-box;overflow:hidden;min-height:44px;font-size:var(--font-size-md);line-height:22px;color:var(--text-secondary);-webkit-box-orient:vertical;-webkit-line-clamp:2}._footer_emmae_51{margin-top:auto}._installButton_emmae_55{display:inline-flex;min-height:var(--control-height-touch);align-items:center;justify-content:center;border-radius:var(--radius-pill);font-size:var(--font-size-md);line-height:1;font-weight:var(--font-weight-medium);transition:border-color .2s ease,background-color .2s ease,color .2s ease;text-decoration:none}._installButtonPrimary_emmae_71:hover,._installButtonPrimary_emmae_71:focus-visible{text-decoration:underline}._installButtonPrimary_emmae_71{color:var(--text-accent)}._installButtonSuccess_emmae_80{color:var(--text-disabled)}._installButtonMuted_emmae_84{color:var(--text-muted)}@media(min-width:1024px){._skillGrid_emmae_7{gap:var(--space-8);grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:640px){._installButton_emmae_55{min-height:var(--control-height-xs)}}@media(max-width:767px){._card_emmae_13{min-height:204px;gap:var(--space-6)}}
@@ -0,0 +1,2 @@
1
+ import{j as e,r as s,b as je,u as me,B as Ce}from"./index-Cb4fQgom.js";import{O as Q,a as z}from"./OverflowTooltip-CE5PjAb-.js";import{n as xe}from"./skill-options-cache-D1BJGTCU.js";import{S as Ne}from"./SkillAvatar-DwGvsY4f.js";import{C as fe}from"./CenteredLoadingState-DHor-9vF.js";import{E as pe}from"./EmptyDataState-6mNx2Xhl.js";import{N as he}from"./NoSearchResultsState-BiiYdZ_Z.js";import{S as ge}from"./SearchInput-tux8xXH1.js";import{N as we}from"./NameInitialIcon-DP-6_HQY.js";function Se(a){return a==="builtin"?"内置技能":a==="external"?"用户添加技能":"其他"}function Le(a){return Se(a)}function _e({item:a,agentFamilies:d,toggling:c,onToggle:n,onUninstall:u,onUpdateSkill:b,updatingSkillId:Z,skillUpdates:w,onClick:O,hideSkillMountStatus:D}){var j,E;`${a.type}${a.id}`;const _=Le(a.source),k=((j=a.description)==null?void 0:j.trim())||"暂未提供技能描述。",S=((E=a.category)==null?void 0:E.trim())||"其他",G=a.source==="external"&&typeof u=="function",A=a.type==="skill"&&!!(w!=null&&w.has(a.id))&&typeof b=="function",y=Z===a.id,p=typeof O=="function";return e.jsxs("div",{className:`ui-card ui-card-hover group flex flex-col gap-4 ${p?"cursor-pointer":""}`,"data-testid":`capability-card-${a.type}-${a.id}`,onClick:O,onKeyDown:p?C=>{(C.key==="Enter"||C.key===" ")&&(C.preventDefault(),O())}:void 0,role:p?"button":void 0,tabIndex:p?0:void 0,children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx(Ne,{avatarName:a.id,avatarUrl:a.iconUrl}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[e.jsx(Q,{content:a.id,className:"min-w-0 flex-1",as:"h3",textClassName:"block truncate text-base font-semibold text-[var(--text-primary)]"}),a.connectionStatus?e.jsx(ke,{status:a.connectionStatus}):null]}),e.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-2 text-xs",children:[A?e.jsxs("span",{className:"ui-badge-muted inline-flex items-center gap-1 border-[rgba(194,87,0,0.28)] bg-[rgba(194,87,0,0.10)] text-[rgba(194,87,0,1)]",children:[e.jsxs("svg",{"aria-hidden":"true",className:"h-4 w-4 shrink-0 opacity-80",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.25",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("path",{d:"M8 2.1A4.15 4.15 0 0 0 3.85 6.25v2.1c0 .76-.25 1.5-.72 2.1L2.6 11.1h10.8l-.53-.65a3.4 3.4 0 0 1-.72-2.1v-2.1A4.15 4.15 0 0 0 8 2.1Z"}),e.jsx("path",{d:"M6.85 13a1.25 1.25 0 0 0 2.3 0"})]}),"有更新"]}):null,e.jsx(Q,{content:S,className:"inline-flex max-w-full min-w-0",as:"span",textClassName:"ui-badge-muted inline-block max-w-full truncate align-middle leading-[18px]"})]})]})]}),e.jsx(Q,{content:k,className:"w-full",children:e.jsx("p",{className:"line-clamp-2 min-h-[44px] text-sm leading-6 text-[var(--text-secondary)]",children:k})}),e.jsx("div",{className:"flex items-end justify-between gap-3",children:e.jsx("div",{className:"min-h-5 text-xs leading-5",children:G||A?e.jsxs("div",{className:"relative",children:[e.jsxs("span",{className:"text-[var(--text-muted)] transition-opacity duration-200 group-hover:opacity-0",children:["来源:",_]}),e.jsxs("div",{className:"absolute left-0 top-0 flex items-center gap-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100",children:[A?e.jsx("button",{type:"button",onClick:C=>{C.stopPropagation(),b==null||b(a.id)},disabled:y,className:"text-[14px] font-bold text-[var(--text-accent)] hover:underline disabled:cursor-not-allowed disabled:opacity-60",children:y?"更新中":"更新"}):null,G?e.jsx("button",{type:"button",onClick:C=>{C.stopPropagation(),u==null||u(a.id)},className:"text-[14px] font-bold text-[var(--text-accent)] hover:underline",children:"卸载"}):null]})]}):e.jsxs("span",{className:"text-[var(--text-muted)]",children:["来源:",_]})})})]})}function ke({status:a}){const d=a==="connected"?"bg-[var(--state-success-text)]":a==="disconnected"?"bg-[var(--state-error-text)]":"bg-[var(--text-muted)]",c=a==="connected"?"已连接":a==="disconnected"?"掉线":"未知";return e.jsx("span",{className:`inline-block h-2 w-2 rounded-full ${d}`,title:c})}const H="全部",se="其他",Ae="搜索技能",Ee="搜索我的技能",Te="筛选分类",Ie="导入",oe=["办公套件"],re="all",le=[{id:re,label:"全部"},{id:"external",label:"我添加的"},{id:"builtin",label:"平台精选"}];function Re(a){return[...a].sort((d,c)=>{const n=oe.indexOf(d),u=oe.indexOf(c);return n!==-1||u!==-1?n===-1?1:u===-1?-1:n-u:d===se?1:c===se?-1:d.localeCompare(c,"zh-CN")})}function xt({hideSkillMountStatus:a,onImport:d,onSelectSkill:c,onUpdateSkill:n,skillUpdates:u,updatingSkillId:b,refreshSignal:Z}){var m;const[w,O]=s.useState([]),[D,_]=s.useState([]),[k,S]=s.useState(null),[G,A]=s.useState(!0),[y,p]=s.useState(re),[j,E]=s.useState(H),[C,R]=s.useState(""),[M,T]=s.useState(!1),[J,F]=s.useState(null),W=s.useRef(null),U=je(),P=me(t=>t.addToast),L=s.useCallback(async()=>{S(null);try{const t=new URLSearchParams;t.set("probe","true");const l=await z(`/api/capabilities?${t.toString()}`);if(!l.ok){const g=await l.json().catch(()=>({}));S(g.error??"加载失败");return}const f=await l.json();O(f.items),_(f.agentFamilies)}catch{S("网络错误")}finally{A(!1)}},[]);s.useEffect(()=>{L()},[L,Z]),s.useEffect(()=>{const t=()=>{document.visibilityState==="visible"&&L()};return document.addEventListener("visibilitychange",t),()=>document.removeEventListener("visibilitychange",t)},[L]);const ee=s.useCallback(async(t,l,f,g="global",B)=>{const ae=B?`${l}:${t}:${B}`:`${l}:${t}`;F(ae);try{const ie={capabilityId:t,capabilityType:l,scope:g,enabled:f};B&&(ie.agentId=B);const ne=await z("/api/capabilities",{method:"PATCH",headers:{"Content-Type":"application/json"},body:JSON.stringify(ie)});if(!ne.ok){const ve=await ne.json().catch(()=>({}));S(ve.error??`开关失败 (${ne.status})`);return}await L()}catch{S("网络错误")}finally{F(null)}},[L]),v=s.useCallback(async t=>{if(await U({title:"卸载技能",message:`确定要卸载 “${t}” 吗?此操作不可恢复。`,confirmLabel:"卸载",cancelLabel:"取消"}))try{const f=await z("/api/skills/uninstall",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:t})});if(f.ok){xe(),P({type:"success",title:"卸载成功",message:`"${t}" 已卸载`,duration:4e3}),await L();return}const B=(await f.json().catch(()=>({}))).error??`HTTP ${f.status}`;P({type:"error",title:"卸载失败",message:B,duration:4e3})}catch{P({type:"error",title:"卸载失败",message:"网络错误,请重试",duration:4e3})}},[P,U,L]),te=s.useMemo(()=>w.filter(t=>t.type!=="mcp"),[w]),$=s.useMemo(()=>te.filter(t=>t.type==="skill"),[te]),Y=s.useMemo(()=>y===re?$:$.filter(t=>t.source===y),[y,$]),V=s.useMemo(()=>{var l;const t=new Map;for(const f of $){const g=((l=f.category)==null?void 0:l.trim())||se;t.set(g,(t.get(g)??0)+1)}return t},[$]),I=s.useMemo(()=>{const t=[H],l=Array.from(V.keys()),f=Re(l);return t.push(...f),t},[V]),q=s.useMemo(()=>j===H?Y:Y.filter(t=>{var l;return(((l=t.category)==null?void 0:l.trim())||se)===j}),[j,Y]),X=s.useMemo(()=>C.trim().toLowerCase(),[C]),r=s.useMemo(()=>X?q.filter(t=>[t.id,t.description??"",t.category??""].join(" ").toLowerCase().includes(X)):q,[q,X]);s.useEffect(()=>{I.includes(j)||E(H)},[j,I]),s.useEffect(()=>{if(!M)return;const t=l=>{var g;const f=l.target;f&&((g=W.current)!=null&&g.contains(f)||T(!1))};return document.addEventListener("mousedown",t),()=>document.removeEventListener("mousedown",t)},[M]);const o=s.useCallback(t=>{R(""),E(H),p(t),T(!1)},[]),i=s.useCallback(t=>{R(""),E(t),T(!1)},[]),x=s.useCallback(()=>{R(""),E(H)},[]),h=((m=le.find(t=>t.id===y))==null?void 0:m.label)??"全部";return G?e.jsx(fe,{}):e.jsxs("div",{className:"flex h-full min-h-0 flex-col overflow-hidden",children:[k&&e.jsx("p",{className:"ui-status-error rounded-[var(--radius-md)] px-3 py-2 text-sm",children:k}),e.jsxs("div",{"data-testid":"hub-capability-fixed-header",children:[e.jsx("div",{className:"flex flex-wrap items-center gap-4",children:le.map((t,l)=>e.jsxs("div",{className:"flex items-center",children:[l>0?e.jsx("div",{"aria-hidden":"true",className:"mr-4 h-4 w-px self-center bg-[#dbdbdb]"}):null,e.jsx("button",{type:"button",onClick:()=>o(t.id),className:`inline-flex min-h-7 items-center leading-none text-sm transition-colors ${y===t.id?"font-semibold text-[var(--text-primary)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)]"}`,children:t.label})]},t.id))}),e.jsxs("div",{className:"pt-6",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("p",{className:"text-[20px] font-semibold",children:`${h} (${r.length})`}),d?e.jsx(Ce,{variant:"major",onClick:d,children:Ie}):null]}),e.jsx("div",{className:"py-6",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{ref:W,className:"relative w-[200px] shrink-0",children:[e.jsx("select",{"aria-label":Te,value:j,onChange:t=>i(t.target.value),className:"sr-only",tabIndex:-1,children:I.map(t=>e.jsx("option",{value:t,children:t},t))}),e.jsxs("button",{type:"button",onClick:()=>T(t=>!t),className:`ui-field flex h-[28px] w-[200px] items-center justify-between rounded-[6px] px-[12px] py-[5px] text-xs transition-colors ${M?"border-[#191919]":""}`,"aria-haspopup":"listbox","aria-expanded":M,children:[e.jsx("span",{className:"truncate text-[var(--text-primary)]",children:j}),e.jsx("svg",{className:`h-3.5 w-3.5 text-[var(--text-muted)] transition-transform duration-200 ${M?"rotate-180":""}`,viewBox:"0 0 16 16",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M4 6L8 10L12 6",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})]}),M?e.jsx("div",{role:"listbox",className:"absolute left-0 top-[calc(100%+4px)] z-30 w-[200px] rounded-[6px] bg-[var(--surface-panel)] py-[8px] shadow-[0_2px_12px_0_var(--tooltip-shadow-color)]",children:I.map(t=>{const l=t===j;return e.jsx("button",{type:"button",role:"option","aria-selected":l,onClick:()=>{i(t)},className:`flex h-[32px] w-full items-center px-[16px] py-[7px] text-left text-xs transition-colors hover:bg-[var(--tag-bg)] ${l?"text-[var(--text-accent)]":"text-[var(--text-primary)]"}`,children:t},t)})}):null]}),e.jsx(ge,{wrapperClassName:"w-full","aria-label":Ee,value:C,onChange:t=>R(t),onClear:()=>R(""),placeholder:Ae,clearAriaLabel:"清除搜索"})]})})]})]}),$.length===0?e.jsx("div",{className:"flex min-h-0 flex-1 items-center justify-center py-16",children:e.jsx(pe,{})}):e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto","data-testid":"hub-capability-scroll-region",children:r.length>0?e.jsx("div",{className:"grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3",children:r.map(t=>e.jsx(_e,{item:t,agentFamilies:D,toggling:J,onToggle:ee,onUninstall:v,onUpdateSkill:n,updatingSkillId:b,skillUpdates:u,onClick:t.type==="skill"?()=>c==null?void 0:c({skillName:t.id,avatarUrl:t.iconUrl??null}):void 0,hideSkillMountStatus:a},`${t.type}:${t.id}`))}):e.jsx("div",{className:"flex min-h-full items-center justify-center py-16",children:e.jsx(he,{onClear:x})})})]})}const Me="_skillGrid_emmae_7",$e="_card_emmae_13",Be="_header_emmae_22",Oe="_content_emmae_28",Pe="_title_emmae_33",De="_description_emmae_40",Ge="_footer_emmae_51",Fe="_installButton_emmae_55",Ye="_installButtonPrimary_emmae_71",qe="_installButtonSuccess_emmae_80",He="_installButtonMuted_emmae_84",N={skillGrid:Me,card:$e,header:Be,content:Oe,title:Pe,description:De,footer:Ge,installButton:Fe,installButtonPrimary:Ye,installButtonSuccess:qe,installButtonMuted:He},Ke="通用技能",Qe="安装中",ze="安装",Ze="暂未提供技能描述。",Je="已安装",ce="搜索技能",K="全部",We=24,Ue=300,Ve="安装成功",de="安装失败",ue=["办公套件"],ye={"ai-intelligence":"AI 智能","developer-tools":"开发工具",productivity:"效率提升","content-creation":"内容创作","data-analysis":"数据分析","security-compliance":"安全合规","communication-collaboration":"沟通协作"};function be(a){return ye[a]??a}function Xe(a){return[...new Set(a)].sort((c,n)=>{const u=ue.indexOf(c),b=ue.indexOf(n);return u!==-1||b!==-1?u===-1?1:b===-1?-1:u-b:c.localeCompare(n,"zh-CN")})}function et(a){var d;return!a||a===K?null:((d=Object.entries(ye).find(([,c])=>c===a))==null?void 0:d[0])??a}function tt(a){var c;if((c=a.category)!=null&&c.trim())return be(a.category.trim());const d=a.tags.find(n=>n.trim().length>0);return d?d.replace(/[-_]/g," "):Ke}function st({slug:a,owner:d,repo:c,status:n,onInstall:u}){return n==="installing"?e.jsx("button",{type:"button",disabled:!0,className:`${N.installButton} ${N.installButtonMuted}`,children:Qe}):e.jsx("button",{type:"button",onClick:()=>u(d,c,a),className:`${N.installButton} ${N.installButtonPrimary}`,children:ze})}function at({results:a,installStatus:d,onInstall:c}){return e.jsx("div",{className:"space-y-4",children:e.jsx("div",{className:N.skillGrid,children:a.skills.map(n=>{const u=n.description.trim()||Ze,b=tt(n);return e.jsxs("article",{className:`ui-card ${N.card}`,children:[e.jsxs("div",{className:N.header,children:[e.jsx(we,{name:n.slug}),e.jsx("div",{className:N.content,children:e.jsx("div",{className:"flex items-start justify-between gap-3",children:e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx(Q,{content:n.slug,className:"min-w-0",as:"h3",textClassName:`${N.title} block truncate`}),e.jsxs("div",{className:"mt-1 flex flex-wrap items-center gap-2 leading-[18px] text-[var(--text-secondary)] text-xs",children:[e.jsx(Q,{content:b,className:"inline-flex max-w-full min-w-0",as:"span",textClassName:"ui-badge-muted inline-block max-w-full truncate align-middle leading-[18px]"}),n.stars!==void 0?e.jsxs("span",{className:"inline-flex items-center gap-1 text-[var(--text-muted)]",children:[e.jsx("svg",{"aria-hidden":"true",className:"h-3 w-3",viewBox:"0 0 12 12",fill:"currentColor",children:e.jsx("path",{d:"M6 1.2 7.55 4.3l3.45.5-2.5 2.45.6 3.45L6 9.1l-3.1 1.6.6-3.45L1 4.8l3.45-.5L6 1.2Z"})}),e.jsx("span",{children:n.stars})]}):null]})]})})})]}),e.jsx(Q,{content:u,className:"w-full",children:e.jsx("p",{className:N.description,children:u})}),e.jsx("div",{className:N.footer,children:n.isInstalled?e.jsx("button",{type:"button",disabled:!0,className:`${N.installButton} ${N.installButtonSuccess} shrink-0`,children:Je}):e.jsx("div",{className:"shrink-0",children:e.jsx(st,{slug:n.slug,owner:n.repo.githubOwner,repo:n.repo.githubRepoName,status:d.get(n.slug),onInstall:c})})})]},n.id)})})})}function ft(){const a=me(r=>r.addToast),[d,c]=s.useState(""),[n,u]=s.useState(null),[b,Z]=s.useState(!1),[w,O]=s.useState(!1),[D,_]=s.useState(1),[k,S]=s.useState("browse"),[G,A]=s.useState(new Map),y=s.useRef(new Map),[p,j]=s.useState(K),[E,C]=s.useState(K),[R,M]=s.useState([]),T=s.useRef(""),J=s.useRef(0),F=s.useRef(null),W=s.useRef(!1),U=s.useRef(null),P=s.useCallback(async()=>{try{const r=await z("/api/skills/categories");if(r.ok){const o=await r.json();M(Xe(o.categories.map(be)))}}catch{}},[]),L=s.useCallback((r,o,i,x)=>{const h=new URLSearchParams({page:String(o),limit:String(We)}),m=et(x);return m&&h.set("category",m),r==="search"?(h.set("keyword",i),`/api/skills/search?${h.toString()}`):`/api/skills/all?${h.toString()}`},[]),ee=s.useCallback((r,o,i)=>!i||!r?o:{...o,skills:[...r.skills,...o.skills]},[]),v=s.useCallback(async({mode:r,page:o,append:i=!1,query:x="",category:h=K})=>{var f;const m=++J.current;(f=F.current)==null||f.abort();const t=new AbortController;F.current=t;const l=i?O:Z;l(!0);try{const g=await z(L(r,o,x,h),{signal:t.signal});if(!g.ok)return;const B=await g.json();if(m!==J.current)return;S(r),u(ae=>ee(ae,B,i)),C(h),_(o)}catch(g){if(g instanceof DOMException&&g.name==="AbortError")return}finally{m===J.current&&l(!1)}},[L,ee]),te=s.useCallback(r=>{T.current="",c(""),j(r),_(1),S("browse"),v({mode:"browse",page:1,category:r})},[v]),$=s.useCallback(()=>{T.current="",c(""),_(1),S("browse"),v({mode:"browse",page:1,category:p})},[p,v]),Y=s.useCallback(()=>{if(!(w||!(n!=null&&n.hasMore))){if(k==="search"){const r=T.current.trim();if(!r)return;v({mode:"search",page:D+1,append:!0,query:r,category:p});return}v({mode:"browse",page:D+1,append:!0,category:p})}},[p,D,v,w,n,k]),V=s.useCallback((r,o)=>{A(x=>new Map(x).set(r,o));const i=y.current.get(r);if(i&&clearTimeout(i),typeof o=="string"&&o!=="installing"){const x=setTimeout(()=>{A(h=>{const m=new Map(h);return m.delete(r),m}),y.current.delete(r)},3e3);y.current.set(r,x)}},[]),I=s.useCallback(r=>{A(i=>{const x=new Map(i);return x.delete(r),x});const o=y.current.get(r);o&&(clearTimeout(o),y.current.delete(r))},[]),q=s.useCallback(r=>{const o=i=>{if(!i)return i;let x=!1;const h=i.skills.map(m=>m.slug!==r||m.isInstalled?m:(x=!0,{...m,isInstalled:!0}));return x?{...i,skills:h}:i};u(i=>o(i))},[]);s.useEffect(()=>{const r=y.current;return()=>{var o;for(const i of r.values())clearTimeout(i);(o=F.current)==null||o.abort()}},[]),s.useEffect(()=>{P()},[P]),s.useEffect(()=>{const r=U.current;if(!r||!(n!=null&&n.hasMore)||w)return;const o=new IntersectionObserver(i=>{i[0].isIntersecting&&Y()},{rootMargin:"200px"});return o.observe(r),()=>o.disconnect()},[n==null?void 0:n.hasMore,w,Y]),s.useEffect(()=>{v({mode:"browse",page:1,category:K})},[v]),s.useEffect(()=>{if(!W.current){W.current=!0;return}const r=setTimeout(()=>{const o=d.trim();if(T.current=o,_(1),!o){v({mode:"browse",page:1,category:p});return}v({mode:"search",page:1,query:o,category:p})},Ue);return()=>clearTimeout(r)},[p,v,d]);const X=s.useCallback(async(r,o,i)=>{var x,h;V(i,"installing");try{const m=await z("/api/skills/install",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({owner:r,repo:o,skill:i,description:((x=n==null?void 0:n.skills.find(t=>t.slug===i))==null?void 0:x.description)??"",version:((h=n==null?void 0:n.skills.find(t=>t.slug===i))==null?void 0:h.version)??""})});if(m.ok)I(i),q(i),xe(),a({type:"success",title:Ve,message:`"${i}" 安装成功,可在我的技能中查看`,duration:4e3});else{const l=(await m.json().catch(()=>({}))).error??`HTTP ${m.status}`;I(i),a({type:"error",title:de,message:l,duration:4e3})}}catch{I(i),a({type:"error",title:de,message:"网络错误,请重试",duration:4e3})}},[a,I,q,n,V]);return!n&&b?e.jsx(fe,{}):e.jsx("div",{className:"flex h-full min-h-0 flex-col overflow-hidden",children:e.jsxs("section",{className:"flex min-h-0 flex-1 flex-col",children:[e.jsxs("div",{className:"shrink-0","data-testid":"hub-skills-fixed-header",children:[R.length>0&&e.jsx("div",{className:"flex flex-wrap items-center gap-4 pb-6",children:[K,...R].map((r,o)=>e.jsxs("div",{className:"flex items-center",children:[o>0?e.jsx("div",{"aria-hidden":"true",className:"mr-4 h-4 w-px self-center bg-[#dbdbdb]"}):null,e.jsx("button",{type:"button",onClick:()=>te(r),className:`inline-flex min-h-7 items-center leading-none text-sm transition-colors ${p===r?"font-semibold text-[var(--text-primary)]":"text-[var(--text-muted)] hover:text-[var(--text-primary)]"}`,children:r})]},r))}),e.jsxs("div",{className:"space-y-0",children:[e.jsxs("p",{className:"text-[20px] font-semibold",children:[E,n?` (${n.total})`:""]}),e.jsx("div",{className:"flex flex-col gap-[var(--space-5)] py-6 sm:flex-row sm:items-center",children:e.jsx(ge,{wrapperClassName:"flex-1","aria-label":ce,value:d,onChange:r=>c(r),onClear:()=>c(""),placeholder:ce,clearAriaLabel:"清除搜索"})})]})]}),e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto","data-testid":"hub-skills-scroll-region",children:n?e.jsxs(e.Fragment,{children:[n.skills.length===0?e.jsx("div",{className:"flex h-full min-h-0 items-center justify-center py-16","data-testid":"hub-skills-empty-state-shell",children:k==="search"?e.jsx(he,{onClear:$}):e.jsx(pe,{})}):e.jsx(at,{results:n,installStatus:G,onInstall:X}),n.skills.length>0&&n.hasMore&&e.jsx("div",{ref:U,className:"flex justify-center py-4",children:w&&e.jsx("span",{className:"text-sm text-[var(--text-muted)]",children:"加载中..."})})]}):null})]})})}export{xt as C,ft as S,Se as s};
2
+ //# sourceMappingURL=SkillsTab-kY7MNdxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SkillsTab-kY7MNdxy.js","sources":["../../src/utils/skill-source-label.ts","../../src/components/skills-panel/components/capability-board-ui.tsx","../../src/components/skills-panel/components/CapabilityTab.tsx","../../src/components/skills-panel/components/SkillsTab.tsx"],"sourcesContent":["export type SkillSource = 'builtin' | 'external';\n\nexport function skillSourceToLabel(source: SkillSource | string): string {\n if (source === 'builtin') return '内置技能';\n if (source === 'external') return '用户添加技能';\n return '其他';\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { type ReactNode } from 'react';\nimport { skillSourceToLabel } from '@/utils/skill-source-label';\nimport { OverflowTooltip } from '../../shared/OverflowTooltip';\nimport { SkillAvatar } from './SkillAvatar';\n\nexport interface CapabilityBoardItem {\n id: string;\n type: 'mcp' | 'skill';\n source: 'builtin' | 'external';\n enabled: boolean;\n agents: Record<string, boolean>;\n description?: string;\n triggers?: string[];\n category?: string;\n mounts?: Record<string, boolean>;\n tools?: { name: string; description?: string }[];\n connectionStatus?: 'connected' | 'disconnected' | 'unknown';\n installedAt?: string;\n iconUrl?: string | null;\n}\n\nexport interface AgentFamily {\n id: string;\n name: string;\n agentIds: string[];\n}\n\nexport interface SkillHealthSummary {\n allMounted: boolean;\n registrationConsistent: boolean;\n unregistered: string[];\n phantom: string[];\n}\n\nexport interface CapabilityBoardResponse {\n items: CapabilityBoardItem[];\n agentFamilies: AgentFamily[];\n projectPath: string;\n skillHealth?: SkillHealthSummary;\n}\n\nexport type ToggleHandler = (\n id: string,\n type: 'mcp' | 'skill',\n enabled: boolean,\n scope?: 'global' | 'agent',\n agentId?: string,\n) => void;\n\nexport function McpIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M12 22v-5\" />\n <path d=\"M9 8V2\" />\n <path d=\"M15 8V2\" />\n <path d=\"M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z\" />\n </svg>\n );\n}\n\nexport function SkillIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z\" />\n <path d=\"M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z\" />\n </svg>\n );\n}\n\nexport function ExtensionIcon({ className }: { className?: string }) {\n return (\n <svg\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M19.439 7.85c-.049.322.059.648.289.878l1.568 1.568c.47.47.706 1.087.706 1.704s-.235 1.233-.706 1.704l-1.611 1.611a.98.98 0 0 1-.837.276c-.47-.07-.802-.48-.968-.925a2.501 2.501 0 1 0-3.214 3.214c.446.166.855.497.925.968a.979.979 0 0 1-.276.837l-1.61 1.61a2.404 2.404 0 0 1-1.705.707 2.402 2.402 0 0 1-1.704-.706l-1.568-1.568a1.026 1.026 0 0 0-.877-.29c-.493.074-.84.504-1.02.968a2.5 2.5 0 1 1-3.237-3.237c.464-.18.894-.527.967-1.02a1.026 1.026 0 0 0-.289-.877l-1.568-1.568A2.402 2.402 0 0 1 1.998 12c0-.617.236-1.234.706-1.704L4.315 8.685a.98.98 0 0 1 .837-.276c.47.07.802.48.968.925a2.501 2.501 0 1 0 3.214-3.214c-.446-.166-.855-.497-.925-.968a.979.979 0 0 1 .276-.837l1.61-1.61a2.404 2.404 0 0 1 1.705-.707c.617 0 1.234.236 1.704.706l1.568 1.568c.23.23.556.338.877.29.493-.074.84-.504 1.02-.969a2.5 2.5 0 1 1 3.237 3.237c-.464.18-.894.527-.967 1.02Z\" />\n </svg>\n );\n}\n\nfunction getSourceLabel(source: CapabilityBoardItem['source']): string {\n return skillSourceToLabel(source);\n}\n\nexport function CapabilitySection({\n title,\n subtitle: _subtitle,\n headerSlot,\n headerSlotClassName,\n titleActionSlot,\n showWhenEmpty,\n emptyState,\n items,\n agentFamilies,\n toggling,\n onToggle,\n onUninstall,\n onUpdateSkill,\n updatingSkillId,\n skillUpdates,\n hideSkillMountStatus: _hideSkillMountStatus,\n}: {\n icon: ReactNode;\n title: string;\n subtitle: string;\n headerSlot?: ReactNode;\n headerSlotClassName?: string;\n titleActionSlot?: ReactNode;\n showWhenEmpty?: boolean;\n emptyState?: ReactNode;\n items: CapabilityBoardItem[];\n agentFamilies: AgentFamily[];\n toggling: string | null;\n onToggle: ToggleHandler;\n onUninstall?: (id: string) => void;\n onUpdateSkill?: (id: string) => void;\n updatingSkillId?: string | null;\n skillUpdates?: ReadonlySet<string>;\n hideSkillMountStatus?: boolean;\n}) {\n if (items.length === 0 && !showWhenEmpty) return null;\n\n return (\n <div className=\"mb-6 pt-6\">\n <div>\n <div className=\"flex items-center justify-between gap-3\">\n <p className=\"text-[20px] font-semibold\">{title}</p>\n {titleActionSlot ? <div className=\"shrink-0\">{titleActionSlot}</div> : null}\n </div>\n {headerSlot ? <div className={headerSlotClassName ?? 'mt-3'}>{headerSlot}</div> : null}\n </div>\n {items.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {items.map((item) => (\n <CapabilityCard\n key={`${item.type}:${item.id}`}\n item={item}\n agentFamilies={agentFamilies}\n toggling={toggling}\n onToggle={onToggle}\n onUninstall={onUninstall}\n onUpdateSkill={onUpdateSkill}\n updatingSkillId={updatingSkillId}\n skillUpdates={skillUpdates}\n hideSkillMountStatus={_hideSkillMountStatus}\n />\n ))}\n </div>\n ) : (\n (emptyState ?? null)\n )}\n </div>\n );\n}\n\nexport function CapabilityCard({\n item,\n agentFamilies: _agentFamilies,\n toggling,\n onToggle,\n onUninstall,\n onUpdateSkill,\n updatingSkillId,\n skillUpdates,\n onClick,\n hideSkillMountStatus: _hideSkillMountStatus,\n}: {\n item: CapabilityBoardItem;\n agentFamilies: AgentFamily[];\n toggling: string | null;\n onToggle: ToggleHandler;\n onUninstall?: (id: string) => void;\n onUpdateSkill?: (id: string) => void;\n updatingSkillId?: string | null;\n skillUpdates?: ReadonlySet<string>;\n onClick?: () => void;\n hideSkillMountStatus?: boolean;\n}) {\n const isToggling = toggling === `${item.type}:${item.id}`;\n const sourceLabel = getSourceLabel(item.source);\n const resolvedDescription = item.description?.trim() || '暂未提供技能描述。';\n const resolvedAgentegory = item.category?.trim() || '其他';\n const showDeleteAction = item.source === 'external' && typeof onUninstall === 'function';\n const showUpdateAction = item.type === 'skill' && Boolean(skillUpdates?.has(item.id)) && typeof onUpdateSkill === 'function';\n const isUpdating = updatingSkillId === item.id;\n const isClickable = typeof onClick === 'function';\n\n return (\n <div\n className={`ui-card ui-card-hover group flex flex-col gap-4 ${isClickable ? 'cursor-pointer' : ''}`}\n data-testid={`capability-card-${item.type}-${item.id}`}\n onClick={onClick}\n onKeyDown={\n isClickable\n ? (event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onClick();\n }\n }\n : undefined\n }\n role={isClickable ? 'button' : undefined}\n tabIndex={isClickable ? 0 : undefined}\n >\n <div className=\"flex items-start gap-3\">\n <SkillAvatar avatarName={item.id} avatarUrl={item.iconUrl} />\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-start gap-2\">\n <OverflowTooltip\n content={item.id}\n className=\"min-w-0 flex-1\"\n as=\"h3\"\n textClassName=\"block truncate text-base font-semibold text-[var(--text-primary)]\"\n />\n {item.connectionStatus ? <StatusDot status={item.connectionStatus} /> : null}\n </div>\n <div className=\"mt-1 flex flex-wrap items-center gap-2 text-xs\">\n {showUpdateAction ? (\n <span className=\"ui-badge-muted inline-flex items-center gap-1 border-[rgba(194,87,0,0.28)] bg-[rgba(194,87,0,0.10)] text-[rgba(194,87,0,1)]\">\n <svg\n aria-hidden=\"true\"\n className=\"h-4 w-4 shrink-0 opacity-80\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.25\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M8 2.1A4.15 4.15 0 0 0 3.85 6.25v2.1c0 .76-.25 1.5-.72 2.1L2.6 11.1h10.8l-.53-.65a3.4 3.4 0 0 1-.72-2.1v-2.1A4.15 4.15 0 0 0 8 2.1Z\" />\n <path d=\"M6.85 13a1.25 1.25 0 0 0 2.3 0\" />\n </svg>\n 有更新\n </span>\n ) : null}\n <OverflowTooltip\n content={resolvedAgentegory}\n className=\"inline-flex max-w-full min-w-0\"\n as=\"span\"\n textClassName=\"ui-badge-muted inline-block max-w-full truncate align-middle leading-[18px]\"\n />\n </div>\n </div>\n </div>\n\n <OverflowTooltip content={resolvedDescription} className=\"w-full\">\n <p className=\"line-clamp-2 min-h-[44px] text-sm leading-6 text-[var(--text-secondary)]\">{resolvedDescription}</p>\n </OverflowTooltip>\n\n <div className=\"flex items-end justify-between gap-3\">\n <div className=\"min-h-5 text-xs leading-5\">\n {showDeleteAction || showUpdateAction ? (\n <div className=\"relative\">\n <span className=\"text-[var(--text-muted)] transition-opacity duration-200 group-hover:opacity-0\">\n 来源:{sourceLabel}\n </span>\n <div className=\"absolute left-0 top-0 flex items-center gap-3 opacity-0 transition-opacity duration-200 group-hover:opacity-100\">\n {showUpdateAction ? (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onUpdateSkill?.(item.id);\n }}\n disabled={isUpdating}\n className=\"text-[14px] font-bold text-[var(--text-accent)] hover:underline disabled:cursor-not-allowed disabled:opacity-60\"\n >\n {isUpdating ? '更新中' : '更新'}\n </button>\n ) : null}\n {showDeleteAction ? (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onUninstall?.(item.id);\n }}\n className=\"text-[14px] font-bold text-[var(--text-accent)] hover:underline\"\n >\n 卸载\n </button>\n ) : null}\n </div>\n </div>\n ) : (\n <span className=\"text-[var(--text-muted)]\">来源:{sourceLabel}</span>\n )}\n </div>\n </div>\n </div>\n );\n}\n\nexport function StatusDot({ status }: { status: 'connected' | 'disconnected' | 'unknown' }) {\n const color =\n status === 'connected'\n ? 'bg-[var(--state-success-text)]'\n : status === 'disconnected'\n ? 'bg-[var(--state-error-text)]'\n : 'bg-[var(--text-muted)]';\n const label = status === 'connected' ? '已连接' : status === 'disconnected' ? '掉线' : '未知';\n return <span className={`inline-block h-2 w-2 rounded-full ${color}`} title={label} />;\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { notifySkillOptionsChanged } from '@/utils/skill-options-cache';\nimport type { CapabilityBoardItem, CapabilityBoardResponse, AgentFamily, ToggleHandler } from './capability-board-ui';\nimport { CapabilityCard } from './capability-board-ui';\nimport { CenteredLoadingState } from '../../shared/CenteredLoadingState';\nimport { EmptyDataState } from '../../shared/EmptyDataState';\nimport { NoSearchResultsState } from '../../shared/NoSearchResultsState';\nimport { SearchInput } from '../../shared/SearchInput';\nimport { Button } from '../../shared/Button';\nimport { useConfirm } from '../../useConfirm';\n\nconst ALL_CATEGORY = '全部';\nconst UNCATEGORIZED = '其他';\nconst SKILL_SEARCH_PLACEHOLDER = '搜索技能';\nconst SKILL_SEARCH_ARIA_LABEL = '搜索我的技能';\nconst CATEGORY_FILTER_ARIA_LABEL = '筛选分类';\nconst IMPORT_LABEL = '导入';\nconst CATEGORY_TAB_PRIORITY = ['办公套件'];\nconst ALL_SKILL_SOURCES = 'all';\ntype SkillSourceScope = CapabilityBoardItem['source'] | typeof ALL_SKILL_SOURCES;\nconst SKILL_SCOPE_TABS: readonly { id: SkillSourceScope; label: string }[] = [\n { id: ALL_SKILL_SOURCES, label: '全部' },\n { id: 'external', label: '我添加的' },\n { id: 'builtin', label: '平台精选' },\n];\nexport interface SelectedSkillSummary {\n skillName: string;\n avatarUrl?: string | null;\n}\n\nfunction sortCategoryTabs(categories: string[]): string[] {\n return [...categories].sort((left, right) => {\n const leftIndex = CATEGORY_TAB_PRIORITY.indexOf(left);\n const rightIndex = CATEGORY_TAB_PRIORITY.indexOf(right);\n if (leftIndex !== -1 || rightIndex !== -1) {\n if (leftIndex === -1) return 1;\n if (rightIndex === -1) return -1;\n return leftIndex - rightIndex;\n }\n if (left === UNCATEGORIZED) return 1;\n if (right === UNCATEGORIZED) return -1;\n return left.localeCompare(right, 'zh-CN');\n });\n}\n\nexport function CapabilityTab({\n hideSkillMountStatus,\n onImport,\n onSelectSkill,\n onUpdateSkill,\n skillUpdates,\n updatingSkillId,\n refreshSignal,\n}: {\n hideSkillMountStatus?: boolean;\n onImport?: () => void;\n onSelectSkill?: (selection: SelectedSkillSummary) => void;\n onUpdateSkill?: (skillId: string) => void;\n skillUpdates?: ReadonlySet<string>;\n updatingSkillId?: string | null;\n refreshSignal?: number;\n}) {\n const [items, setItems] = useState<CapabilityBoardItem[]>([]);\n const [agentFamilies, setAgentFamilies] = useState<AgentFamily[]>([]);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [activeSkillSource, setActiveSkillSource] = useState<SkillSourceScope>(ALL_SKILL_SOURCES);\n const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);\n const [searchQuery, setSearchQuery] = useState('');\n const [isCategoryMenuOpen, setIsCategoryMenuOpen] = useState(false);\n const [toggling, setToggling] = useState<string | null>(null);\n const categoryMenuRef = useRef<HTMLDivElement>(null);\n\n const confirm = useConfirm();\n const addToast = useToastStore((state) => state.addToast);\n\n const fetchCapabilities = useCallback(async () => {\n setError(null);\n try {\n const query = new URLSearchParams();\n query.set('probe', 'true');\n const res = await apiFetch(`/api/capabilities?${query.toString()}`);\n if (!res.ok) {\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n setError((data.error as string) ?? '加载失败');\n return;\n }\n const data = (await res.json()) as CapabilityBoardResponse;\n setItems(data.items);\n setAgentFamilies(data.agentFamilies);\n } catch {\n setError('网络错误');\n } finally {\n setLoading(false);\n }\n }, []);\n\n useEffect(() => {\n void fetchCapabilities();\n }, [fetchCapabilities, refreshSignal]);\n\n useEffect(() => {\n const onVisible = () => {\n if (document.visibilityState === 'visible') {\n void fetchCapabilities();\n }\n };\n document.addEventListener('visibilitychange', onVisible);\n return () => document.removeEventListener('visibilitychange', onVisible);\n }, [fetchCapabilities]);\n\n const handleToggle: ToggleHandler = useCallback(\n async (capabilityId, capabilityType, enabled, scope = 'global', agentId) => {\n const toggleKey = agentId ? `${capabilityType}:${capabilityId}:${agentId}` : `${capabilityType}:${capabilityId}`;\n setToggling(toggleKey);\n try {\n const body: Record<string, unknown> = {\n capabilityId,\n capabilityType,\n scope,\n enabled,\n };\n if (agentId) body.agentId = agentId;\n\n const res = await apiFetch('/api/capabilities', {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n const data = (await res.json().catch(() => ({}))) as Record<string, unknown>;\n setError((data.error as string) ?? `开关失败 (${res.status})`);\n return;\n }\n await fetchCapabilities();\n } catch {\n setError('网络错误');\n } finally {\n setToggling(null);\n }\n },\n [fetchCapabilities],\n );\n\n const handleUninstall = useCallback(\n async (skillId: string) => {\n const ok = await confirm({\n title: '卸载技能',\n message: `确定要卸载 “${skillId}” 吗?此操作不可恢复。`,\n confirmLabel: '卸载',\n cancelLabel: '取消',\n });\n if (!ok) return;\n try {\n const res = await apiFetch('/api/skills/uninstall', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: skillId }),\n });\n if (res.ok) {\n notifySkillOptionsChanged();\n addToast({\n type: 'success',\n title: '卸载成功',\n message: `\"${skillId}\" 已卸载`,\n duration: 4000,\n });\n await fetchCapabilities();\n return;\n }\n const payload = (await res.json().catch(() => ({}))) as { error?: string };\n const detail = payload.error ?? `HTTP ${res.status}`;\n addToast({\n type: 'error',\n title: '卸载失败',\n message: detail,\n duration: 4000,\n });\n } catch {\n addToast({\n type: 'error',\n title: '卸载失败',\n message: '网络错误,请重试',\n duration: 4000,\n });\n }\n },\n [addToast, confirm, fetchCapabilities],\n );\n\n const visibleItems = useMemo(() => items.filter((item) => item.type !== 'mcp'), [items]);\n const skillItems = useMemo(() => visibleItems.filter((item) => item.type === 'skill'), [visibleItems]);\n const sourceScopedSkillItems = useMemo(\n () => (activeSkillSource === ALL_SKILL_SOURCES ? skillItems : skillItems.filter((item) => item.source === activeSkillSource)),\n [activeSkillSource, skillItems],\n );\n const categoryCounts = useMemo(() => {\n const counts = new Map<string, number>();\n for (const item of skillItems) {\n const category = item.category?.trim() || UNCATEGORIZED;\n counts.set(category, (counts.get(category) ?? 0) + 1);\n }\n return counts;\n }, [skillItems]);\n const categoryOptions = useMemo(() => {\n const options = [ALL_CATEGORY];\n const categories = Array.from(categoryCounts.keys());\n const ordered = sortCategoryTabs(categories);\n options.push(...ordered);\n return options;\n }, [categoryCounts]);\n const categoryFilteredItems = useMemo(() => {\n if (activeCategory === ALL_CATEGORY) return sourceScopedSkillItems;\n return sourceScopedSkillItems.filter((item) => (item.category?.trim() || UNCATEGORIZED) === activeCategory);\n }, [activeCategory, sourceScopedSkillItems]);\n const normalizedSearchQuery = useMemo(() => searchQuery.trim().toLowerCase(), [searchQuery]);\n const filteredDisplayedSkillItems = useMemo(() => {\n if (!normalizedSearchQuery) return categoryFilteredItems;\n return categoryFilteredItems.filter((item) => {\n const haystack = [item.id, item.description ?? '', item.category ?? ''].join(' ').toLowerCase();\n return haystack.includes(normalizedSearchQuery);\n });\n }, [categoryFilteredItems, normalizedSearchQuery]);\n\n useEffect(() => {\n if (!categoryOptions.includes(activeCategory)) setActiveCategory(ALL_CATEGORY);\n }, [activeCategory, categoryOptions]);\n\n useEffect(() => {\n if (!isCategoryMenuOpen) return;\n const onPointerDown = (event: MouseEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (categoryMenuRef.current?.contains(target)) return;\n setIsCategoryMenuOpen(false);\n };\n document.addEventListener('mousedown', onPointerDown);\n return () => document.removeEventListener('mousedown', onPointerDown);\n }, [isCategoryMenuOpen]);\n\n const handleSkillSourceChange = useCallback((source: SkillSourceScope) => {\n setSearchQuery('');\n setActiveCategory(ALL_CATEGORY);\n setActiveSkillSource(source);\n setIsCategoryMenuOpen(false);\n }, []);\n\n const handleCategoryChange = useCallback((category: string) => {\n setSearchQuery('');\n setActiveCategory(category);\n setIsCategoryMenuOpen(false);\n }, []);\n\n const handleClearFilters = useCallback(() => {\n setSearchQuery('');\n setActiveCategory(ALL_CATEGORY);\n }, []);\n\n const activeSkillSourceLabel = SKILL_SCOPE_TABS.find((tab) => tab.id === activeSkillSource)?.label ?? '全部';\n\n if (loading) return <CenteredLoadingState />;\n\n return (\n <div className=\"flex h-full min-h-0 flex-col overflow-hidden\">\n {error && <p className=\"ui-status-error rounded-[var(--radius-md)] px-3 py-2 text-sm\">{error}</p>}\n\n <div data-testid=\"hub-capability-fixed-header\">\n <div className=\"flex flex-wrap items-center gap-4\">\n {SKILL_SCOPE_TABS.map((tab, index) => (\n <div key={tab.id} className=\"flex items-center\">\n {index > 0 ? <div aria-hidden=\"true\" className=\"mr-4 h-4 w-px self-center bg-[#dbdbdb]\" /> : null}\n <button\n type=\"button\"\n onClick={() => handleSkillSourceChange(tab.id)}\n className={`inline-flex min-h-7 items-center leading-none text-sm transition-colors ${activeSkillSource === tab.id\n ? 'font-semibold text-[var(--text-primary)]'\n : 'text-[var(--text-muted)] hover:text-[var(--text-primary)]'\n }`}\n >\n {tab.label}\n </button>\n </div>\n ))}\n </div>\n <div className=\"pt-6\">\n <div className=\"flex items-center justify-between gap-3\">\n <p className=\"text-[20px] font-semibold\">{`${activeSkillSourceLabel} (${filteredDisplayedSkillItems.length})`}</p>\n {onImport ? (\n <Button variant=\"major\" onClick={onImport}>\n {IMPORT_LABEL}\n </Button>\n ) : null}\n </div>\n <div className=\"py-6\">\n <div className=\"flex items-center gap-2\">\n <div ref={categoryMenuRef} className=\"relative w-[200px] shrink-0\">\n <select\n aria-label={CATEGORY_FILTER_ARIA_LABEL}\n value={activeCategory}\n onChange={(event) => handleCategoryChange(event.target.value)}\n className=\"sr-only\"\n tabIndex={-1}\n >\n {categoryOptions.map((category) => (\n <option key={category} value={category}>\n {category}\n </option>\n ))}\n </select>\n <button\n type=\"button\"\n onClick={() => setIsCategoryMenuOpen((prev) => !prev)}\n className={`ui-field flex h-[28px] w-[200px] items-center justify-between rounded-[6px] px-[12px] py-[5px] text-xs transition-colors ${isCategoryMenuOpen ? 'border-[#191919]' : ''\n }`}\n aria-haspopup=\"listbox\"\n aria-expanded={isCategoryMenuOpen}\n >\n <span className=\"truncate text-[var(--text-primary)]\">{activeCategory}</span>\n <svg\n className={`h-3.5 w-3.5 text-[var(--text-muted)] transition-transform duration-200 ${isCategoryMenuOpen ? 'rotate-180' : ''\n }`}\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path d=\"M4 6L8 10L12 6\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n {isCategoryMenuOpen ? (\n <div\n role=\"listbox\"\n className=\"absolute left-0 top-[calc(100%+4px)] z-30 w-[200px] rounded-[6px] bg-[var(--surface-panel)] py-[8px] shadow-[0_2px_12px_0_var(--tooltip-shadow-color)]\"\n >\n {categoryOptions.map((category) => {\n const isSelected = category === activeCategory;\n return (\n <button\n key={category}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => {\n handleCategoryChange(category);\n }}\n className={`flex h-[32px] w-full items-center px-[16px] py-[7px] text-left text-xs transition-colors hover:bg-[var(--tag-bg)] ${isSelected ? 'text-[var(--text-accent)]' : 'text-[var(--text-primary)]'\n }`}\n >\n {category}\n </button>\n );\n })}\n </div>\n ) : null}\n </div>\n <SearchInput\n wrapperClassName=\"w-full\"\n aria-label={SKILL_SEARCH_ARIA_LABEL}\n value={searchQuery}\n onChange={(value) => setSearchQuery(value)}\n onClear={() => setSearchQuery('')}\n placeholder={SKILL_SEARCH_PLACEHOLDER}\n clearAriaLabel=\"清除搜索\"\n />\n </div>\n </div>\n </div>\n </div>\n\n {skillItems.length === 0 ? (\n <div className=\"flex min-h-0 flex-1 items-center justify-center py-16\">\n <EmptyDataState />\n </div>\n ) : (\n <div className=\"min-h-0 flex-1 overflow-y-auto\" data-testid=\"hub-capability-scroll-region\">\n {filteredDisplayedSkillItems.length > 0 ? (\n <div className=\"grid grid-cols-1 gap-3 md:grid-cols-2 xl:grid-cols-3\">\n {filteredDisplayedSkillItems.map((item) => (\n <CapabilityCard\n key={`${item.type}:${item.id}`}\n item={item}\n agentFamilies={agentFamilies}\n toggling={toggling}\n onToggle={handleToggle}\n onUninstall={handleUninstall}\n onUpdateSkill={onUpdateSkill}\n updatingSkillId={updatingSkillId}\n skillUpdates={skillUpdates}\n onClick={\n item.type === 'skill'\n ? () =>\n onSelectSkill?.({\n skillName: item.id,\n avatarUrl: item.iconUrl ?? null,\n })\n : undefined\n }\n hideSkillMountStatus={hideSkillMountStatus}\n />\n ))}\n </div>\n ) : (\n <div className=\"flex min-h-full items-center justify-center py-16\">\n <NoSearchResultsState onClear={handleClearFilters} />\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { notifySkillOptionsChanged } from '@/utils/skill-options-cache';\nimport styles from './SkillsTab.module.css';\nimport { CenteredLoadingState } from '../../shared/CenteredLoadingState';\nimport { EmptyDataState } from '../../shared/EmptyDataState';\nimport { NoSearchResultsState } from '../../shared/NoSearchResultsState';\nimport { OverflowTooltip } from '../../shared/OverflowTooltip';\nimport { SearchInput } from '../../shared/SearchInput';\nimport { NameInitialIcon } from '../../NameInitialIcon';\n\ninterface SearchSkill {\n id: string;\n slug: string;\n name: string;\n description: string;\n version?: string;\n category?: string;\n tags: string[];\n stars?: number;\n repo: { githubOwner: string; githubRepoName: string };\n isInstalled: boolean;\n}\n\ninterface SearchResult {\n skills: SearchSkill[];\n total: number;\n page: number;\n hasMore: boolean;\n}\n\ntype InstallStatus = 'installing' | string;\ntype ViewMode = 'browse' | 'search';\n\nconst GENERAL_CATEGORY = '通用技能';\nconst INSTALLING_LABEL = '安装中';\nconst INSTALL_LABEL = '安装';\nconst FALLBACK_DESCRIPTION = '暂未提供技能描述。';\nconst INSTALLED_LABEL = '已安装';\nconst SEARCH_ARIA_LABEL = '搜索技能';\nconst ALL_CATEGORY = '全部';\nconst PAGE_SIZE = 24;\nconst SEARCH_DEBOUNCE_MS = 300;\nconst INSTALL_SUCCESS_TITLE = '安装成功';\nconst INSTALL_FAILURE_TITLE = '安装失败';\nconst CATEGORY_TAB_PRIORITY = ['办公套件'];\n\nconst CATEGORY_MAP: Record<string, string> = {\n 'ai-intelligence': 'AI 智能',\n 'developer-tools': '开发工具',\n productivity: '效率提升',\n 'content-creation': '内容创作',\n 'data-analysis': '数据分析',\n 'security-compliance': '安全合规',\n 'communication-collaboration': '沟通协作',\n};\n\nfunction normalizeCategory(cat: string): string {\n return CATEGORY_MAP[cat] ?? cat;\n}\n\nfunction sortCategoryTabs(categories: string[]): string[] {\n const unique = [...new Set(categories)];\n return unique.sort((left, right) => {\n const leftIndex = CATEGORY_TAB_PRIORITY.indexOf(left);\n const rightIndex = CATEGORY_TAB_PRIORITY.indexOf(right);\n if (leftIndex !== -1 || rightIndex !== -1) {\n if (leftIndex === -1) return 1;\n if (rightIndex === -1) return -1;\n return leftIndex - rightIndex;\n }\n return left.localeCompare(right, 'zh-CN');\n });\n}\n\nfunction resolveCategoryParam(category: string): string | null {\n if (!category || category === ALL_CATEGORY) return null;\n return Object.entries(CATEGORY_MAP).find(([, zh]) => zh === category)?.[0] ?? category;\n}\n\nfunction getSkillCategory(skill: SearchSkill): string {\n if (skill.category?.trim()) {\n return normalizeCategory(skill.category.trim());\n }\n const primaryTag = skill.tags.find((tag) => tag.trim().length > 0);\n return primaryTag ? primaryTag.replace(/[-_]/g, ' ') : GENERAL_CATEGORY;\n}\n\nfunction InstallButton({\n slug,\n owner,\n repo,\n status,\n onInstall,\n}: {\n slug: string;\n owner: string;\n repo: string;\n status: InstallStatus | undefined;\n onInstall: (owner: string, repo: string, skill: string) => void;\n}) {\n if (status === 'installing') {\n return (\n <button type=\"button\" disabled className={`${styles.installButton} ${styles.installButtonMuted}`}>\n {INSTALLING_LABEL}\n </button>\n );\n }\n return (\n <button\n type=\"button\"\n onClick={() => onInstall(owner, repo, slug)}\n className={`${styles.installButton} ${styles.installButtonPrimary}`}\n >\n {INSTALL_LABEL}\n </button>\n );\n}\n\nfunction SkillList({\n results,\n installStatus,\n onInstall,\n}: {\n results: SearchResult;\n installStatus: Map<string, InstallStatus>;\n onInstall: (owner: string, repo: string, skill: string) => void;\n}) {\n return (\n <div className=\"space-y-4\">\n <div className={styles.skillGrid}>\n {results.skills.map((skill) => {\n const resolvedDescription = skill.description.trim() || FALLBACK_DESCRIPTION;\n const resolvedAgentegory = getSkillCategory(skill);\n\n return (\n <article key={skill.id} className={`ui-card ${styles.card}`}>\n <div className={styles.header}>\n <NameInitialIcon name={skill.slug} />\n <div className={styles.content}>\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">\n <OverflowTooltip\n content={skill.slug}\n className=\"min-w-0\"\n as=\"h3\"\n textClassName={`${styles.title} block truncate`}\n />\n <div className=\"mt-1 flex flex-wrap items-center gap-2 leading-[18px] text-[var(--text-secondary)] text-xs\">\n <OverflowTooltip\n content={resolvedAgentegory}\n className=\"inline-flex max-w-full min-w-0\"\n as=\"span\"\n textClassName=\"ui-badge-muted inline-block max-w-full truncate align-middle leading-[18px]\"\n />\n {skill.stars !== undefined ? (\n <span className=\"inline-flex items-center gap-1 text-[var(--text-muted)]\">\n <svg aria-hidden=\"true\" className=\"h-3 w-3\" viewBox=\"0 0 12 12\" fill=\"currentColor\">\n <path d=\"M6 1.2 7.55 4.3l3.45.5-2.5 2.45.6 3.45L6 9.1l-3.1 1.6.6-3.45L1 4.8l3.45-.5L6 1.2Z\" />\n </svg>\n <span>{skill.stars}</span>\n </span>\n ) : null}\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <OverflowTooltip content={resolvedDescription} className=\"w-full\">\n <p className={styles.description}>{resolvedDescription}</p>\n </OverflowTooltip>\n\n <div className={styles.footer}>\n {!skill.isInstalled ? (\n <div className=\"shrink-0\">\n <InstallButton\n slug={skill.slug}\n owner={skill.repo.githubOwner}\n repo={skill.repo.githubRepoName}\n status={installStatus.get(skill.slug)}\n onInstall={onInstall}\n />\n </div>\n ) : (\n <button\n type=\"button\"\n disabled\n className={`${styles.installButton} ${styles.installButtonSuccess} shrink-0`}\n >\n {INSTALLED_LABEL}\n </button>\n )}\n </div>\n </article>\n );\n })}\n </div>\n </div>\n );\n}\n\nexport function SkillsTab() {\n const addToast = useToastStore((s) => s.addToast);\n const [searchQuery, setSearchQuery] = useState('');\n const [results, setResults] = useState<SearchResult | null>(null);\n const [loading, setLoading] = useState(false);\n const [loadingMore, setLoadingMore] = useState(false);\n const [currentPage, setCurrentPage] = useState(1);\n const [viewMode, setViewMode] = useState<ViewMode>('browse');\n const [installStatus, setInstallStatus] = useState<Map<string, InstallStatus>>(new Map());\n const statusTimers = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());\n const [activeCategory, setActiveCategory] = useState(ALL_CATEGORY);\n const [displayCategory, setDisplayCategory] = useState(ALL_CATEGORY);\n const [categories, setCategories] = useState<string[]>([]);\n const latestQueryRef = useRef('');\n const requestSeqRef = useRef(0);\n const activeAbortRef = useRef<AbortController | null>(null);\n const searchEffectReadyRef = useRef(false);\n const loadMoreTriggerRef = useRef<HTMLDivElement>(null);\n\n const loadCategories = useCallback(async () => {\n try {\n const res = await apiFetch('/api/skills/categories');\n if (res.ok) {\n const data = (await res.json()) as { categories: string[] };\n setCategories(sortCategoryTabs(data.categories.map(normalizeCategory)));\n }\n } catch {\n // ignore error\n }\n }, []);\n\n const buildSkillsUrl = useCallback((mode: ViewMode, page: number, query: string, category: string) => {\n const params = new URLSearchParams({ page: String(page), limit: String(PAGE_SIZE) });\n const categoryParam = resolveCategoryParam(category);\n if (categoryParam) {\n params.set('category', categoryParam);\n }\n if (mode === 'search') {\n params.set('keyword', query);\n return `/api/skills/search?${params.toString()}`;\n }\n return `/api/skills/all?${params.toString()}`;\n }, []);\n\n const mergeResults = useCallback((prev: SearchResult | null, next: SearchResult, append: boolean): SearchResult => {\n if (!append || !prev) return next;\n return {\n ...next,\n skills: [...prev.skills, ...next.skills],\n };\n }, []);\n\n const loadPage = useCallback(\n async ({\n mode,\n page,\n append = false,\n query = '',\n category = ALL_CATEGORY,\n }: {\n mode: ViewMode;\n page: number;\n append?: boolean;\n query?: string;\n category?: string;\n }) => {\n const requestId = ++requestSeqRef.current;\n activeAbortRef.current?.abort();\n const controller = new AbortController();\n activeAbortRef.current = controller;\n\n const setLoadingFn = append ? setLoadingMore : setLoading;\n setLoadingFn(true);\n\n try {\n const res = await apiFetch(buildSkillsUrl(mode, page, query, category), { signal: controller.signal });\n if (!res.ok) return;\n const data = (await res.json()) as SearchResult;\n if (requestId !== requestSeqRef.current) return;\n\n setViewMode(mode);\n setResults((prev) => mergeResults(prev, data, append));\n setDisplayCategory(category);\n setCurrentPage(page);\n } catch (error) {\n if (error instanceof DOMException && error.name === 'AbortError') return;\n // ignore error\n } finally {\n if (requestId === requestSeqRef.current) {\n setLoadingFn(false);\n }\n }\n },\n [buildSkillsUrl, mergeResults],\n );\n\n const handleCategoryChange = useCallback(\n (category: string) => {\n latestQueryRef.current = '';\n setSearchQuery('');\n setActiveCategory(category);\n setCurrentPage(1);\n setViewMode('browse');\n void loadPage({ mode: 'browse', page: 1, category });\n },\n [loadPage],\n );\n\n const handleClearFilters = useCallback(() => {\n latestQueryRef.current = '';\n setSearchQuery('');\n setCurrentPage(1);\n setViewMode('browse');\n void loadPage({ mode: 'browse', page: 1, category: activeCategory });\n }, [activeCategory, loadPage]);\n\n const handleLoadMore = useCallback(() => {\n if (loadingMore || !results?.hasMore) return;\n if (viewMode === 'search') {\n const query = latestQueryRef.current.trim();\n if (!query) return;\n void loadPage({ mode: 'search', page: currentPage + 1, append: true, query, category: activeCategory });\n return;\n }\n void loadPage({ mode: 'browse', page: currentPage + 1, append: true, category: activeCategory });\n }, [activeCategory, currentPage, loadPage, loadingMore, results, viewMode]);\n\n const setInstallStatusWithTimer = useCallback((slug: string, status: InstallStatus) => {\n setInstallStatus((prev) => new Map(prev).set(slug, status));\n const existing = statusTimers.current.get(slug);\n if (existing) clearTimeout(existing);\n if (typeof status === 'string' && status !== 'installing') {\n const timer = setTimeout(() => {\n setInstallStatus((prev) => {\n const next = new Map(prev);\n next.delete(slug);\n return next;\n });\n statusTimers.current.delete(slug);\n }, 3000);\n statusTimers.current.set(slug, timer);\n }\n }, []);\n\n const clearInstallStatus = useCallback((slug: string) => {\n setInstallStatus((prev) => {\n const next = new Map(prev);\n next.delete(slug);\n return next;\n });\n const existing = statusTimers.current.get(slug);\n if (existing) {\n clearTimeout(existing);\n statusTimers.current.delete(slug);\n }\n }, []);\n\n const markSkillInstalled = useCallback((slug: string) => {\n const markInstalled = (result: SearchResult | null): SearchResult | null => {\n if (!result) return result;\n let changed = false;\n const skills = result.skills.map((item) => {\n if (item.slug !== slug || item.isInstalled) return item;\n changed = true;\n return { ...item, isInstalled: true };\n });\n return changed ? { ...result, skills } : result;\n };\n\n setResults((prev) => markInstalled(prev));\n }, []);\n\n useEffect(() => {\n const timers = statusTimers.current;\n return () => {\n for (const timer of timers.values()) clearTimeout(timer);\n activeAbortRef.current?.abort();\n };\n }, []);\n\n useEffect(() => {\n void loadCategories();\n }, [loadCategories]);\n\n useEffect(() => {\n const el = loadMoreTriggerRef.current;\n if (!el || !results?.hasMore || loadingMore) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n if (entries[0].isIntersecting) {\n handleLoadMore();\n }\n },\n { rootMargin: '200px' }\n );\n\n observer.observe(el);\n return () => observer.disconnect();\n }, [results?.hasMore, loadingMore, handleLoadMore]);\n\n useEffect(() => {\n void loadPage({ mode: 'browse', page: 1, category: ALL_CATEGORY });\n }, [loadPage]);\n\n useEffect(() => {\n if (!searchEffectReadyRef.current) {\n searchEffectReadyRef.current = true;\n return;\n }\n\n const timer = setTimeout(() => {\n const trimmed = searchQuery.trim();\n latestQueryRef.current = trimmed;\n setCurrentPage(1);\n\n if (!trimmed) {\n void loadPage({ mode: 'browse', page: 1, category: activeCategory });\n return;\n }\n\n void loadPage({ mode: 'search', page: 1, query: trimmed, category: activeCategory });\n }, SEARCH_DEBOUNCE_MS);\n\n return () => clearTimeout(timer);\n }, [activeCategory, loadPage, searchQuery]);\n\n const handleInstall = useCallback(\n async (owner: string, repo: string, skill: string) => {\n setInstallStatusWithTimer(skill, 'installing');\n try {\n const res = await apiFetch('/api/skills/install', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n owner,\n repo,\n skill,\n description: results?.skills.find((item) => item.slug === skill)?.description ?? '',\n version: results?.skills.find((item) => item.slug === skill)?.version ?? '',\n }),\n });\n if (res.ok) {\n clearInstallStatus(skill);\n markSkillInstalled(skill);\n notifySkillOptionsChanged();\n addToast({\n type: 'success',\n title: INSTALL_SUCCESS_TITLE,\n message: `\"${skill}\" 安装成功,可在我的技能中查看`,\n duration: 4000,\n });\n } else {\n const payload = (await res.json().catch(() => ({}))) as { error?: string };\n const detail = payload.error ?? `HTTP ${res.status}`;\n clearInstallStatus(skill);\n addToast({\n type: 'error',\n title: INSTALL_FAILURE_TITLE,\n message: detail,\n duration: 4000,\n });\n }\n } catch {\n clearInstallStatus(skill);\n addToast({\n type: 'error',\n title: INSTALL_FAILURE_TITLE,\n message: '网络错误,请重试',\n duration: 4000,\n });\n }\n },\n [addToast, clearInstallStatus, markSkillInstalled, results, setInstallStatusWithTimer],\n );\n\n if (!results && loading) {\n return <CenteredLoadingState />;\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col overflow-hidden\">\n <section className=\"flex min-h-0 flex-1 flex-col\">\n <div className=\"shrink-0\" data-testid=\"hub-skills-fixed-header\">\n {categories.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-4 pb-6\">\n {[ALL_CATEGORY, ...categories].map((category, index) => (\n <div key={category} className=\"flex items-center\">\n {index > 0 ? <div aria-hidden=\"true\" className=\"mr-4 h-4 w-px self-center bg-[#dbdbdb]\" /> : null}\n <button\n type=\"button\"\n onClick={() => handleCategoryChange(category)}\n className={`inline-flex min-h-7 items-center leading-none text-sm transition-colors ${\n activeCategory === category\n ? 'font-semibold text-[var(--text-primary)]'\n : 'text-[var(--text-muted)] hover:text-[var(--text-primary)]'\n }`}\n >\n {category}\n </button>\n </div>\n ))}\n </div>\n )}\n\n <div className=\"space-y-0\">\n <p className=\"text-[20px] font-semibold\">\n {displayCategory}\n {results ? ` (${results.total})` : ''}\n </p>\n <div className=\"flex flex-col gap-[var(--space-5)] py-6 sm:flex-row sm:items-center\">\n <SearchInput\n wrapperClassName=\"flex-1\"\n aria-label={SEARCH_ARIA_LABEL}\n value={searchQuery}\n onChange={(value) => setSearchQuery(value)}\n onClear={() => setSearchQuery('')}\n placeholder={SEARCH_ARIA_LABEL}\n clearAriaLabel=\"清除搜索\"\n />\n </div>\n </div>\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto\" data-testid=\"hub-skills-scroll-region\">\n {results ? (\n <>\n {results.skills.length === 0 ? (\n <div\n className=\"flex h-full min-h-0 items-center justify-center py-16\"\n data-testid=\"hub-skills-empty-state-shell\"\n >\n {viewMode === 'search' ? <NoSearchResultsState onClear={handleClearFilters} /> : <EmptyDataState />}\n </div>\n ) : (\n <SkillList results={results} installStatus={installStatus} onInstall={handleInstall} />\n )}\n {results.skills.length > 0 && results.hasMore && (\n <div ref={loadMoreTriggerRef} className=\"flex justify-center py-4\">\n {loadingMore && <span className=\"text-sm text-[var(--text-muted)]\">加载中...</span>}\n </div>\n )}\n </>\n ) : null}\n </div>\n </section>\n </div>\n );\n}\n"],"names":["skillSourceToLabel","source","getSourceLabel","CapabilityCard","item","_agentFamilies","toggling","onToggle","onUninstall","onUpdateSkill","updatingSkillId","skillUpdates","onClick","_hideSkillMountStatus","sourceLabel","resolvedDescription","_a","resolvedAgentegory","_b","showDeleteAction","showUpdateAction","isUpdating","isClickable","jsxs","event","jsx","SkillAvatar","OverflowTooltip","StatusDot","status","color","label","ALL_CATEGORY","UNCATEGORIZED","SKILL_SEARCH_PLACEHOLDER","SKILL_SEARCH_ARIA_LABEL","CATEGORY_FILTER_ARIA_LABEL","IMPORT_LABEL","CATEGORY_TAB_PRIORITY","ALL_SKILL_SOURCES","SKILL_SCOPE_TABS","sortCategoryTabs","categories","left","right","leftIndex","rightIndex","CapabilityTab","hideSkillMountStatus","onImport","onSelectSkill","refreshSignal","items","setItems","useState","agentFamilies","setAgentFamilies","error","setError","loading","setLoading","activeSkillSource","setActiveSkillSource","activeCategory","setActiveCategory","searchQuery","setSearchQuery","isCategoryMenuOpen","setIsCategoryMenuOpen","setToggling","categoryMenuRef","useRef","confirm","useConfirm","addToast","useToastStore","state","fetchCapabilities","useCallback","query","res","apiFetch","data","useEffect","onVisible","handleToggle","capabilityId","capabilityType","enabled","scope","agentId","toggleKey","body","handleUninstall","skillId","notifySkillOptionsChanged","detail","visibleItems","useMemo","skillItems","sourceScopedSkillItems","categoryCounts","counts","category","categoryOptions","options","ordered","categoryFilteredItems","normalizedSearchQuery","filteredDisplayedSkillItems","onPointerDown","target","handleSkillSourceChange","handleCategoryChange","handleClearFilters","activeSkillSourceLabel","tab","CenteredLoadingState","index","Button","prev","isSelected","SearchInput","value","EmptyDataState","NoSearchResultsState","GENERAL_CATEGORY","INSTALLING_LABEL","INSTALL_LABEL","FALLBACK_DESCRIPTION","INSTALLED_LABEL","SEARCH_ARIA_LABEL","PAGE_SIZE","SEARCH_DEBOUNCE_MS","INSTALL_SUCCESS_TITLE","INSTALL_FAILURE_TITLE","CATEGORY_MAP","normalizeCategory","cat","resolveCategoryParam","zh","getSkillCategory","skill","primaryTag","tag","InstallButton","slug","owner","repo","onInstall","styles","SkillList","results","installStatus","NameInitialIcon","SkillsTab","s","setResults","loadingMore","setLoadingMore","currentPage","setCurrentPage","viewMode","setViewMode","setInstallStatus","statusTimers","displayCategory","setDisplayCategory","setCategories","latestQueryRef","requestSeqRef","activeAbortRef","searchEffectReadyRef","loadMoreTriggerRef","loadCategories","buildSkillsUrl","mode","page","params","categoryParam","mergeResults","next","append","loadPage","requestId","controller","setLoadingFn","handleLoadMore","setInstallStatusWithTimer","existing","timer","clearInstallStatus","markSkillInstalled","markInstalled","result","changed","skills","timers","el","observer","entries","trimmed","handleInstall","Fragment"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{j as e}from"./index-Cb4fQgom.js";function x({items:a,value:t,onChange:n,className:s,activeBorderColor:l,activeTextColor:i}){const c=(r,o)=>{r.stopPropagation(),o!==t&&n(o)},p={display:"flex",gap:"var(--space-7)",borderBottom:"1px solid var(--border-default)"};return e.jsx("div",{role:"tablist",style:p,className:s,children:a.map(r=>{const o=r.value===t;return e.jsx("button",{role:"tab",type:"button","aria-selected":o,onClick:d=>c(d,r.value),style:{padding:"8px 0",fontSize:"14px",fontWeight:o?500:400,color:o?i??"var(--tab-active-color)":"var(--text-secondary)",background:"transparent",border:"none",borderBottom:o?`2px solid ${l??"var(--tab-active-color)"}`:"2px solid transparent",cursor:"pointer",transition:"color 150ms ease, border-color 150ms ease",marginBottom:"-1px"},children:r.label},r.value)})})}export{x as T};
2
+ //# sourceMappingURL=Tab-FE0F2EQP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tab-FE0F2EQP.js","sources":["../../src/components/shared/Tab.tsx"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport type { CSSProperties, MouseEvent } from 'react';\n\ninterface TabItem {\n value: string;\n label: string;\n}\n\ninterface TabProps {\n items: TabItem[];\n value: string;\n onChange: (value: string) => void;\n className?: string;\n /** 激活 Tab 底部边框颜色,默认 var(--accent-primary) */\n activeBorderColor?: string;\n /** 激活 Tab 文字颜色,默认 var(--text-accent) */\n activeTextColor?: string;\n}\n\nfunction joinClasses(...values: Array<string | false | null | undefined>) {\n return values.filter(Boolean).join(' ');\n}\n\nexport function Tab({ items, value, onChange, className, activeBorderColor, activeTextColor }: TabProps) {\n const handleTabClick = (event: MouseEvent<HTMLButtonElement>, tabValue: string) => {\n event.stopPropagation();\n if (tabValue !== value) {\n onChange(tabValue);\n }\n };\n\n const containerStyle: CSSProperties = {\n display: 'flex',\n gap: 'var(--space-7)',\n borderBottom: '1px solid var(--border-default)',\n };\n\n return (\n <div\n role=\"tablist\"\n style={containerStyle}\n className={className}\n >\n {items.map((item) => {\n const isActive = item.value === value;\n return (\n <button\n key={item.value}\n role=\"tab\"\n type=\"button\"\n aria-selected={isActive}\n onClick={(e) => handleTabClick(e, item.value)}\n style={{\n padding: '8px 0',\n fontSize: '14px',\n fontWeight: isActive ? 500 : 400,\n color: isActive ? (activeTextColor ?? 'var(--tab-active-color)') : 'var(--text-secondary)',\n background: 'transparent',\n border: 'none',\n borderBottom: isActive ? `2px solid ${activeBorderColor ?? 'var(--tab-active-color)'}` : '2px solid transparent',\n cursor: 'pointer',\n transition: 'color 150ms ease, border-color 150ms ease',\n marginBottom: '-1px',\n }}\n >\n {item.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"names":["Tab","items","value","onChange","className","activeBorderColor","activeTextColor","handleTabClick","event","tabValue","containerStyle","jsx","item","isActive","e"],"mappings":"wCA8BO,SAASA,EAAI,CAAE,MAAAC,EAAO,MAAAC,EAAO,SAAAC,EAAU,UAAAC,EAAW,kBAAAC,EAAmB,gBAAAC,GAA6B,CACvG,MAAMC,EAAiB,CAACC,EAAsCC,IAAqB,CACjFD,EAAM,gBAAA,EACFC,IAAaP,GACfC,EAASM,CAAQ,CAErB,EAEMC,EAAgC,CACpC,QAAS,OACT,IAAK,iBACL,aAAc,iCAAA,EAGhB,OACEC,EAAAA,IAAC,MAAA,CACC,KAAK,UACL,MAAOD,EACP,UAAAN,EAEC,SAAAH,EAAM,IAAKW,GAAS,CACnB,MAAMC,EAAWD,EAAK,QAAUV,EAChC,OACES,EAAAA,IAAC,SAAA,CAEC,KAAK,MACL,KAAK,SACL,gBAAeE,EACf,QAAUC,GAAMP,EAAeO,EAAGF,EAAK,KAAK,EAC5C,MAAO,CACL,QAAS,QACT,SAAU,OACV,WAAYC,EAAW,IAAM,IAC7B,MAAOA,EAAYP,GAAmB,0BAA6B,wBACnE,WAAY,cACZ,OAAQ,OACR,aAAcO,EAAW,aAAaR,GAAqB,yBAAyB,GAAK,wBACzF,OAAQ,UACR,WAAY,4CACZ,aAAc,MAAA,EAGf,SAAAO,EAAK,KAAA,EAlBDA,EAAK,KAAA,CAqBhB,CAAC,CAAA,CAAA,CAGP"}