@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 @@
1
+ {"version":3,"file":"quick-actions-DzZE-zyP.js","sources":["../../src/config/quick-actions.ts"],"sourcesContent":["\n/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport interface ExpertCardConfig {\n agentId: string;\n agentName: string;\n content: string;\n mentionTargetIds?: string[];\n}\n\nexport interface QuickActionConfig {\n label: string;\n icon: string;\n show: boolean;\n prompts: Array<string>;\n /** 专家团思辨专用:包含智能体信息和内容 */\n expertCards?: ExpertCardConfig[];\n}\n\nexport const QUICK_ACTIONS: QuickActionConfig[] = [\n {\n label: '定时任务',\n icon: '/icons/schedule.svg',\n show: true,\n prompts: [\n '每日 10:00 提醒我喝水,从今天开始并持续生效,任务创建后设置为立即执行。',\n '设置每天为我推送当天最新的10条科技新闻,每条新闻总结要精简。',\n '设置每天生成一个3-5分钟的睡前故事,并在每日10:00推送给我。',\n ],\n },\n {\n label: '专家团思辨',\n icon: '/icons/expert-debate.svg',\n show: true,\n prompts: [],\n expertCards: [\n {\n agentId: 'office',\n agentName: '通用助手',\n content:\n '@通用助手@逻辑大师@人文顾问,你们三个站在自己的立场讨论一下普通人在AI时代如何与AI共处,然后基于各自的观点进行深入讨论。',\n mentionTargetIds: ['office', 'assistant', 'agentteams'],\n },\n {\n agentId: 'assistant',\n agentName: '逻辑大师',\n content: '你拉着你的其他小伙伴,讨论一下传统企业数字化转型战略的规划与落地路径,整合自身核心资源形成差异化竞争力',\n },\n {\n agentId: 'agentteams',\n agentName: '人文顾问',\n content: '你拉着你的其他小伙伴,讨论一下企业该如何构建自己的AI技术壁垒,形成长期可持续的竞争力',\n },\n ],\n },\n {\n label: '文档处理',\n icon: '/icons/document-processing.svg',\n show: true,\n prompts: [\n '请以部门负责人视角,写一篇逻辑扎实、内容饱满的季度工作总结,既要体现关键成果与数据支撑,也要客观说明现存问题,并给出务实可行的下一阶段工作计划,文风正式不浮夸,可直接用于正式汇报。',\n '基于一场典型的产品迭代项目推进会,帮我自动生成一篇完整规范的会议纪要,结构清晰、要素齐全,把讨论焦点、达成共识、遗留问题、责任人与时间节点全部写清楚,格式符合企业正式文件要求。',\n '请生成一份完整的企业数字化升级解决方案,内容要包含项目背景、核心目标、实施步骤、资源配置、预算框架、风险应对和预期价值,行文专业严谨,结构完整,不用我补充任何信息即可直接使用。',\n ],\n },\n {\n label: '深度研究',\n icon: '/icons/deep-research.svg',\n show: true,\n prompts: [\n '以智能家电赛道为例,输出一份完整的竞品全景分析报告,包括产品定位、功能差异、价格体系、用户口碑、优势短板和未来布局方向,最后给出差异化竞争的可行思路。',\n '请生成一份针对都市年轻职场人群的用户需求洞察报告,完整刻画用户画像、行为习惯、真实痛点、潜在需求和消费决策逻辑,结论清晰,可直接指导产品设计。',\n '围绕银发经济赛道做一份完整市场机会分析,包括市场规模、人群结构、未被满足需求、细分切入点、竞争壁垒和长期潜力,内容扎实,可直接用于决策参考。',\n ],\n },\n {\n label: '幻灯片',\n icon: '/icons/slides.svg',\n show: true,\n prompts: [\n 'OpenAI ChatGPT 5.4深度技术原理分析PPT。',\n '给我做一个详细讲解下NotebookLM的原理的PPT。',\n '生成一页华为风格的ppt,内容是关于:黄仁勋2026 GTC大会上讲话的核心观点总结,要求包含图表、数据、smart化的内容。',\n ],\n },\n {\n label: '数据分析',\n icon: '/icons/data-analysis.svg',\n show: true,\n prompts: [\n '基于电商 APP 用户原始行为数据集分析:日均访客 82000 人,页面平均停留 72 秒,首页点击率 35.6%,详情页跳转率 61%,商品加购率 12.8%,下单转化率 4.35%,7 日留存 28.5%,30 日留存 16.2%。请完整分析用户路径、时段分布、行为偏好、流失节点,输出数据结论、原因剖析以及对应的产品体验优化策略。',\n '基于抖音直播间原始漏斗全量数据:总曝光 1260000、进入直播间 412000、点击小黄车 83000、商品加购 21500、最终下单 9800、用户复购 3100。逐层计算每一环转化率与流失率,定位最高流失环节,分析流失诱因,输出分环节流量承接、转化提升的量化运营方案。',\n '已知连锁餐饮 4 月总营收环比下滑 13.5%,拆解原始维度数据:门店维度社区店下滑 8%、商圈店下滑 19%;产品维度主食类下滑 9%、小食饮品类下滑 22%;渠道维度到店消费下滑 10%、外卖渠道下滑 17%。逐层钻取量化各维度影响权重,定位核心下滑原因,给出针对性整改与资源调配方案。',\n ],\n },\n {\n label: '数据可视化',\n icon: '/icons/data-visualization.svg',\n show: true,\n prompts: [\n '请设计一套逻辑清晰、美观实用的业务数据监控看板,明确核心指标、图表类型、页面布局、配色风格和筛选交互方式,结构完整可直接交给设计落地。',\n '请设计一套用户行为分析专用可视化图表,包括漏斗图、热力图、留存曲线、地域分布,直观呈现用户规律,专业清晰。',\n '请设计一套规范专业的财务数据可视化图表,包含趋势变化、结构占比、同比对比等类型,符合正式财务汇报的严谨性要求。',\n ],\n },\n {\n label: '金融服务',\n icon: '/icons/financial-services.svg',\n show: true,\n prompts: [\n '请以普通中产家庭为对象,生成一份完整可执行的理财规划方案,包含现金管理、保障配置、权益与固收配比、风险控制和长期执行步骤,实用易懂。',\n '请生成一份公募基金投资分析报告,讲清楚基金选择逻辑、配置思路、定投方法和风险控制要点,语言通俗,普通投资者能看懂能用。',\n '请以科技赛道龙头为例,生成一份完整个股价值分析报告,包括业务、财务、行业地位、估值、核心逻辑与风险,客观中立具备参考性。',\n ],\n },\n {\n label: '视频生成',\n icon: '/icons/video-generation.svg',\n show: false,\n prompts: [\n '基于这份新品发布会的PPT脚本,生成一段30秒的宣传视频。',\n '帮我制作一段员工培训视频,内容是关于新上线的办公系统操作教程,要求画面清晰、步骤讲解详细,添加字幕和操作指引标注,视频时长控制在8分钟以内。',\n '以公司年度大事记为内容,生成一段3分钟的回顾视频,采用温暖怀旧的风格,搭配舒缓的音乐,插入真实的公司活动照片和员工采访片段。',\n ],\n },\n {\n label: '内容核查',\n icon: '/icons/query_the_optical_power_border.svg',\n show: false,\n prompts: [],\n },\n];\n"],"names":["QUICK_ACTIONS"],"mappings":"AAuBO,MAAMA,EAAqC,CAChD,CACE,MAAO,OACP,KAAM,sBACN,KAAM,GACN,QAAS,CACP,0CACA,kCACA,mCAAA,CACF,EAEF,CACE,MAAO,QACP,KAAM,2BACN,KAAM,GACN,QAAS,CAAA,EACT,YAAa,CACX,CACE,QAAS,SACT,UAAW,OACX,QACE,kEACF,iBAAkB,CAAC,SAAU,YAAa,YAAY,CAAA,EAExD,CACE,QAAS,YACT,UAAW,OACX,QAAS,qDAAA,EAEX,CACE,QAAS,aACT,UAAW,OACX,QAAS,6CAAA,CACX,CACF,EAEF,CACE,MAAO,OACP,KAAM,iCACN,KAAM,GACN,QAAS,CACP,6FACA,2FACA,0FAAA,CACF,EAEF,CACE,MAAO,OACP,KAAM,2BACN,KAAM,GACN,QAAS,CACP,8EACA,0EACA,wEAAA,CACF,EAEF,CACE,MAAO,MACP,KAAM,oBACN,KAAM,GACN,QAAS,CACP,iCACA,+BACA,iEAAA,CACF,EAEF,CACE,MAAO,OACP,KAAM,2BACN,KAAM,GACN,QAAS,CACP,2KACA,4IACA,mJAAA,CACF,EAEF,CACE,MAAO,QACP,KAAM,gCACN,KAAM,GACN,QAAS,CACP,sEACA,wDACA,yDAAA,CACF,EAEF,CACE,MAAO,OACP,KAAM,gCACN,KAAM,GACN,QAAS,CACP,qEACA,8DACA,8DAAA,CACF,EAEF,CACE,MAAO,OACP,KAAM,8BACN,KAAM,GACN,QAAS,CACP,gCACA,yEACA,gEAAA,CACF,EAEF,CACE,MAAO,OACP,KAAM,4CACN,KAAM,GACN,QAAS,CAAA,CAAC,CAEd"}
@@ -0,0 +1,2 @@
1
+ import{a as u}from"./OverflowTooltip-CE5PjAb-.js";const d="office-claw:skill-options-updated";let a=null,i=null,o=0;function f(){return a||null}function h(e){a=Array.from(new Map(e.map(n=>{var r;return{name:n.name.trim(),iconUrl:n.iconUrl??null,description:((r=n.description)==null?void 0:r.trim())??""}}).filter(n=>n.name.length>0).map(n=>[n.name,n])).values())}function k(){a=null,o+=1,i=null}function O(){k(),!(typeof window>"u")&&window.dispatchEvent(new CustomEvent(d))}async function w(e){const l=(e==null?void 0:e.force)===!0,n=f();if(!l&&n)return n;if(!l&&i)return i;const r=o,s=(async()=>{try{const c=await u("/api/capabilities?probe=true");if(!c.ok)return[];const p=((await c.json()).items??[]).filter(t=>t.type==="skill"&&typeof t.id=="string"&&t.id.trim().length>0).map(t=>({name:t.id.trim(),description:typeof t.description=="string"?t.description.trim():""}));return o===r&&h(p),p}catch{return[]}finally{i===s&&(i=null)}})();return l||(i=s),s}export{d as S,w as f,f as g,O as n,h as s};
2
+ //# sourceMappingURL=skill-options-cache-D1BJGTCU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-options-cache-D1BJGTCU.js","sources":["../../src/utils/skill-options-cache.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { apiFetch } from './api-client';\n\nexport interface SkillOption {\n name: string;\n iconUrl?: string | null;\n description?: string;\n}\n\ninterface CapabilitySkillItem {\n id: string;\n type: 'mcp' | 'skill' | 'limb';\n description?: string;\n}\n\ninterface CapabilitiesResponseLite {\n items?: CapabilitySkillItem[];\n}\n\nexport const SKILL_OPTIONS_UPDATED_EVENT = 'office-claw:skill-options-updated';\n\nlet cachedSkillOptions: SkillOption[] | null = null;\nlet skillOptionsInFlight: Promise<SkillOption[]> | null = null;\nlet skillOptionsEpoch = 0;\n\nexport function getCachedSkillOptions(): SkillOption[] | null {\n if (!cachedSkillOptions) return null;\n return cachedSkillOptions;\n}\n\nexport function seedSkillOptionsCache(options: SkillOption[]): void {\n const deduped = Array.from(\n new Map(\n options\n .map((item) => ({\n name: item.name.trim(),\n iconUrl: item.iconUrl ?? null,\n description: item.description?.trim() ?? '',\n }))\n .filter((item) => item.name.length > 0)\n .map((item) => [item.name, item] as const),\n ).values(),\n );\n cachedSkillOptions = deduped;\n}\n\nexport function invalidateSkillOptionsCache(): void {\n cachedSkillOptions = null;\n skillOptionsEpoch += 1;\n skillOptionsInFlight = null;\n}\n\nexport function notifySkillOptionsChanged(): void {\n invalidateSkillOptionsCache();\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(SKILL_OPTIONS_UPDATED_EVENT));\n}\n\nexport async function fetchSkillOptionsWithCache(options?: { force?: boolean }): Promise<SkillOption[]> {\n const force = options?.force === true;\n const cached = getCachedSkillOptions();\n if (!force && cached) return cached;\n if (!force && skillOptionsInFlight) return skillOptionsInFlight;\n\n const requestEpoch = skillOptionsEpoch;\n\n const request = (async () => {\n try {\n const res = await apiFetch('/api/capabilities?probe=true');\n if (!res.ok) return [];\n const data = (await res.json()) as CapabilitiesResponseLite;\n const options = (data.items ?? [])\n .filter((item) => item.type === 'skill' && typeof item.id === 'string' && item.id.trim().length > 0)\n .map((item) => ({\n name: item.id.trim(),\n description: typeof item.description === 'string' ? item.description.trim() : '',\n }));\n if (skillOptionsEpoch === requestEpoch) {\n seedSkillOptionsCache(options);\n }\n return options;\n } catch {\n return [];\n } finally {\n if (skillOptionsInFlight === request) {\n skillOptionsInFlight = null;\n }\n }\n })();\n\n if (!force) {\n skillOptionsInFlight = request;\n }\n\n return request;\n}\n"],"names":["SKILL_OPTIONS_UPDATED_EVENT","cachedSkillOptions","skillOptionsInFlight","skillOptionsEpoch","getCachedSkillOptions","seedSkillOptionsCache","options","item","_a","invalidateSkillOptionsCache","notifySkillOptionsChanged","fetchSkillOptionsWithCache","force","cached","requestEpoch","request","res","apiFetch"],"mappings":"kDAwBO,MAAMA,EAA8B,oCAE3C,IAAIC,EAA2C,KAC3CC,EAAsD,KACtDC,EAAoB,EAEjB,SAASC,GAA8C,CAC5D,OAAKH,GAA2B,IAElC,CAEO,SAASI,EAAsBC,EAA8B,CAalEL,EAZgB,MAAM,KACpB,IAAI,IACFK,EACG,IAAKC,GAAA,OAAU,OACd,KAAMA,EAAK,KAAK,KAAA,EAChB,QAASA,EAAK,SAAW,KACzB,cAAaC,EAAAD,EAAK,cAAL,YAAAC,EAAkB,SAAU,EAAA,EACzC,EACD,OAAQD,GAASA,EAAK,KAAK,OAAS,CAAC,EACrC,IAAKA,GAAS,CAACA,EAAK,KAAMA,CAAI,CAAU,CAAA,EAC3C,OAAA,CAAO,CAGb,CAEO,SAASE,GAAoC,CAClDR,EAAqB,KACrBE,GAAqB,EACrBD,EAAuB,IACzB,CAEO,SAASQ,GAAkC,CAChDD,EAAA,EACI,SAAO,OAAW,MACtB,OAAO,cAAc,IAAI,YAAYT,CAA2B,CAAC,CACnE,CAEA,eAAsBW,EAA2BL,EAAuD,CACtG,MAAMM,GAAQN,GAAA,YAAAA,EAAS,SAAU,GAC3BO,EAAST,EAAA,EACf,GAAI,CAACQ,GAASC,EAAQ,OAAOA,EAC7B,GAAI,CAACD,GAASV,EAAsB,OAAOA,EAE3C,MAAMY,EAAeX,EAEfY,GAAW,SAAY,CAC3B,GAAI,CACF,MAAMC,EAAM,MAAMC,EAAS,8BAA8B,EACzD,GAAI,CAACD,EAAI,GAAI,MAAO,CAAA,EAEpB,MAAMV,IADQ,MAAMU,EAAI,KAAA,GACF,OAAS,CAAA,GAC5B,OAAQT,GAASA,EAAK,OAAS,SAAW,OAAOA,EAAK,IAAO,UAAYA,EAAK,GAAG,KAAA,EAAO,OAAS,CAAC,EAClG,IAAKA,IAAU,CACd,KAAMA,EAAK,GAAG,KAAA,EACd,YAAa,OAAOA,EAAK,aAAgB,SAAWA,EAAK,YAAY,OAAS,EAAA,EAC9E,EACJ,OAAIJ,IAAsBW,GACxBT,EAAsBC,CAAO,EAExBA,CACT,MAAQ,CACN,MAAO,CAAA,CACT,QAAA,CACMJ,IAAyBa,IAC3Bb,EAAuB,KAE3B,CACF,GAAA,EAEA,OAAKU,IACHV,EAAuBa,GAGlBA,CACT"}
@@ -0,0 +1,2 @@
1
+ import{O as le,r as d,j as e,u as X}from"./index-Cb4fQgom.js";import{u as ie}from"./useEscapeKey-CEQ6-8GR.js";import{A as de}from"./AppModal-BYZTSuch.js";import{T as ce}from"./Tab-FE0F2EQP.js";import{C as K}from"./CenteredLoadingState-DHor-9vF.js";import{E as ue}from"./EmptyDataState-6mNx2Xhl.js";import{N as se}from"./NoSearchResultsState-BiiYdZ_Z.js";import{a as $,O as U}from"./OverflowTooltip-CE5PjAb-.js";import{S as re}from"./SearchInput-tux8xXH1.js";function Be(t,a,s="#FFFFFF"){const r=u=>[Number.parseInt(u.slice(1,3),16),Number.parseInt(u.slice(3,5),16),Number.parseInt(u.slice(5,7),16)],[n,i,l]=r(t),[p,f,x]=r(s);return`rgb(${Math.round(p+(n-p)*a)}, ${Math.round(f+(i-f)*a)}, ${Math.round(x+(l-x)*a)})`}function _e(t,a){const s=t.replace("#","");let r,n,i;return s.length===3?(r=parseInt(s[0]+s[0],16),n=parseInt(s[1]+s[1],16),i=parseInt(s[2]+s[2],16)):(r=parseInt(s.slice(0,2),16),n=parseInt(s.slice(2,4),16),i=parseInt(s.slice(4,6),16)),`rgba(${r},${n},${i},${a})`}function Fe(){const{theme:t,setTheme:a,toggleTheme:s,isLoaded:r,initializeTheme:n}=le();return d.useEffect(()=>{r||n()},[r,n]),{theme:t,setTheme:a,toggleTheme:s,isLoaded:r}}function G({checked:t,onToggle:a,ariaLabel:s,disabled:r=!1,testId:n}){return e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":s,"aria-disabled":r,disabled:r,"data-testid":n,onClick:()=>a(!t),className:["relative inline-flex h-[20px] w-[40px] shrink-0 items-center rounded-full transition-colors duration-200 disabled:cursor-not-allowed disabled:opacity-60",t?"bg-[var(--switch-on-bg)]":"bg-[var(--switch-off-bg)]"].join(" "),children:e.jsx("span",{className:["inline-block h-[16px] w-[16px] rounded-full bg-[var(--modal-switch-thumb)] shadow-sm transition-transform duration-200",t?"translate-x-[22px]":"translate-x-[2px]"].join(" ")})})}const V=5,W=50;function pe(t){return t?typeof t=="string"?t:t["*"]??"allow":"allow"}function me(t){const a=(t==null?void 0:t.tools)??{};return Object.entries(a).map(([s,r])=>({id:s,action:s,approvalRequired:pe(r)==="ask"}))}function fe(t){return(t==null?void 0:t.enabled)??!0}function he(t,a){return!t||typeof t=="string"?a:{...t,"*":a}}function ne(t,a){if(a<=8)return Array.from({length:a},(i,l)=>l+1);const s=new Set([1,2,a-1,a,t-2,t-1,t,t+1,t+2]),r=Array.from(s).filter(i=>i>=1&&i<=a).sort((i,l)=>i-l),n=[];for(let i=0;i<r.length;i+=1){const l=r[i],p=r[i-1];p!=null&&l-p>1&&n.push("ellipsis"),n.push(l)}return n}const xe=300;function ge(t,a){const s=new URLSearchParams({limit:String(W),offset:String(a),includeRuleMatched:"false"});return t&&s.set("threadQuery",t),`/api/authorization/records?${s.toString()}`}async function ae(t,a){const s=await $(ge(t,a)),r=await s.json();if(!s.ok)throw new Error(r.error||"加载审批记录失败");return r}function ve(t){if(typeof t!="number"||!Number.isFinite(t))return"--";const a=new Date(t);return Number.isNaN(a.getTime())?"--":a.toLocaleString("zh-CN",{hour12:!1})}function be(t,a){const s=X(N=>N.addToast),r=d.useRef(0),[n,i]=d.useState({}),[l,p]=d.useState(""),[f,x]=d.useState(""),[u,E]=d.useState(null),[j,y]=d.useState(1),[v,b]=d.useState(0),[w,C]=d.useState(!1),[L,o]=d.useState(!1),[A,I]=d.useState(!1),[_,P]=d.useState(!1);d.useEffect(()=>{const N=window.setTimeout(()=>{x(l.trim())},xe);return()=>{window.clearTimeout(N)}},[l]),d.useEffect(()=>{t||(r.current+=1,i({}),p(""),x(""),E(null),y(1),b(0),C(!1),o(!1),I(!1),P(!1))},[t]),d.useEffect(()=>{a||(r.current+=1,o(!1),I(!1),P(!1))},[a]),d.useEffect(()=>{if(!t||!a||u===f)return;const N=++r.current,M=u===null&&f.length===0;o(M),I(!M),P(!1);async function h(){try{const m=await ae(f,0);if(r.current!==N)return;const S=m.records??[];i({0:S}),E(f),y(1),b(m.totalCount??S.length),f.length===0&&S.length>0&&C(!0)}catch(m){if(r.current!==N)return;s({type:"error",title:"审批记录加载失败",message:m instanceof Error?m.message:"加载审批记录失败",duration:3e3})}finally{r.current===N&&(o(!1),I(!1))}}h()},[a,s,f,u,t]);const B=async N=>{if(!a||_||u==null||N===j||N<1)return;const M=(N-1)*V,h=Math.floor(M/W)*W;if(n[h]){y(N);return}const m=++r.current;P(!0);try{const S=await ae(u,h);if(r.current!==m)return;const te=S.records??[];y(N),i(oe=>({...oe,[h]:te})),b(S.totalCount??te.length)}catch(S){if(r.current!==m)return;s({type:"error",title:"审批记录加载失败",message:S instanceof Error?S.message:"加载审批记录失败",duration:3e3})}finally{r.current===m&&P(!1)}},F=d.useMemo(()=>l.trim(),[l]),q=(j-1)*V,Q=Math.floor(q/W)*W,Z=n[Q]??[],D=q-Q,O=Z.slice(D,D+V),z=w||F.length>0,H=z&&(A||F!==f),c=L&&u===null,T=!c&&u===""&&O.length===0,g=!H&&u!=null&&u.length>0&&O.length===0,R=Math.max(1,Math.ceil(v/V)),k=R>1,ee=k?ne(j,R):[];return{records:O,searchQuery:l,page:j,totalPages:R,paginationItems:ee,showPagination:k,loadingPage:_,showSearchInput:z,showSearchLoading:H,showInitialLoading:c,showEmptyState:T,showNoSearchResults:g,setSearchQuery:p,handlePageChange:B}}function ye({records:t,autoCleanupEnabled:a,loadingAutoCleanupSetting:s,autoCleanupSettingLoadFailed:r,savingAutoCleanupSetting:n,searchQuery:i,page:l,totalPages:p,paginationItems:f,showPagination:x,loadingPage:u,showSearchInput:E,showSearchLoading:j,showInitialLoading:y,showEmptyState:v,showNoSearchResults:b,onToggleAutoCleanup:w,onSearchChange:C,onPageChange:L}){return e.jsxs("div",{className:"space-y-4","data-testid":"approval-records-tab",children:[e.jsxs("section",{children:[e.jsxs("div",{className:"flex items-center justify-between gap-4","data-testid":"approval-records-auto-cleanup-header",children:[e.jsx("h4",{className:"text-[12px] text-[var(--text-primary)]",children:"自动清理安全审批记录"}),e.jsx(G,{checked:a,onToggle:w,ariaLabel:"自动清理安全审批记录",disabled:s||r||n,testId:"approval-records-auto-cleanup-toggle"})]}),e.jsx("p",{className:"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]","data-testid":"approval-records-auto-cleanup-description",children:"开启后,将仅保存近30天的审批数据;关闭则保存历史全部的审批记录"})]}),e.jsxs("section",{className:"space-y-3",children:[e.jsx("h4",{className:"text-[12px] text-[var(--text-primary)]","data-testid":"approval-records-title",children:"审批记录"}),y?e.jsx("div",{className:"flex min-h-[220px] flex-1 items-center justify-center","data-testid":"approval-records-loading",children:e.jsx(K,{})}):null,!y&&v&&!E?e.jsx("div",{className:"flex min-h-[220px] flex-1 items-center justify-center","data-testid":"approval-records-empty-state",children:e.jsx(ue,{title:"暂无审批记录"})}):null,!y&&E?e.jsx(re,{value:i,onChange:o=>C(o),onClear:()=>C(""),placeholder:"请输入会话名称搜索","data-testid":"approval-records-search-input"}):null,!y&&j?e.jsx("div",{className:"flex min-h-[180px] items-center justify-center","data-testid":"approval-records-search-loading",children:e.jsx(K,{})}):null,!y&&!j&&b?e.jsx("div",{className:"flex min-h-[180px] items-center justify-center","data-testid":"approval-records-no-results",children:e.jsx(se,{onClear:()=>C("")})}):null,!y&&!j&&!b&&t.length>0?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"overflow-hidden rounded-[12px] border border-[var(--modal-muted-border)]","data-testid":"approval-records-table",children:[e.jsxs("div",{className:"grid grid-cols-[1.8fr_1fr_0.8fr_0.9fr] border-b border-[var(--modal-muted-border)] bg-[var(--modal-table-header-bg)] px-5 py-4 text-[12px] font-medium text-[var(--modal-text-muted)]",children:[e.jsx("div",{children:"会话名称"}),e.jsx("div",{children:"敏感操作"}),e.jsx("div",{children:"审批结果"}),e.jsx("div",{children:"时间"})]}),e.jsx("div",{className:"bg-[var(--modal-surface)]",children:t.map(o=>(()=>{const A=o.threadTitle||o.threadId||"--",I=ve(o.decidedAt);return e.jsxs("div",{className:"grid grid-cols-[1.8fr_1fr_0.8fr_0.9fr] items-center border-b border-[var(--modal-table-divider)] px-5 py-4 text-[12px] text-[var(--modal-title-text)] last:border-b-0","data-testid":`approval-record-row-${o.id}`,children:[e.jsx("div",{className:"min-w-0 pr-4","data-testid":`approval-record-cell-${o.id}-thread`,children:e.jsx(U,{content:A,className:"min-w-0",children:e.jsx("span",{className:"block truncate text-[var(--modal-text)]",children:A})})}),e.jsx("div",{className:"min-w-0 pr-4","data-testid":`approval-record-cell-${o.id}-action`,children:e.jsx(U,{content:o.action,className:"min-w-0",children:e.jsx("span",{className:"block truncate text-[var(--modal-text)]",children:o.action})})}),e.jsx("div",{className:"min-w-0 pr-4","data-testid":`approval-record-cell-${o.id}-result`,children:e.jsx(U,{content:o.approvalLabel,className:"min-w-0",children:e.jsx("span",{className:"block truncate",children:o.approvalLabel})})}),e.jsx("div",{className:"min-w-0","data-testid":`approval-record-cell-${o.id}-time`,children:e.jsx(U,{content:I,className:"min-w-0",children:e.jsx("span",{className:"block truncate tabular-nums",children:I})})})]},o.id)})())})]}),x?e.jsxs("div",{className:"flex items-center justify-end gap-1 pt-1","data-testid":"approval-records-pagination",children:[e.jsx("button",{type:"button",className:"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40",onClick:()=>L(Math.max(1,l-1)),disabled:u||l<=1,"aria-label":"上一页","data-testid":"approval-records-pagination-prev",children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M11.5 5L6.5 10L11.5 15",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"})})}),f.map((o,A)=>o==="ellipsis"?e.jsx("span",{className:"px-2 text-[14px] text-[var(--modal-text-subtle)]",children:"..."},`ellipsis-${A}`):e.jsx("button",{type:"button",className:`flex h-8 min-w-8 items-center justify-center rounded-full px-2 text-[12px] ${o===l?"bg-[var(--modal-muted-surface)] text-[var(--modal-text)]":"text-[var(--modal-text-muted)] hover:bg-[var(--modal-muted-surface)]"}`,onClick:()=>L(o),disabled:u,"data-testid":`approval-records-pagination-page-${o}`,children:o},o)),e.jsx("button",{type:"button",className:"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40",onClick:()=>L(Math.min(p,l+1)),disabled:u||l>=p,"aria-label":"下一页","data-testid":"approval-records-pagination-next",children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M8.5 5L13.5 10L8.5 15",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"})})})]}):null]}):null]})]})}function we({loading:t,loadFailed:a,approvalBarEnabled:s,workspaceRwEnabled:r,savingApprovalBar:n,savingWorkspaceRw:i,savingPolicyIds:l,hasPolicies:p,paginatedPolicies:f,page:x,totalPages:u,paginationItems:E,showPagination:j,searchQuery:y,onPageChange:v,onSearchChange:b,onToggleApprovalBar:w,onToggleWorkspaceRw:C,onTogglePolicy:L}){return t?e.jsx("div",{className:"flex min-h-[220px] flex-1 items-center justify-center","data-testid":"security-management-loading",children:e.jsx(K,{})}):a?e.jsx("div",{className:"flex flex-col justify-center","data-testid":"security-management-load-failed",children:e.jsx("p",{className:"text-[14px] text-[var(--text-secondary)]",children:"加载安全权限配置失败"})}):e.jsxs("div",{className:"space-y-4",children:[e.jsxs("section",{children:[e.jsxs("div",{className:"flex items-center justify-between gap-4","data-testid":"security-management-approval-header",children:[e.jsx("h4",{className:"text-[14px] font-semibold text-[var(--text-primary)]",children:"是否开启审批护栏"}),e.jsx(G,{checked:s,onToggle:w,ariaLabel:"是否开启审批护栏",disabled:n,testId:"security-management-approval-bar-toggle"})]}),e.jsx("p",{className:"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]","data-testid":"security-management-approval-description",children:"开启后,若对话中触发相关权限时按安全策略展示确认卡片;若关闭,则所有敏感操作无需用户执行风险审批。"})]}),s&&p?e.jsx("section",{"data-testid":"security-management-workspace-rw-section",children:e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("h4",{className:"text-[12px] text-[var(--text-primary)]",children:"信任工作空间内文件读写"}),e.jsx(G,{checked:r,onToggle:C,ariaLabel:"是否信任会话空间内读写",disabled:i,testId:"security-management-workspace-rw-toggle"})]}),e.jsx("p",{className:"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]","data-testid":"security-management-workspace-rw-description",children:"开启后,将允许工作空间内可以自由读写所有本地文件,不对工作空间下发生的敏感操作进行拦截审批。"})]})}):null,s?e.jsxs("section",{className:"space-y-2","data-testid":"security-management-policy-section",children:[e.jsx("h4",{className:"text-[12px] text-[var(--text-primary)]",children:"安全策略配置"}),e.jsx(re,{value:y,onChange:o=>b(o),onClear:()=>b(""),placeholder:"搜索敏感操作",wrapperClassName:"mb-3","data-testid":"security-policy-search-input"}),e.jsxs("div",{className:"overflow-hidden rounded-[12px] border border-[var(--modal-muted-border)]",children:[e.jsxs("div",{className:"grid grid-cols-[1.6fr_1.4fr] border-b border-[var(--modal-muted-border)] bg-[var(--modal-table-header-bg)] px-5 py-4 text-[12px] font-medium text-[var(--modal-text-muted)]",children:[e.jsx("div",{children:"敏感操作"}),e.jsx("div",{children:"在对话中是否需要审批"})]}),e.jsx("div",{className:"bg-[var(--modal-surface)]",children:f.length===0?e.jsx("div",{className:"flex items-center justify-center px-5 py-8",children:e.jsx(se,{onClear:()=>b(""),title:"暂未匹配到数据",description:"没有匹配到符合条件的敏感操作",clearLabel:"清空筛选器"})}):f.map(o=>e.jsxs("div",{"data-testid":`security-policy-row-${o.id}`,className:"grid grid-cols-[1.6fr_1.4fr] items-center border-b border-[var(--modal-table-divider)] px-5 py-5 text-[12px] text-[var(--modal-title-text)] last:border-b-0",children:[e.jsx("div",{className:"font-normal leading-5 text-[var(--modal-text)]",children:o.action}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(G,{checked:o.approvalRequired,onToggle:()=>L(o.id),ariaLabel:`${o.action} 执行前审批开关`,disabled:!!l[o.id],testId:`security-policy-toggle-${o.id}`}),e.jsx("span",{className:"text-[12px] text-[var(--modal-title-text)]",children:o.approvalRequired?"是":"否"})]})]},o.id))})]}),j?e.jsxs("div",{className:"flex items-center justify-end gap-1","data-testid":"security-management-pagination",children:[e.jsx("button",{type:"button",className:"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40",onClick:()=>v(Math.max(1,x-1)),disabled:x<=1,"aria-label":"上一页","data-testid":"security-management-pagination-prev",children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M11.5 5L6.5 10L11.5 15",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"})})}),E.map((o,A)=>o==="ellipsis"?e.jsx("span",{className:"px-2 text-[14px] text-[var(--modal-text-subtle)]",children:"..."},`ellipsis-${A}`):e.jsx("button",{type:"button",className:`flex h-8 min-w-8 items-center justify-center rounded-full px-2 text-[12px] ${o===x?"bg-[var(--modal-muted-surface)] text-[var(--modal-text)]":"text-[var(--modal-text-muted)] hover:bg-[var(--modal-muted-surface)]"}`,onClick:()=>v(o),"data-testid":`security-management-pagination-page-${o}`,children:o},o)),e.jsx("button",{type:"button",className:"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40",onClick:()=>v(Math.min(u,x+1)),disabled:x>=u,"aria-label":"下一页","data-testid":"security-management-pagination-next",children:e.jsx("svg",{className:"h-4 w-4",viewBox:"0 0 20 20",fill:"none","aria-hidden":"true",children:e.jsx("path",{d:"M8.5 5L13.5 10L8.5 15",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round"})})})]}):null]}):null]})}async function je(){const t=await $("/api/authorization/records/settings"),a=await t.json();if(!t.ok)throw new Error(a.error||"加载审批记录设置失败");return a}async function Se(t){const a=await $("/api/authorization/records/settings",{method:"PUT",headers:{"content-type":"application/json"},body:JSON.stringify({autoCleanupEnabled:t})}),s=await a.json();if(!a.ok)throw new Error(s.error||"保存审批记录设置失败");return s}function Ne(t,a){const s=X(v=>v.addToast),[r,n]=d.useState(!1),[i,l]=d.useState(!1),[p,f]=d.useState(!1),[x,u]=d.useState(!1),[E,j]=d.useState(!1);return d.useEffect(()=>{if(!t){n(!1),l(!1),f(!1),u(!1),j(!1);return}if(!a||E)return;let v=!1;async function b(){l(!0),f(!1);try{const w=await je();if(typeof w.autoCleanupEnabled!="boolean")throw new Error(w.error||"加载审批记录设置失败");if(v)return;n(w.autoCleanupEnabled),j(!0)}catch(w){if(v)return;n(!1),f(!0),s({type:"error",title:"审批记录设置加载失败",message:w instanceof Error?w.message:"加载审批记录设置失败",duration:3e3})}finally{v||l(!1)}}return b(),()=>{v=!0}},[a,s,E,t]),{autoCleanupEnabled:r,loading:i,loadFailed:p,saving:x,handleToggleAutoCleanup:async()=>{if(i||p||x)return;const v=r,b=!v;n(b),u(!0);try{await Se(b),s({type:"success",title:"审批记录设置成功",message:"",duration:2e3})}catch(w){n(v),s({type:"error",title:"审批记录设置失败",message:w instanceof Error?w.message:"保存审批记录设置失败",duration:3e3})}finally{u(!1)}}}}const J=5;function Ee(t){const a=X(c=>c.addToast),[s,r]=d.useState(null),[n,i]=d.useState(!1),[l,p]=d.useState(!1),[f,x]=d.useState([]),[u,E]=d.useState(1),[j,y]=d.useState(""),[v,b]=d.useState(!1),[w,C]=d.useState(!1),[L,o]=d.useState(!1),[A,I]=d.useState(!1),[_,P]=d.useState({});d.useEffect(()=>{if(!t){r(null),i(!1),p(!1),x([]),E(1),y(""),b(!1),C(!1),o(!1),I(!1),P({});return}let c=!1;async function T(){b(!0),C(!1);try{const g=await $("/api/config/relayclaw/security"),R=await g.json(),k=R.permissions;if(!g.ok||!k)throw new Error(R.error||"加载安全权限配置失败");if(c)return;r(k),i(fe(k)),p(k.rw_enabled===!0),x(me(k)),E(1),y("")}catch(g){if(c)return;r(null),i(!1),p(!1),x([]),C(!0),a({type:"error",title:"安全管理加载失败",message:g instanceof Error?g.message:"加载安全权限配置失败",duration:3e3})}finally{c||b(!1)}}return T(),()=>{c=!0}},[t,a]);const B=d.useMemo(()=>f.filter(c=>c.action.toLowerCase().includes(j.toLowerCase())),[f,j]),F=Math.max(1,Math.ceil(B.length/J)),q=d.useMemo(()=>B.slice((u-1)*J,u*J),[B,u]),Q=B.length>J,Z=Q?ne(u,F):[],D=v||t&&s===null&&!w,O=c=>{y(c),E(1)},z=async()=>{if(L)return;const c=n,T=!c;i(T),o(!0);try{const g=await $("/api/config/relayclaw/security",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({permissions:{enabled:T}})}),R=await g.json();if(!g.ok)throw new Error(R.error||"保存审批护栏设置失败");r(k=>({...k??{},enabled:T})),a({type:"success",title:"审批护栏设置成功",message:"",duration:2e3})}catch(g){i(c),a({type:"error",title:"审批护栏设置失败",message:g instanceof Error?g.message:"保存审批护栏设置失败",duration:3e3})}finally{o(!1)}},Y=async()=>{if(A)return;const c=l,T=!c;p(T),I(!0);try{const g=await $("/api/config/relayclaw/security",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({permissions:{rw_enabled:T}})}),R=await g.json();if(!g.ok)throw new Error(R.error||"保存工作空间读写设置失败");r(k=>({...k??{},rw_enabled:T})),a({type:"success",title:"工作空间读写设置成功",message:"",duration:2e3})}catch(g){p(c),a({type:"error",title:"工作空间读写设置失败",message:g instanceof Error?g.message:"保存工作空间读写设置失败",duration:3e3})}finally{I(!1)}},H=async c=>{var M;if(_[c])return;const T=f.find(h=>h.id===c),g=(T==null?void 0:T.approvalRequired)??!1,R=(M=s==null?void 0:s.tools)==null?void 0:M[c],k=!g,N=he(R,k?"ask":"allow");x(h=>h.map(m=>m.id===c?{...m,approvalRequired:k}:m)),r(h=>({...h??{},tools:{...(h==null?void 0:h.tools)??{},[c]:N}})),P(h=>({...h,[c]:!0}));try{const h=await $("/api/config/relayclaw/security",{method:"PATCH",headers:{"content-type":"application/json"},body:JSON.stringify({permissions:{tools:{[c]:N}}})}),m=await h.json();if(!h.ok)throw new Error(m.error||"保存安全策略失败");a({type:"success",title:"安全策略设置成功",message:"",duration:2e3})}catch(h){x(m=>m.map(S=>S.id===c?{...S,approvalRequired:g}:S)),r(m=>{const S={...(m==null?void 0:m.tools)??{}};return R===void 0?delete S[c]:S[c]=R,{...m??{},tools:S}}),a({type:"error",title:"安全策略设置失败",message:h instanceof Error?h.message:"保存安全策略失败",duration:3e3})}finally{P(h=>{const m={...h};return delete m[c],m})}};return{loading:D,loadFailed:w,approvalBarEnabled:n,workspaceRwEnabled:l,savingApprovalBar:L,savingWorkspaceRw:A,savingPolicyIds:_,hasPolicies:f.length>0,paginatedPolicies:q,page:u,totalPages:F,paginationItems:Z,showPagination:Q,searchQuery:j,setPage:E,handleSearchChange:O,handleToggleApprovalBar:z,handleToggleWorkspaceRw:Y,handleTogglePolicy:H}}const Te=[{value:"approval",label:"安全审批"},{value:"records",label:"审批记录"}];function Qe({open:t,onClose:a}){const[s,r]=d.useState("approval"),n=Ee(t),i=Ne(t,s==="records"),l=be(t,s==="records");return d.useEffect(()=>{t||r("approval")},[t]),ie({enabled:t,onEscape:a}),e.jsxs(de,{open:t,onClose:a,disableBackdropClose:!0,title:"安全管理",closeButtonAriaLabel:"关闭安全管理弹窗",backdropTestId:"security-management-modal-backdrop",panelTestId:"security-management-modal",bodyTestId:"security-management-modal-body",panelClassName:"min-h-[480px] w-[700px] max-h-[calc(100vh-32px)] max-w-[calc(100vw-32px)] overflow-hidden",headerClassName:"p-0 pb-4",bodyClassName:"flex min-h-0 flex-1 flex-col overflow-hidden",children:[e.jsx("div",{className:"mb-4","data-testid":"security-management-tabs",children:e.jsx(ce,{items:Te,value:s,onChange:p=>r(p)})}),e.jsx("div",{className:"min-h-0 flex-1 overflow-y-auto pr-1","data-testid":"security-management-scroll-region",children:s==="approval"?e.jsx(we,{loading:n.loading,loadFailed:n.loadFailed,approvalBarEnabled:n.approvalBarEnabled,workspaceRwEnabled:n.workspaceRwEnabled,savingApprovalBar:n.savingApprovalBar,savingWorkspaceRw:n.savingWorkspaceRw,savingPolicyIds:n.savingPolicyIds,hasPolicies:n.hasPolicies,paginatedPolicies:n.paginatedPolicies,page:n.page,totalPages:n.totalPages,paginationItems:n.paginationItems,showPagination:n.showPagination,searchQuery:n.searchQuery,onPageChange:n.setPage,onSearchChange:n.handleSearchChange,onToggleApprovalBar:()=>void n.handleToggleApprovalBar(),onToggleWorkspaceRw:()=>void n.handleToggleWorkspaceRw(),onTogglePolicy:p=>void n.handleTogglePolicy(p)}):e.jsx(ye,{records:l.records,autoCleanupEnabled:i.autoCleanupEnabled,loadingAutoCleanupSetting:i.loading,autoCleanupSettingLoadFailed:i.loadFailed,savingAutoCleanupSetting:i.saving,searchQuery:l.searchQuery,page:l.page,totalPages:l.totalPages,paginationItems:l.paginationItems,showPagination:l.showPagination,loadingPage:l.loadingPage,showSearchInput:l.showSearchInput,showSearchLoading:l.showSearchLoading,showInitialLoading:l.showInitialLoading,showEmptyState:l.showEmptyState,showNoSearchResults:l.showNoSearchResults,onToggleAutoCleanup:()=>void i.handleToggleAutoCleanup(),onSearchChange:l.setSearchQuery,onPageChange:p=>void l.handlePageChange(p)})})]})}function Oe(t){return t<1e3?`${t}ms`:`${(t/1e3).toFixed(1)}s`}function We(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}k`:String(t)}function qe(t){return`$${t.toFixed(t<.01?4:2)}`}export{Qe as S,G as T,qe as a,Oe as b,We as f,_e as h,Be as t,Fe as u};
2
+ //# sourceMappingURL=status-helpers-BILdm2MI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status-helpers-BILdm2MI.js","sources":["../../src/lib/color-utils.ts","../../src/hooks/useTheme.ts","../../src/components/shared/ToggleSwitch.tsx","../../src/components/security-management/constants.ts","../../src/components/security-management/utils.ts","../../src/components/security-management/useApprovalRecords.ts","../../src/components/security-management/ApprovalRecordsTab.tsx","../../src/components/security-management/SecurityApprovalSettingsTab.tsx","../../src/components/security-management/useApprovalRecordSettings.ts","../../src/components/security-management/useSecurityApprovalSettings.ts","../../src/components/SecurityManagementModal.tsx","../../src/components/status-helpers.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * Color utilities for dynamic cat theme rendering.\n * Converts hex colors from API to rgba for glow/shadow effects.\n */\n\n/** Blend a hex color toward white by ratio (0→white, 1→accent). Symmetric to tintedDark. */\nexport function tintedLight(hex: string, ratio: number, base = '#FFFFFF'): string {\n const parse = (h: string) => [\n Number.parseInt(h.slice(1, 3), 16),\n Number.parseInt(h.slice(3, 5), 16),\n Number.parseInt(h.slice(5, 7), 16),\n ];\n const [r1, g1, b1] = parse(hex);\n const [r2, g2, b2] = parse(base);\n return `rgb(${Math.round(r2 + (r1 - r2) * ratio)}, ${Math.round(g2 + (g1 - g2) * ratio)}, ${Math.round(b2 + (b1 - b2) * ratio)})`;\n}\n\n/** Convert hex color (3/6/8 digit) to rgba string */\nexport function hexToRgba(hex: string, alpha: number): string {\n const cleaned = hex.replace('#', '');\n let r: number, g: number, b: number;\n if (cleaned.length === 3) {\n r = parseInt(cleaned[0] + cleaned[0], 16);\n g = parseInt(cleaned[1] + cleaned[1], 16);\n b = parseInt(cleaned[2] + cleaned[2], 16);\n } else {\n r = parseInt(cleaned.slice(0, 2), 16);\n g = parseInt(cleaned.slice(2, 4), 16);\n b = parseInt(cleaned.slice(4, 6), 16);\n }\n return `rgba(${r},${g},${b},${alpha})`;\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { useEffect } from 'react';\nimport { useThemeStore, type ThemeType } from '@/stores/themeStore';\n\nexport type { ThemeType };\n\nexport function useTheme() {\n const { theme, setTheme, toggleTheme, isLoaded, initializeTheme } = useThemeStore();\n\n useEffect(() => {\n if (!isLoaded) {\n initializeTheme();\n }\n }, [isLoaded, initializeTheme]);\n\n return {\n theme,\n setTheme,\n toggleTheme,\n isLoaded,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n\"use client\";\n\ninterface ToggleSwitchProps {\n checked: boolean;\n onToggle: (checked: boolean) => void;\n ariaLabel: string;\n disabled?: boolean;\n testId?: string;\n}\n\nexport function ToggleSwitch({\n checked,\n onToggle,\n ariaLabel,\n disabled = false,\n testId,\n}: ToggleSwitchProps) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={ariaLabel}\n aria-disabled={disabled}\n disabled={disabled}\n data-testid={testId}\n onClick={() => onToggle(!checked)}\n className={[\n \"relative inline-flex h-[20px] w-[40px] shrink-0 items-center rounded-full transition-colors duration-200 disabled:cursor-not-allowed disabled:opacity-60\",\n checked\n ? \"bg-[var(--switch-on-bg)]\"\n : \"bg-[var(--switch-off-bg)]\",\n ].join(\" \")}\n >\n <span\n className={[\n \"inline-block h-[16px] w-[16px] rounded-full bg-[var(--modal-switch-thumb)] shadow-sm transition-transform duration-200\",\n checked ? \"translate-x-[22px]\" : \"translate-x-[2px]\",\n ].join(\" \")}\n />\n </button>\n );\n}\n","export const APPROVAL_RECORDS_PAGE_SIZE = 5;\nexport const APPROVAL_RECORDS_REQUEST_LIMIT = 50;\n","import type {\n PermissionDecision,\n PermissionsConfig,\n SecurityPolicyItem,\n ToolPermissionRule,\n} from './types';\n\nexport function getToolDecision(\n value: PermissionDecision | ToolPermissionRule | undefined,\n): PermissionDecision {\n if (!value) return 'allow';\n if (typeof value === 'string') return value;\n return value['*'] ?? 'allow';\n}\n\nexport function normalizePolicies(config?: PermissionsConfig): SecurityPolicyItem[] {\n const tools = config?.tools ?? {};\n return Object.entries(tools).map(([toolName, value]) => ({\n id: toolName,\n action: toolName,\n approvalRequired: getToolDecision(value) === 'ask',\n }));\n}\n\nexport function isPermissionsEnabled(config?: PermissionsConfig): boolean {\n return config?.enabled ?? true;\n}\n\nexport function updateToolValue(\n current: PermissionDecision | ToolPermissionRule | undefined,\n nextDecision: PermissionDecision,\n): PermissionDecision | ToolPermissionRule {\n if (!current || typeof current === 'string') {\n return nextDecision;\n }\n\n return {\n ...current,\n '*': nextDecision,\n };\n}\n\nexport function formatPaginationPages(currentPage: number, totalPages: number): Array<number | 'ellipsis'> {\n if (totalPages <= 8) {\n return Array.from({ length: totalPages }, (_, index) => index + 1);\n }\n\n const pages = new Set<number>([\n 1,\n 2,\n totalPages - 1,\n totalPages,\n currentPage - 2,\n currentPage - 1,\n currentPage,\n currentPage + 1,\n currentPage + 2,\n ]);\n const sortedPages = Array.from(pages)\n .filter((page) => page >= 1 && page <= totalPages)\n .sort((a, b) => a - b);\n const result: Array<number | 'ellipsis'> = [];\n\n for (let index = 0; index < sortedPages.length; index += 1) {\n const page = sortedPages[index];\n const previous = sortedPages[index - 1];\n if (previous != null && page - previous > 1) {\n result.push('ellipsis');\n }\n result.push(page);\n }\n\n return result;\n}\n","'use client';\n\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport { APPROVAL_RECORDS_PAGE_SIZE, APPROVAL_RECORDS_REQUEST_LIMIT } from './constants';\nimport type { ApprovalRecord, ApprovalRecordsResponse } from './types';\nimport { formatPaginationPages } from './utils';\n\nconst SEARCH_DEBOUNCE_MS = 300;\n\nfunction buildRecordsUrl(query: string, offset: number): string {\n const params = new URLSearchParams({\n limit: String(APPROVAL_RECORDS_REQUEST_LIMIT),\n offset: String(offset),\n includeRuleMatched: 'false',\n });\n if (query) params.set('threadQuery', query);\n return `/api/authorization/records?${params.toString()}`;\n}\n\nasync function fetchApprovalRecords(query: string, offset: number): Promise<ApprovalRecordsResponse> {\n const response = await apiFetch(buildRecordsUrl(query, offset));\n const payload = (await response.json()) as ApprovalRecordsResponse;\n if (!response.ok) {\n throw new Error(payload.error || '加载审批记录失败');\n }\n return payload;\n}\n\nexport function formatApprovalRecordTime(value: number | null | undefined): string {\n if (typeof value !== 'number' || !Number.isFinite(value)) return '--';\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return '--';\n return date.toLocaleString('zh-CN', { hour12: false });\n}\n\nexport function useApprovalRecords(open: boolean, active: boolean) {\n const addToast = useToastStore((state) => state.addToast);\n const requestIdRef = useRef(0);\n const [recordBatches, setRecordBatches] = useState<Record<number, ApprovalRecord[]>>({});\n const [searchQuery, setSearchQuery] = useState('');\n const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('');\n const [loadedQuery, setLoadedQuery] = useState<string | null>(null);\n const [page, setPage] = useState(1);\n const [totalCount, setTotalCount] = useState(0);\n const [hasAvailableRecords, setHasAvailableRecords] = useState(false);\n const [loadingInitial, setLoadingInitial] = useState(false);\n const [loadingSearch, setLoadingSearch] = useState(false);\n const [loadingPage, setLoadingPage] = useState(false);\n\n useEffect(() => {\n const timeoutId = window.setTimeout(() => {\n setDebouncedSearchQuery(searchQuery.trim());\n }, SEARCH_DEBOUNCE_MS);\n\n return () => {\n window.clearTimeout(timeoutId);\n };\n }, [searchQuery]);\n\n useEffect(() => {\n if (open) return;\n\n requestIdRef.current += 1;\n setRecordBatches({});\n setSearchQuery('');\n setDebouncedSearchQuery('');\n setLoadedQuery(null);\n setPage(1);\n setTotalCount(0);\n setHasAvailableRecords(false);\n setLoadingInitial(false);\n setLoadingSearch(false);\n setLoadingPage(false);\n }, [open]);\n\n useEffect(() => {\n if (active) return;\n\n requestIdRef.current += 1;\n setLoadingInitial(false);\n setLoadingSearch(false);\n setLoadingPage(false);\n }, [active]);\n\n useEffect(() => {\n if (!open || !active || loadedQuery === debouncedSearchQuery) return;\n\n const currentRequestId = ++requestIdRef.current;\n const isInitialLoad = loadedQuery === null && debouncedSearchQuery.length === 0;\n setLoadingInitial(isInitialLoad);\n setLoadingSearch(!isInitialLoad);\n setLoadingPage(false);\n\n async function loadRecords() {\n try {\n const payload = await fetchApprovalRecords(debouncedSearchQuery, 0);\n if (requestIdRef.current !== currentRequestId) return;\n\n const nextRecords = payload.records ?? [];\n setRecordBatches({ 0: nextRecords });\n setLoadedQuery(debouncedSearchQuery);\n setPage(1);\n setTotalCount(payload.totalCount ?? nextRecords.length);\n if (debouncedSearchQuery.length === 0 && nextRecords.length > 0) {\n setHasAvailableRecords(true);\n }\n } catch (error) {\n if (requestIdRef.current !== currentRequestId) return;\n addToast({\n type: 'error',\n title: '审批记录加载失败',\n message: error instanceof Error ? error.message : '加载审批记录失败',\n duration: 3000,\n });\n } finally {\n if (requestIdRef.current === currentRequestId) {\n setLoadingInitial(false);\n setLoadingSearch(false);\n }\n }\n }\n\n void loadRecords();\n }, [active, addToast, debouncedSearchQuery, loadedQuery, open]);\n\n const handlePageChange = async (targetPage: number) => {\n if (!active || loadingPage || loadedQuery == null || targetPage === page || targetPage < 1) return;\n\n const targetStartIndex = (targetPage - 1) * APPROVAL_RECORDS_PAGE_SIZE;\n const targetBatchOffset =\n Math.floor(targetStartIndex / APPROVAL_RECORDS_REQUEST_LIMIT) * APPROVAL_RECORDS_REQUEST_LIMIT;\n if (recordBatches[targetBatchOffset]) {\n setPage(targetPage);\n return;\n }\n\n const currentRequestId = ++requestIdRef.current;\n setLoadingPage(true);\n\n try {\n const payload = await fetchApprovalRecords(loadedQuery, targetBatchOffset);\n if (requestIdRef.current !== currentRequestId) return;\n\n const nextRecords = payload.records ?? [];\n setPage(targetPage);\n setRecordBatches((currentBatches) => ({\n ...currentBatches,\n [targetBatchOffset]: nextRecords,\n }));\n setTotalCount(payload.totalCount ?? nextRecords.length);\n } catch (error) {\n if (requestIdRef.current !== currentRequestId) return;\n addToast({\n type: 'error',\n title: '审批记录加载失败',\n message: error instanceof Error ? error.message : '加载审批记录失败',\n duration: 3000,\n });\n } finally {\n if (requestIdRef.current === currentRequestId) {\n setLoadingPage(false);\n }\n }\n };\n\n const normalizedSearchQuery = useMemo(() => searchQuery.trim(), [searchQuery]);\n const currentPageStartIndex = (page - 1) * APPROVAL_RECORDS_PAGE_SIZE;\n const currentBatchOffset =\n Math.floor(currentPageStartIndex / APPROVAL_RECORDS_REQUEST_LIMIT) * APPROVAL_RECORDS_REQUEST_LIMIT;\n const currentBatch = recordBatches[currentBatchOffset] ?? [];\n const currentBatchStartIndex = currentPageStartIndex - currentBatchOffset;\n const records = currentBatch.slice(currentBatchStartIndex, currentBatchStartIndex + APPROVAL_RECORDS_PAGE_SIZE);\n const showSearchInput = hasAvailableRecords || normalizedSearchQuery.length > 0;\n const searchPending = normalizedSearchQuery !== debouncedSearchQuery;\n const showSearchLoading = showSearchInput && (loadingSearch || searchPending);\n const showInitialLoading = loadingInitial && loadedQuery === null;\n const showEmptyState = !showInitialLoading && loadedQuery === '' && records.length === 0;\n const showNoSearchResults =\n !showSearchLoading && loadedQuery != null && loadedQuery.length > 0 && records.length === 0;\n const totalPages = Math.max(1, Math.ceil(totalCount / APPROVAL_RECORDS_PAGE_SIZE));\n const showPagination = totalPages > 1;\n const paginationItems = showPagination ? formatPaginationPages(page, totalPages) : [];\n\n return {\n records,\n searchQuery,\n page,\n totalPages,\n paginationItems,\n showPagination,\n loadingPage,\n showSearchInput,\n showSearchLoading,\n showInitialLoading,\n showEmptyState,\n showNoSearchResults,\n setSearchQuery,\n handlePageChange,\n };\n}\n","'use client';\n\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 { ToggleSwitch } from '../shared/ToggleSwitch';\nimport type { ApprovalRecord } from './types';\nimport { formatApprovalRecordTime } from './useApprovalRecords';\n\ninterface ApprovalRecordsTabProps {\n records: ApprovalRecord[];\n autoCleanupEnabled: boolean;\n loadingAutoCleanupSetting: boolean;\n autoCleanupSettingLoadFailed: boolean;\n savingAutoCleanupSetting: boolean;\n searchQuery: string;\n page: number;\n totalPages: number;\n paginationItems: Array<number | 'ellipsis'>;\n showPagination: boolean;\n loadingPage: boolean;\n showSearchInput: boolean;\n showSearchLoading: boolean;\n showInitialLoading: boolean;\n showEmptyState: boolean;\n showNoSearchResults: boolean;\n onToggleAutoCleanup: () => void;\n onSearchChange: (value: string) => void;\n onPageChange: (page: number) => void;\n}\n\nexport function ApprovalRecordsTab({\n records,\n autoCleanupEnabled,\n loadingAutoCleanupSetting,\n autoCleanupSettingLoadFailed,\n savingAutoCleanupSetting,\n searchQuery,\n page,\n totalPages,\n paginationItems,\n showPagination,\n loadingPage,\n showSearchInput,\n showSearchLoading,\n showInitialLoading,\n showEmptyState,\n showNoSearchResults,\n onToggleAutoCleanup,\n onSearchChange,\n onPageChange,\n}: ApprovalRecordsTabProps) {\n return (\n <div className=\"space-y-4\" data-testid=\"approval-records-tab\">\n <section>\n <div className=\"flex items-center justify-between gap-4\" data-testid=\"approval-records-auto-cleanup-header\">\n <h4 className=\"text-[12px] text-[var(--text-primary)]\">自动清理安全审批记录</h4>\n <ToggleSwitch\n checked={autoCleanupEnabled}\n onToggle={onToggleAutoCleanup}\n ariaLabel=\"自动清理安全审批记录\"\n disabled={loadingAutoCleanupSetting || autoCleanupSettingLoadFailed || savingAutoCleanupSetting}\n testId=\"approval-records-auto-cleanup-toggle\"\n />\n </div>\n <p\n className=\"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]\"\n data-testid=\"approval-records-auto-cleanup-description\"\n >\n 开启后,将仅保存近30天的审批数据;关闭则保存历史全部的审批记录\n </p>\n </section>\n\n <section className=\"space-y-3\">\n <h4 className=\"text-[12px] text-[var(--text-primary)]\" data-testid=\"approval-records-title\">\n 审批记录\n </h4>\n\n {showInitialLoading ? (\n <div\n className=\"flex min-h-[220px] flex-1 items-center justify-center\"\n data-testid=\"approval-records-loading\"\n >\n <CenteredLoadingState />\n </div>\n ) : null}\n\n {!showInitialLoading && showEmptyState && !showSearchInput ? (\n <div\n className=\"flex min-h-[220px] flex-1 items-center justify-center\"\n data-testid=\"approval-records-empty-state\"\n >\n <EmptyDataState title=\"暂无审批记录\"/>\n </div>\n ) : null}\n\n {!showInitialLoading && showSearchInput ? (\n <SearchInput\n value={searchQuery}\n onChange={(value) => onSearchChange(value)}\n onClear={() => onSearchChange('')}\n placeholder=\"请输入会话名称搜索\"\n data-testid=\"approval-records-search-input\"\n />\n ) : null}\n\n {!showInitialLoading && showSearchLoading ? (\n <div\n className=\"flex min-h-[180px] items-center justify-center\"\n data-testid=\"approval-records-search-loading\"\n >\n <CenteredLoadingState />\n </div>\n ) : null}\n\n {!showInitialLoading && !showSearchLoading && showNoSearchResults ? (\n <div className=\"flex min-h-[180px] items-center justify-center\" data-testid=\"approval-records-no-results\">\n <NoSearchResultsState onClear={() => onSearchChange('')} />\n </div>\n ) : null}\n\n {!showInitialLoading && !showSearchLoading && !showNoSearchResults && records.length > 0 ? (\n <>\n <div\n className=\"overflow-hidden rounded-[12px] border border-[var(--modal-muted-border)]\"\n data-testid=\"approval-records-table\"\n >\n <div className=\"grid grid-cols-[1.8fr_1fr_0.8fr_0.9fr] border-b border-[var(--modal-muted-border)] bg-[var(--modal-table-header-bg)] px-5 py-4 text-[12px] font-medium text-[var(--modal-text-muted)]\">\n <div>会话名称</div>\n <div>敏感操作</div>\n <div>审批结果</div>\n <div>时间</div>\n </div>\n <div className=\"bg-[var(--modal-surface)]\">\n {records.map((record) => (\n (() => {\n const threadLabel = record.threadTitle || record.threadId || '--';\n const timeLabel = formatApprovalRecordTime(record.decidedAt);\n\n return (\n <div\n key={record.id}\n className=\"grid grid-cols-[1.8fr_1fr_0.8fr_0.9fr] items-center border-b border-[var(--modal-table-divider)] px-5 py-4 text-[12px] text-[var(--modal-title-text)] last:border-b-0\"\n data-testid={`approval-record-row-${record.id}`}\n >\n <div className=\"min-w-0 pr-4\" data-testid={`approval-record-cell-${record.id}-thread`}>\n <OverflowTooltip content={threadLabel} className=\"min-w-0\">\n <span className=\"block truncate text-[var(--modal-text)]\">{threadLabel}</span>\n </OverflowTooltip>\n </div>\n <div className=\"min-w-0 pr-4\" data-testid={`approval-record-cell-${record.id}-action`}>\n <OverflowTooltip content={record.action} className=\"min-w-0\">\n <span className=\"block truncate text-[var(--modal-text)]\">{record.action}</span>\n </OverflowTooltip>\n </div>\n <div className=\"min-w-0 pr-4\" data-testid={`approval-record-cell-${record.id}-result`}>\n <OverflowTooltip content={record.approvalLabel} className=\"min-w-0\">\n <span className=\"block truncate\">{record.approvalLabel}</span>\n </OverflowTooltip>\n </div>\n <div className=\"min-w-0\" data-testid={`approval-record-cell-${record.id}-time`}>\n <OverflowTooltip content={timeLabel} className=\"min-w-0\">\n <span className=\"block truncate tabular-nums\">{timeLabel}</span>\n </OverflowTooltip>\n </div>\n </div>\n );\n })()\n ))}\n </div>\n </div>\n\n {showPagination ? (\n <div className=\"flex items-center justify-end gap-1 pt-1\" data-testid=\"approval-records-pagination\">\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={loadingPage || page <= 1}\n aria-label=\"上一页\"\n data-testid=\"approval-records-pagination-prev\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M11.5 5L6.5 10L11.5 15\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n </button>\n\n {paginationItems.map((item, index) =>\n item === 'ellipsis' ? (\n <span key={`ellipsis-${index}`} className=\"px-2 text-[14px] text-[var(--modal-text-subtle)]\">\n ...\n </span>\n ) : (\n <button\n key={item}\n type=\"button\"\n className={`flex h-8 min-w-8 items-center justify-center rounded-full px-2 text-[12px] ${\n item === page\n ? 'bg-[var(--modal-muted-surface)] text-[var(--modal-text)]'\n : 'text-[var(--modal-text-muted)] hover:bg-[var(--modal-muted-surface)]'\n }`}\n onClick={() => onPageChange(item)}\n disabled={loadingPage}\n data-testid={`approval-records-pagination-page-${item}`}\n >\n {item}\n </button>\n ),\n )}\n\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={loadingPage || page >= totalPages}\n aria-label=\"下一页\"\n data-testid=\"approval-records-pagination-next\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8.5 5L13.5 10L8.5 15\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n ) : null}\n </>\n ) : null}\n </section>\n </div>\n );\n}\n","'use client';\n\nimport { CenteredLoadingState } from '../shared/CenteredLoadingState';\nimport { NoSearchResultsState } from '../shared/NoSearchResultsState';\nimport { SearchInput } from '../shared/SearchInput';\nimport { ToggleSwitch } from '../shared/ToggleSwitch';\nimport type { SecurityPolicyItem } from './types';\n\ninterface SecurityApprovalSettingsTabProps {\n loading: boolean;\n loadFailed: boolean;\n approvalBarEnabled: boolean;\n workspaceRwEnabled: boolean;\n savingApprovalBar: boolean;\n savingWorkspaceRw: boolean;\n savingPolicyIds: Record<string, boolean>;\n hasPolicies: boolean;\n paginatedPolicies: SecurityPolicyItem[];\n page: number;\n totalPages: number;\n paginationItems: Array<number | 'ellipsis'>;\n showPagination: boolean;\n searchQuery: string;\n onPageChange: (page: number) => void;\n onSearchChange: (value: string) => void;\n onToggleApprovalBar: () => void;\n onToggleWorkspaceRw: () => void;\n onTogglePolicy: (id: string) => void;\n}\n\nexport function SecurityApprovalSettingsTab({\n loading,\n loadFailed,\n approvalBarEnabled,\n workspaceRwEnabled,\n savingApprovalBar,\n savingWorkspaceRw,\n savingPolicyIds,\n hasPolicies,\n paginatedPolicies,\n page,\n totalPages,\n paginationItems,\n showPagination,\n searchQuery,\n onPageChange,\n onSearchChange,\n onToggleApprovalBar,\n onToggleWorkspaceRw,\n onTogglePolicy,\n}: SecurityApprovalSettingsTabProps) {\n if (loading) {\n return (\n <div\n className=\"flex min-h-[220px] flex-1 items-center justify-center\"\n data-testid=\"security-management-loading\"\n >\n <CenteredLoadingState />\n </div>\n );\n }\n\n if (loadFailed) {\n return (\n <div className=\"flex flex-col justify-center\" data-testid=\"security-management-load-failed\">\n <p className=\"text-[14px] text-[var(--text-secondary)]\">加载安全权限配置失败</p>\n </div>\n );\n }\n\n return (\n <div className=\"space-y-4\">\n <section>\n <div className=\"flex items-center justify-between gap-4\" data-testid=\"security-management-approval-header\">\n <h4 className=\"text-[14px] font-semibold text-[var(--text-primary)]\">是否开启审批护栏</h4>\n <ToggleSwitch\n checked={approvalBarEnabled}\n onToggle={onToggleApprovalBar}\n ariaLabel=\"是否开启审批护栏\"\n disabled={savingApprovalBar}\n testId=\"security-management-approval-bar-toggle\"\n />\n </div>\n <p\n className=\"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]\"\n data-testid=\"security-management-approval-description\"\n >\n 开启后,若对话中触发相关权限时按安全策略展示确认卡片;若关闭,则所有敏感操作无需用户执行风险审批。\n </p>\n </section>\n\n {approvalBarEnabled && hasPolicies ? (\n <section data-testid=\"security-management-workspace-rw-section\">\n <div className=\"min-w-0\">\n <div className=\"flex items-center justify-between gap-4\">\n <h4 className=\"text-[12px] text-[var(--text-primary)]\">信任工作空间内文件读写</h4>\n <ToggleSwitch\n checked={workspaceRwEnabled}\n onToggle={onToggleWorkspaceRw}\n ariaLabel=\"是否信任会话空间内读写\"\n disabled={savingWorkspaceRw}\n testId=\"security-management-workspace-rw-toggle\"\n />\n </div>\n <p\n className=\"mt-1 block w-full text-[12px] text-[color:rgba(128,128,128,1)]\"\n data-testid=\"security-management-workspace-rw-description\"\n >\n 开启后,将允许工作空间内可以自由读写所有本地文件,不对工作空间下发生的敏感操作进行拦截审批。\n </p>\n </div>\n </section>\n ) : null}\n\n {approvalBarEnabled ? (\n <section className=\"space-y-2\" data-testid=\"security-management-policy-section\">\n <h4 className=\"text-[12px] text-[var(--text-primary)]\">安全策略配置</h4>\n\n <SearchInput\n value={searchQuery}\n onChange={(value) => onSearchChange(value)}\n onClear={() => onSearchChange('')}\n placeholder=\"搜索敏感操作\"\n wrapperClassName=\"mb-3\"\n data-testid=\"security-policy-search-input\"\n />\n\n <div className=\"overflow-hidden rounded-[12px] border border-[var(--modal-muted-border)]\">\n <div className=\"grid grid-cols-[1.6fr_1.4fr] border-b border-[var(--modal-muted-border)] bg-[var(--modal-table-header-bg)] px-5 py-4 text-[12px] font-medium text-[var(--modal-text-muted)]\">\n <div>敏感操作</div>\n <div>在对话中是否需要审批</div>\n </div>\n\n <div className=\"bg-[var(--modal-surface)]\">\n {paginatedPolicies.length === 0 ? (\n <div className=\"flex items-center justify-center px-5 py-8\">\n <NoSearchResultsState\n onClear={() => onSearchChange('')}\n title=\"暂未匹配到数据\"\n description=\"没有匹配到符合条件的敏感操作\"\n clearLabel=\"清空筛选器\"\n />\n </div>\n ) : (\n paginatedPolicies.map((policy) => (\n <div\n key={policy.id}\n data-testid={`security-policy-row-${policy.id}`}\n className=\"grid grid-cols-[1.6fr_1.4fr] items-center border-b border-[var(--modal-table-divider)] px-5 py-5 text-[12px] text-[var(--modal-title-text)] last:border-b-0\"\n >\n <div className=\"font-normal leading-5 text-[var(--modal-text)]\">{policy.action}</div>\n <div className=\"flex items-center gap-3\">\n <ToggleSwitch\n checked={policy.approvalRequired}\n onToggle={() => onTogglePolicy(policy.id)}\n ariaLabel={`${policy.action} 执行前审批开关`}\n disabled={Boolean(savingPolicyIds[policy.id])}\n testId={`security-policy-toggle-${policy.id}`}\n />\n <span className=\"text-[12px] text-[var(--modal-title-text)]\">\n {policy.approvalRequired ? '是' : '否'}\n </span>\n </div>\n </div>\n ))\n )}\n </div>\n </div>\n\n {showPagination ? (\n <div className=\"flex items-center justify-end gap-1\" data-testid=\"security-management-pagination\">\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={() => onPageChange(Math.max(1, page - 1))}\n disabled={page <= 1}\n aria-label=\"上一页\"\n data-testid=\"security-management-pagination-prev\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M11.5 5L6.5 10L11.5 15\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n </button>\n\n {paginationItems.map((item, index) =>\n item === 'ellipsis' ? (\n <span key={`ellipsis-${index}`} className=\"px-2 text-[14px] text-[var(--modal-text-subtle)]\">\n ...\n </span>\n ) : (\n <button\n key={item}\n type=\"button\"\n className={`flex h-8 min-w-8 items-center justify-center rounded-full px-2 text-[12px] ${\n item === page\n ? 'bg-[var(--modal-muted-surface)] text-[var(--modal-text)]'\n : 'text-[var(--modal-text-muted)] hover:bg-[var(--modal-muted-surface)]'\n }`}\n onClick={() => onPageChange(item)}\n data-testid={`security-management-pagination-page-${item}`}\n >\n {item}\n </button>\n ),\n )}\n\n <button\n type=\"button\"\n className=\"flex h-8 w-8 items-center justify-center rounded-full text-[var(--modal-text-subtle)] disabled:cursor-not-allowed disabled:opacity-40\"\n onClick={() => onPageChange(Math.min(totalPages, page + 1))}\n disabled={page >= totalPages}\n aria-label=\"下一页\"\n data-testid=\"security-management-pagination-next\"\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <path d=\"M8.5 5L13.5 10L8.5 15\" stroke=\"currentColor\" strokeWidth=\"1.6\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n ) : null}\n </section>\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport type { ApprovalRecordSettingsResponse } from './types';\n\nasync function fetchApprovalRecordSettings(): Promise<ApprovalRecordSettingsResponse> {\n const response = await apiFetch('/api/authorization/records/settings');\n const payload = (await response.json()) as ApprovalRecordSettingsResponse;\n if (!response.ok) {\n throw new Error(payload.error || '加载审批记录设置失败');\n }\n return payload;\n}\n\nasync function updateApprovalRecordSettings(\n autoCleanupEnabled: boolean,\n): Promise<ApprovalRecordSettingsResponse> {\n const response = await apiFetch('/api/authorization/records/settings', {\n method: 'PUT',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ autoCleanupEnabled }),\n });\n const payload = (await response.json()) as ApprovalRecordSettingsResponse;\n if (!response.ok) {\n throw new Error(payload.error || '保存审批记录设置失败');\n }\n return payload;\n}\n\nexport function useApprovalRecordSettings(open: boolean, active: boolean) {\n const addToast = useToastStore((state) => state.addToast);\n const [autoCleanupEnabled, setAutoCleanupEnabled] = useState(false);\n const [loading, setLoading] = useState(false);\n const [loadFailed, setLoadFailed] = useState(false);\n const [saving, setSaving] = useState(false);\n const [loaded, setLoaded] = useState(false);\n\n useEffect(() => {\n if (!open) {\n setAutoCleanupEnabled(false);\n setLoading(false);\n setLoadFailed(false);\n setSaving(false);\n setLoaded(false);\n return;\n }\n if (!active || loaded) return;\n\n let cancelled = false;\n\n async function loadSettings() {\n setLoading(true);\n setLoadFailed(false);\n\n try {\n const payload = await fetchApprovalRecordSettings();\n if (typeof payload.autoCleanupEnabled !== 'boolean') {\n throw new Error(payload.error || '加载审批记录设置失败');\n }\n if (cancelled) return;\n\n setAutoCleanupEnabled(payload.autoCleanupEnabled);\n setLoaded(true);\n } catch (error) {\n if (cancelled) return;\n\n setAutoCleanupEnabled(false);\n setLoadFailed(true);\n addToast({\n type: 'error',\n title: '审批记录设置加载失败',\n message: error instanceof Error ? error.message : '加载审批记录设置失败',\n duration: 3000,\n });\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n void loadSettings();\n\n return () => {\n cancelled = true;\n };\n }, [active, addToast, loaded, open]);\n\n const handleToggleAutoCleanup = async () => {\n if (loading || loadFailed || saving) return;\n\n const previousEnabled = autoCleanupEnabled;\n const nextEnabled = !previousEnabled;\n setAutoCleanupEnabled(nextEnabled);\n setSaving(true);\n\n try {\n await updateApprovalRecordSettings(nextEnabled);\n addToast({ type: 'success', title: '审批记录设置成功', message: '', duration: 2000 });\n } catch (error) {\n setAutoCleanupEnabled(previousEnabled);\n addToast({\n type: 'error',\n title: '审批记录设置失败',\n message: error instanceof Error ? error.message : '保存审批记录设置失败',\n duration: 3000,\n });\n } finally {\n setSaving(false);\n }\n };\n\n return {\n autoCleanupEnabled,\n loading,\n loadFailed,\n saving,\n handleToggleAutoCleanup,\n };\n}\n","'use client';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { useToastStore } from '@/stores/toastStore';\nimport { apiFetch } from '@/utils/api-client';\nimport type { PermissionDecision, PermissionsConfig, SecurityPolicyItem } from './types';\nimport {\n formatPaginationPages,\n isPermissionsEnabled,\n normalizePolicies,\n updateToolValue,\n} from './utils';\n\nconst PAGE_SIZE = 5;\n\nexport function useSecurityApprovalSettings(open: boolean) {\n const addToast = useToastStore((state) => state.addToast);\n const [permissionsConfig, setPermissionsConfig] = useState<PermissionsConfig | null>(null);\n const [approvalBarEnabled, setApprovalBarEnabled] = useState(false);\n const [workspaceRwEnabled, setWorkspaceRwEnabled] = useState(false);\n const [policies, setPolicies] = useState<SecurityPolicyItem[]>([]);\n const [page, setPage] = useState(1);\n const [searchQuery, setSearchQuery] = useState('');\n const [loading, setLoading] = useState(false);\n const [loadFailed, setLoadFailed] = useState(false);\n const [savingApprovalBar, setSavingApprovalBar] = useState(false);\n const [savingWorkspaceRw, setSavingWorkspaceRw] = useState(false);\n const [savingPolicyIds, setSavingPolicyIds] = useState<Record<string, boolean>>({});\n\n useEffect(() => {\n if (!open) {\n setPermissionsConfig(null);\n setApprovalBarEnabled(false);\n setWorkspaceRwEnabled(false);\n setPolicies([]);\n setPage(1);\n setSearchQuery('');\n setLoading(false);\n setLoadFailed(false);\n setSavingApprovalBar(false);\n setSavingWorkspaceRw(false);\n setSavingPolicyIds({});\n return;\n }\n\n let cancelled = false;\n\n async function loadPermissions() {\n setLoading(true);\n setLoadFailed(false);\n\n try {\n const response = await apiFetch('/api/config/relayclaw/security');\n const payload = (await response.json()) as {\n permissions?: PermissionsConfig;\n error?: string;\n };\n const permissions = payload.permissions;\n if (!response.ok || !permissions) {\n throw new Error(payload.error || '加载安全权限配置失败');\n }\n if (cancelled) return;\n\n setPermissionsConfig(permissions);\n setApprovalBarEnabled(isPermissionsEnabled(permissions));\n setWorkspaceRwEnabled(permissions.rw_enabled === true);\n setPolicies(normalizePolicies(permissions));\n setPage(1);\n setSearchQuery('');\n } catch (error) {\n if (cancelled) return;\n\n setPermissionsConfig(null);\n setApprovalBarEnabled(false);\n setWorkspaceRwEnabled(false);\n setPolicies([]);\n setLoadFailed(true);\n addToast({\n type: 'error',\n title: '安全管理加载失败',\n message: error instanceof Error ? error.message : '加载安全权限配置失败',\n duration: 3000,\n });\n } finally {\n if (!cancelled) {\n setLoading(false);\n }\n }\n }\n\n void loadPermissions();\n\n return () => {\n cancelled = true;\n };\n }, [open, addToast]);\n\n const filteredPolicies = useMemo(\n () =>\n policies.filter((policy) =>\n policy.action.toLowerCase().includes(searchQuery.toLowerCase()),\n ),\n [policies, searchQuery],\n );\n const totalPages = Math.max(1, Math.ceil(filteredPolicies.length / PAGE_SIZE));\n const paginatedPolicies = useMemo(\n () => filteredPolicies.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE),\n [filteredPolicies, page],\n );\n const showPagination = filteredPolicies.length > PAGE_SIZE;\n const paginationItems = showPagination ? formatPaginationPages(page, totalPages) : [];\n const showLoading = loading || (open && permissionsConfig === null && !loadFailed);\n\n const handleSearchChange = (value: string) => {\n setSearchQuery(value);\n setPage(1);\n };\n\n const handleToggleApprovalBar = async () => {\n if (savingApprovalBar) return;\n\n const previousEnabled = approvalBarEnabled;\n const nextEnabled = !previousEnabled;\n setApprovalBarEnabled(nextEnabled);\n setSavingApprovalBar(true);\n\n try {\n const response = await apiFetch('/api/config/relayclaw/security', {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n permissions: {\n enabled: nextEnabled,\n },\n }),\n });\n const payload = (await response.json()) as { error?: string };\n if (!response.ok) throw new Error(payload.error || '保存审批护栏设置失败');\n\n setPermissionsConfig((current) => ({\n ...(current ?? {}),\n enabled: nextEnabled,\n }));\n addToast({ type: 'success', title: '审批护栏设置成功', message: '', duration: 2000 });\n } catch (error) {\n setApprovalBarEnabled(previousEnabled);\n addToast({\n type: 'error',\n title: '审批护栏设置失败',\n message: error instanceof Error ? error.message : '保存审批护栏设置失败',\n duration: 3000,\n });\n } finally {\n setSavingApprovalBar(false);\n }\n };\n\n const handleToggleWorkspaceRw = async () => {\n if (savingWorkspaceRw) return;\n\n const previousEnabled = workspaceRwEnabled;\n const nextEnabled = !previousEnabled;\n setWorkspaceRwEnabled(nextEnabled);\n setSavingWorkspaceRw(true);\n\n try {\n const response = await apiFetch('/api/config/relayclaw/security', {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n permissions: {\n rw_enabled: nextEnabled,\n },\n }),\n });\n const payload = (await response.json()) as { error?: string };\n if (!response.ok) throw new Error(payload.error || '保存工作空间读写设置失败');\n\n setPermissionsConfig((current) => ({\n ...(current ?? {}),\n rw_enabled: nextEnabled,\n }));\n addToast({ type: 'success', title: '工作空间读写设置成功', message: '', duration: 2000 });\n } catch (error) {\n setWorkspaceRwEnabled(previousEnabled);\n addToast({\n type: 'error',\n title: '工作空间读写设置失败',\n message: error instanceof Error ? error.message : '保存工作空间读写设置失败',\n duration: 3000,\n });\n } finally {\n setSavingWorkspaceRw(false);\n }\n };\n\n const handleTogglePolicy = async (id: string) => {\n if (savingPolicyIds[id]) return;\n\n const currentPolicy = policies.find((policy) => policy.id === id);\n const previousApprovalRequired = currentPolicy?.approvalRequired ?? false;\n const currentValue = permissionsConfig?.tools?.[id];\n const nextApprovalRequired = !previousApprovalRequired;\n const nextDecision: PermissionDecision = nextApprovalRequired ? 'ask' : 'allow';\n const nextToolValue = updateToolValue(currentValue, nextDecision);\n\n setPolicies((current) =>\n current.map((policy) =>\n policy.id === id ? { ...policy, approvalRequired: nextApprovalRequired } : policy,\n ),\n );\n setPermissionsConfig((current) => ({\n ...(current ?? {}),\n tools: {\n ...(current?.tools ?? {}),\n [id]: nextToolValue,\n },\n }));\n setSavingPolicyIds((current) => ({ ...current, [id]: true }));\n\n try {\n const response = await apiFetch('/api/config/relayclaw/security', {\n method: 'PATCH',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n permissions: {\n tools: {\n [id]: nextToolValue,\n },\n },\n }),\n });\n const payload = (await response.json()) as { error?: string };\n if (!response.ok) throw new Error(payload.error || '保存安全策略失败');\n addToast({ type: 'success', title: '安全策略设置成功', message: '', duration: 2000 });\n } catch (error) {\n setPolicies((current) =>\n current.map((policy) =>\n policy.id === id ? { ...policy, approvalRequired: previousApprovalRequired } : policy,\n ),\n );\n setPermissionsConfig((current) => {\n const nextTools = { ...(current?.tools ?? {}) };\n if (currentValue === undefined) {\n delete nextTools[id];\n } else {\n nextTools[id] = currentValue;\n }\n\n return {\n ...(current ?? {}),\n tools: nextTools,\n };\n });\n addToast({\n type: 'error',\n title: '安全策略设置失败',\n message: error instanceof Error ? error.message : '保存安全策略失败',\n duration: 3000,\n });\n } finally {\n setSavingPolicyIds((current) => {\n const next = { ...current };\n delete next[id];\n return next;\n });\n }\n };\n\n return {\n loading: showLoading,\n loadFailed,\n approvalBarEnabled,\n workspaceRwEnabled,\n savingApprovalBar,\n savingWorkspaceRw,\n savingPolicyIds,\n hasPolicies: policies.length > 0,\n paginatedPolicies,\n page,\n totalPages,\n paginationItems,\n showPagination,\n searchQuery,\n setPage,\n handleSearchChange,\n handleToggleApprovalBar,\n handleToggleWorkspaceRw,\n handleTogglePolicy,\n };\n}\n","'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useEscapeKey } from '@/hooks/useEscapeKey';\nimport { AppModal } from './AppModal';\nimport { Tab } from './shared/Tab';\nimport { ApprovalRecordsTab } from './security-management/ApprovalRecordsTab';\nimport { SecurityApprovalSettingsTab } from './security-management/SecurityApprovalSettingsTab';\nimport { useApprovalRecordSettings } from './security-management/useApprovalRecordSettings';\nimport { useApprovalRecords } from './security-management/useApprovalRecords';\nimport { useSecurityApprovalSettings } from './security-management/useSecurityApprovalSettings';\n\nexport interface SecurityManagementModalProps {\n open: boolean;\n onClose: () => void;\n}\n\ntype SecurityManagementTab = 'approval' | 'records';\n\nconst TAB_ITEMS = [\n { value: 'approval', label: '安全审批' },\n { value: 'records', label: '审批记录' },\n];\n\nexport default function SecurityManagementModal({ open, onClose }: SecurityManagementModalProps) {\n const [activeTab, setActiveTab] = useState<SecurityManagementTab>('approval');\n const approvalSettings = useSecurityApprovalSettings(open);\n const approvalRecordSettings = useApprovalRecordSettings(open, activeTab === 'records');\n const approvalRecords = useApprovalRecords(open, activeTab === 'records');\n\n useEffect(() => {\n if (!open) {\n setActiveTab('approval');\n }\n }, [open]);\n\n useEscapeKey({\n enabled: open,\n onEscape: onClose,\n });\n\n return (\n <AppModal\n open={open}\n onClose={onClose}\n disableBackdropClose\n title=\"安全管理\"\n closeButtonAriaLabel=\"关闭安全管理弹窗\"\n backdropTestId=\"security-management-modal-backdrop\"\n panelTestId=\"security-management-modal\"\n bodyTestId=\"security-management-modal-body\"\n panelClassName=\"min-h-[480px] w-[700px] max-h-[calc(100vh-32px)] max-w-[calc(100vw-32px)] overflow-hidden\"\n headerClassName=\"p-0 pb-4\"\n bodyClassName=\"flex min-h-0 flex-1 flex-col overflow-hidden\"\n >\n <div className=\"mb-4\" data-testid=\"security-management-tabs\">\n <Tab\n items={TAB_ITEMS}\n value={activeTab}\n onChange={(value) => setActiveTab(value as SecurityManagementTab)}\n />\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-y-auto pr-1\" data-testid=\"security-management-scroll-region\">\n {activeTab === 'approval' ? (\n <SecurityApprovalSettingsTab\n loading={approvalSettings.loading}\n loadFailed={approvalSettings.loadFailed}\n approvalBarEnabled={approvalSettings.approvalBarEnabled}\n workspaceRwEnabled={approvalSettings.workspaceRwEnabled}\n savingApprovalBar={approvalSettings.savingApprovalBar}\n savingWorkspaceRw={approvalSettings.savingWorkspaceRw}\n savingPolicyIds={approvalSettings.savingPolicyIds}\n hasPolicies={approvalSettings.hasPolicies}\n paginatedPolicies={approvalSettings.paginatedPolicies}\n page={approvalSettings.page}\n totalPages={approvalSettings.totalPages}\n paginationItems={approvalSettings.paginationItems}\n showPagination={approvalSettings.showPagination}\n searchQuery={approvalSettings.searchQuery}\n onPageChange={approvalSettings.setPage}\n onSearchChange={approvalSettings.handleSearchChange}\n onToggleApprovalBar={() => void approvalSettings.handleToggleApprovalBar()}\n onToggleWorkspaceRw={() => void approvalSettings.handleToggleWorkspaceRw()}\n onTogglePolicy={(id) => void approvalSettings.handleTogglePolicy(id)}\n />\n ) : (\n <ApprovalRecordsTab\n records={approvalRecords.records}\n autoCleanupEnabled={approvalRecordSettings.autoCleanupEnabled}\n loadingAutoCleanupSetting={approvalRecordSettings.loading}\n autoCleanupSettingLoadFailed={approvalRecordSettings.loadFailed}\n savingAutoCleanupSetting={approvalRecordSettings.saving}\n searchQuery={approvalRecords.searchQuery}\n page={approvalRecords.page}\n totalPages={approvalRecords.totalPages}\n paginationItems={approvalRecords.paginationItems}\n showPagination={approvalRecords.showPagination}\n loadingPage={approvalRecords.loadingPage}\n showSearchInput={approvalRecords.showSearchInput}\n showSearchLoading={approvalRecords.showSearchLoading}\n showInitialLoading={approvalRecords.showInitialLoading}\n showEmptyState={approvalRecords.showEmptyState}\n showNoSearchResults={approvalRecords.showNoSearchResults}\n onToggleAutoCleanup={() => void approvalRecordSettings.handleToggleAutoCleanup()}\n onSearchChange={approvalRecords.setSearchQuery}\n onPageChange={(page) => void approvalRecords.handlePageChange(page)}\n />\n )}\n </div>\n </AppModal>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * Shared helper functions for status display (tokens, costs, durations).\n */\n\nexport type IntentMode = 'execute' | 'ideate' | null;\nexport type AgentStreamStatus = 'pending' | 'streaming' | 'done' | 'error' | 'alive_but_silent' | 'suspected_stall';\n\nexport function statusLabel(status: AgentStreamStatus): string {\n switch (status) {\n case 'pending':\n return '待命';\n case 'streaming':\n return '工作中';\n case 'done':\n return '完成';\n case 'error':\n return '异常';\n case 'alive_but_silent':\n return '静默等待';\n case 'suspected_stall':\n return '疑似卡住';\n default:\n return '未知';\n }\n}\n\nexport function statusTone(status: AgentStreamStatus): string {\n switch (status) {\n case 'pending':\n return 'text-gray-500';\n case 'streaming':\n return 'text-green-600';\n case 'done':\n return 'text-emerald-700';\n case 'error':\n return 'text-red-600';\n case 'alive_but_silent':\n return 'text-amber-500';\n case 'suspected_stall':\n return 'text-orange-600';\n default:\n return 'text-gray-500';\n }\n}\n\nexport function truncateId(id: string, len = 8): string {\n return id.length > len ? `${id.slice(0, len)}…` : id;\n}\n\nexport function formatDuration(ms: number): string {\n if (ms < 1000) return `${ms}ms`;\n return `${(ms / 1000).toFixed(1)}s`;\n}\n\n/** F8: Format token count as compact string (e.g. 39270 → \"39.3k\") */\nexport function formatTokenCount(n: number): string {\n if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;\n if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;\n return String(n);\n}\n\n/** F8: Format USD cost (e.g. 0.03 → \"$0.03\") */\nexport function formatCost(usd: number): string {\n return `$${usd.toFixed(usd < 0.01 ? 4 : 2)}`;\n}\n"],"names":["tintedLight","hex","ratio","base","parse","h","r1","g1","b1","r2","g2","b2","hexToRgba","alpha","cleaned","g","b","useTheme","theme","setTheme","toggleTheme","isLoaded","initializeTheme","useThemeStore","useEffect","ToggleSwitch","checked","onToggle","ariaLabel","disabled","testId","jsx","APPROVAL_RECORDS_PAGE_SIZE","APPROVAL_RECORDS_REQUEST_LIMIT","getToolDecision","value","normalizePolicies","config","tools","toolName","isPermissionsEnabled","updateToolValue","current","nextDecision","formatPaginationPages","currentPage","totalPages","_","index","pages","sortedPages","page","a","result","previous","SEARCH_DEBOUNCE_MS","buildRecordsUrl","query","offset","params","fetchApprovalRecords","response","apiFetch","payload","formatApprovalRecordTime","date","useApprovalRecords","open","active","addToast","useToastStore","state","requestIdRef","useRef","recordBatches","setRecordBatches","useState","searchQuery","setSearchQuery","debouncedSearchQuery","setDebouncedSearchQuery","loadedQuery","setLoadedQuery","setPage","totalCount","setTotalCount","hasAvailableRecords","setHasAvailableRecords","loadingInitial","setLoadingInitial","loadingSearch","setLoadingSearch","loadingPage","setLoadingPage","timeoutId","currentRequestId","isInitialLoad","loadRecords","nextRecords","error","handlePageChange","targetPage","targetStartIndex","targetBatchOffset","currentBatches","normalizedSearchQuery","useMemo","currentPageStartIndex","currentBatchOffset","currentBatch","currentBatchStartIndex","records","showSearchInput","showSearchLoading","showInitialLoading","showEmptyState","showNoSearchResults","showPagination","paginationItems","ApprovalRecordsTab","autoCleanupEnabled","loadingAutoCleanupSetting","autoCleanupSettingLoadFailed","savingAutoCleanupSetting","onToggleAutoCleanup","onSearchChange","onPageChange","jsxs","CenteredLoadingState","EmptyDataState","SearchInput","NoSearchResultsState","Fragment","record","threadLabel","timeLabel","OverflowTooltip","item","SecurityApprovalSettingsTab","loading","loadFailed","approvalBarEnabled","workspaceRwEnabled","savingApprovalBar","savingWorkspaceRw","savingPolicyIds","hasPolicies","paginatedPolicies","onToggleApprovalBar","onToggleWorkspaceRw","onTogglePolicy","policy","fetchApprovalRecordSettings","updateApprovalRecordSettings","useApprovalRecordSettings","setAutoCleanupEnabled","setLoading","setLoadFailed","saving","setSaving","loaded","setLoaded","cancelled","loadSettings","previousEnabled","nextEnabled","PAGE_SIZE","useSecurityApprovalSettings","permissionsConfig","setPermissionsConfig","setApprovalBarEnabled","setWorkspaceRwEnabled","policies","setPolicies","setSavingApprovalBar","setSavingWorkspaceRw","setSavingPolicyIds","loadPermissions","permissions","filteredPolicies","showLoading","handleSearchChange","handleToggleApprovalBar","handleToggleWorkspaceRw","handleTogglePolicy","id","currentPolicy","previousApprovalRequired","currentValue","_a","nextApprovalRequired","nextToolValue","nextTools","next","TAB_ITEMS","SecurityManagementModal","onClose","activeTab","setActiveTab","approvalSettings","approvalRecordSettings","approvalRecords","useEscapeKey","AppModal","Tab","formatDuration","ms","formatTokenCount","n","formatCost","usd"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ const E=/([@\uFF20])([^\s,.:;!?\[\]{}<>\uFF0C\u3002\uFF01\uFF1F\u3001\uFF1A\uFF1B\u3010\u3011\u300A\u300B\u300C\u300D\u300E\u300F\u3008\u3009()()]+)(?:\uFF08([^\uFF09]*)\uFF09|\(([^)]*)\))?/g,p=/^[\s.\u3002\u2026!\uFF01?\uFF1F,\uFF0C:\uFF1A;\uFF1B\u3001~\-\u2014_()()]+/,g=/[A-Za-z0-9\u4E00-\u9FFF]/,f=/^[,.:;!?()\[\]{}<>\uFF0C\u3002\uFF01\uFF1F\u3001\uFF1A\uFF1B]+|[,.:;!?()\[\]{}<>\uFF0C\u3002\uFF01\uFF1F\u3001\uFF1A\uFF1B]+$/g,d=/[@\uFF20][^\s,.:;!?\[\]{}<>\uFF0C\u3002\uFF01\uFF1F\u3001\uFF1A\uFF1B\u3010\u3011\u300A\u300B\u300C\u300D\u300E\u300F\u3008\u3009()()]+(?:\uFF08[^\uFF09]*\uFF09|\([^)]*\))?/g,a="[\\s,.:;!?()\\[\\]{}<>\\uFF0C\\u3002\\uFF01\\uFF1F\\u3001\\uFF1A\\uFF1B\\uFF08\\uFF09\\u3010\\u3011\\u300A\\u300B\\u300C\\u300D\\u300E\\u300F\\u3008\\u3009]";function A(F){return F.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function m(F,u){return F.replace(E,(t,r,o,i,l)=>{if(!u)return" ";const s=o.toLowerCase();if(u.has(s))return" ";const c=i??l;return c&&u.has(`${s}(${c.toLowerCase()})`)?" ":t}).replace(d," ").replace(/\s+/g," ").trim()}function C(F,u){if(!u||u.size===0)return F;let e=F;const n=Array.from(u).map(t=>t.trim()).filter(Boolean).sort((t,r)=>r.length-t.length);for(const t of n){const r=A(t),o=new RegExp(`(^|${a})${r}(?=$|${a})`,"giu");e=e.replace(o,"$1")}return e.replace(f,"").replace(/\s+/g," ").trim()}function N(F,u){const e=m((F??"").trim(),u),t=C(e,u).replace(p,"").trim();return t&&g.test(t)?t:null}function B(F){return(F??"").trim()||null}function _(F,u="未命名对话"){return B(F)??u}export{_ as a,B as n,N as s};
2
+ //# sourceMappingURL=thread-title-Cerb2mHa.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-title-Cerb2mHa.js","sources":["../../src/components/thread-sidebar/thread-title.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nconst TOKEN_RE =\n /([@\\uFF20])([^\\s,.:;!?\\[\\]{}<>\\uFF0C\\u3002\\uFF01\\uFF1F\\u3001\\uFF1A\\uFF1B\\u3010\\u3011\\u300A\\u300B\\u300C\\u300D\\u300E\\u300F\\u3008\\u3009()()]+)(?:\\uFF08([^\\uFF09]*)\\uFF09|\\(([^)]*)\\))?/g;\nconst LEADING_NOISE_RE = /^[\\s.\\u3002\\u2026!\\uFF01?\\uFF1F,\\uFF0C:\\uFF1A;\\uFF1B\\u3001~\\-\\u2014_()()]+/;\nconst MEANINGFUL_CHAR_RE = /[A-Za-z0-9\\u4E00-\\u9FFF]/;\nconst EDGE_PUNCT_RE = /^[,.:;!?()\\[\\]{}<>\\uFF0C\\u3002\\uFF01\\uFF1F\\u3001\\uFF1A\\uFF1B]+|[,.:;!?()\\[\\]{}<>\\uFF0C\\u3002\\uFF01\\uFF1F\\u3001\\uFF1A\\uFF1B]+$/g;\nconst GENERIC_MENTION_RE =\n /[@\\uFF20][^\\s,.:;!?\\[\\]{}<>\\uFF0C\\u3002\\uFF01\\uFF1F\\u3001\\uFF1A\\uFF1B\\u3010\\u3011\\u300A\\u300B\\u300C\\u300D\\u300E\\u300F\\u3008\\u3009()()]+(?:\\uFF08[^\\uFF09]*\\uFF09|\\([^)]*\\))?/g;\nconst BOUNDARY = '[\\\\s,.:;!?()\\\\[\\\\]{}<>\\\\uFF0C\\\\u3002\\\\uFF01\\\\uFF1F\\\\u3001\\\\uFF1A\\\\uFF1B\\\\uFF08\\\\uFF09\\\\u3010\\\\u3011\\\\u300A\\\\u300B\\\\u300C\\\\u300D\\\\u300E\\\\u300F\\\\u3008\\\\u3009]';\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport function stripAgentMentions(text: string, knownAliases?: ReadonlySet<string>): string {\n const targeted = text.replace(\n TOKEN_RE,\n (full: string, _at: string, alias: string, fullWidthSuffix?: string, halfWidthSuffix?: string) => {\n if (!knownAliases) return ' ';\n const base = alias.toLowerCase();\n if (knownAliases.has(base)) return ' ';\n const suffix = fullWidthSuffix ?? halfWidthSuffix;\n if (suffix && knownAliases.has(`${base}(${suffix.toLowerCase()})`)) return ' ';\n return full;\n },\n );\n // Fallback: remove any remaining @token mentions to handle unregistered aliases/special chars.\n const replaced = targeted.replace(GENERIC_MENTION_RE, ' ');\n return replaced.replace(/\\s+/g, ' ').trim();\n}\n\nfunction stripBareAgentAliases(text: string, knownAliases?: ReadonlySet<string>): string {\n if (!knownAliases || knownAliases.size === 0) return text;\n let next = text;\n const aliases = Array.from(knownAliases)\n .map((a) => a.trim())\n .filter(Boolean)\n .sort((a, b) => b.length - a.length);\n for (const alias of aliases) {\n const escaped = escapeRegExp(alias);\n const re = new RegExp(`(^|${BOUNDARY})${escaped}(?=$|${BOUNDARY})`, 'giu');\n next = next.replace(re, '$1');\n }\n return next.replace(EDGE_PUNCT_RE, '').replace(/\\s+/g, ' ').trim();\n}\n\nexport function sanitizeThreadTitleOrNull(\n rawTitle: string | null | undefined,\n knownAliases?: ReadonlySet<string>,\n): string | null {\n const withoutMentions = stripAgentMentions((rawTitle ?? '').trim(), knownAliases);\n const withoutAgentWords = stripBareAgentAliases(withoutMentions, knownAliases);\n const cleaned = withoutAgentWords.replace(LEADING_NOISE_RE, '').trim();\n return cleaned && MEANINGFUL_CHAR_RE.test(cleaned) ? cleaned : null;\n}\n\nexport function normalizeStoredThreadTitleOrNull(rawTitle: string | null | undefined): string | null {\n const trimmed = (rawTitle ?? '').trim();\n return trimmed || null;\n}\n\nexport function normalizeStoredThreadTitle(\n rawTitle: string | null | undefined,\n fallback = '\\u672A\\u547D\\u540D\\u5BF9\\u8BDD',\n): string {\n return normalizeStoredThreadTitleOrNull(rawTitle) ?? fallback;\n}\n"],"names":["TOKEN_RE","LEADING_NOISE_RE","MEANINGFUL_CHAR_RE","EDGE_PUNCT_RE","GENERIC_MENTION_RE","BOUNDARY","escapeRegExp","value","stripAgentMentions","text","knownAliases","full","_at","alias","fullWidthSuffix","halfWidthSuffix","base","suffix","stripBareAgentAliases","next","aliases","a","b","escaped","re","sanitizeThreadTitleOrNull","rawTitle","withoutMentions","cleaned","normalizeStoredThreadTitleOrNull","normalizeStoredThreadTitle","fallback"],"mappings":"AAMA,MAAMA,EACJ,wLACIC,EAAmB,6EACnBC,EAAqB,2BACrBC,EAAgB,iIAChBC,EACJ,gLACIC,EAAW,+JAEjB,SAASC,EAAaC,EAAuB,CAC3C,OAAOA,EAAM,QAAQ,sBAAuB,MAAM,CACpD,CAEO,SAASC,EAAmBC,EAAcC,EAA4C,CAc3F,OAbiBD,EAAK,QACpBT,EACA,CAACW,EAAcC,EAAaC,EAAeC,EAA0BC,IAA6B,CAChG,GAAI,CAACL,EAAc,MAAO,IAC1B,MAAMM,EAAOH,EAAM,YAAA,EACnB,GAAIH,EAAa,IAAIM,CAAI,EAAG,MAAO,IACnC,MAAMC,EAASH,GAAmBC,EAClC,OAAIE,GAAUP,EAAa,IAAI,GAAGM,CAAI,IAAIC,EAAO,YAAA,CAAa,GAAG,EAAU,IACpEN,CACT,CAAA,EAGwB,QAAQP,EAAoB,GAAG,EACzC,QAAQ,OAAQ,GAAG,EAAE,KAAA,CACvC,CAEA,SAASc,EAAsBT,EAAcC,EAA4C,CACvF,GAAI,CAACA,GAAgBA,EAAa,OAAS,EAAG,OAAOD,EACrD,IAAIU,EAAOV,EACX,MAAMW,EAAU,MAAM,KAAKV,CAAY,EACpC,IAAKW,GAAMA,EAAE,KAAA,CAAM,EACnB,OAAO,OAAO,EACd,KAAK,CAACA,EAAGC,IAAMA,EAAE,OAASD,EAAE,MAAM,EACrC,UAAWR,KAASO,EAAS,CAC3B,MAAMG,EAAUjB,EAAaO,CAAK,EAC5BW,EAAK,IAAI,OAAO,MAAMnB,CAAQ,IAAIkB,CAAO,QAAQlB,CAAQ,IAAK,KAAK,EACzEc,EAAOA,EAAK,QAAQK,EAAI,IAAI,CAC9B,CACA,OAAOL,EAAK,QAAQhB,EAAe,EAAE,EAAE,QAAQ,OAAQ,GAAG,EAAE,KAAA,CAC9D,CAEO,SAASsB,EACdC,EACAhB,EACe,CACf,MAAMiB,EAAkBnB,GAAoBkB,GAAY,IAAI,KAAA,EAAQhB,CAAY,EAE1EkB,EADoBV,EAAsBS,EAAiBjB,CAAY,EAC3C,QAAQT,EAAkB,EAAE,EAAE,KAAA,EAChE,OAAO2B,GAAW1B,EAAmB,KAAK0B,CAAO,EAAIA,EAAU,IACjE,CAEO,SAASC,EAAiCH,EAAoD,CAEnG,OADiBA,GAAY,IAAI,KAAA,GACf,IACpB,CAEO,SAASI,EACdJ,EACAK,EAAW,QACH,CACR,OAAOF,EAAiCH,CAAQ,GAAKK,CACvD"}
@@ -0,0 +1,2 @@
1
+ function g(e,r=!1){if(!Number.isFinite(e)||e<=0)return"-";const a=new Date(e);if(Number.isNaN(a.getTime()))return"-";const n=new Date,t=a.getFullYear()===n.getFullYear()&&a.getMonth()===n.getMonth()&&a.getDate()===n.getDate(),o=String(a.getMonth()+1).padStart(2,"0"),c=String(a.getDate()).padStart(2,"0");if(!t)return`${o}/${c}`;const i=String(a.getHours()).padStart(2,"0"),s=String(a.getMinutes()).padStart(2,"0");return`${i}:${s}`}function p(e){if(e==="default")return"未分类";const r=e.replace(/\/+$/,"").split("/");return r[r.length-1]||e}function f(e){const r=new Set;for(const t of e)t.projectPath&&t.projectPath!=="default"&&r.add(t.projectPath);const a=[...r],n=new Map;for(const t of e)if(t.projectPath&&t.projectPath!=="default"){const o=n.get(t.projectPath)??0;t.lastActiveAt>o&&n.set(t.projectPath,t.lastActiveAt)}return a.sort((t,o)=>(n.get(o)??0)-(n.get(t)??0))}export{g as f,f as g,p};
2
+ //# sourceMappingURL=thread-utils-Ct3yp4R3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-utils-Ct3yp4R3.js","sources":["../../src/components/thread-sidebar/thread-utils.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport type { ChatMessage, Thread, ThreadState } from '@/stores/chat-types';\nimport { getRecentThreads, splitIntoActiveAndArchived } from './active-workspace';\n\nexport function formatRelativeTime(ts: number, compact = false): string {\n if (!Number.isFinite(ts) || ts <= 0) return '-';\n const d = new Date(ts);\n if (Number.isNaN(d.getTime())) return '-';\n const now = new Date();\n const isSameDay =\n d.getFullYear() === now.getFullYear() &&\n d.getMonth() === now.getMonth() &&\n d.getDate() === now.getDate();\n const mm = String(d.getMonth() + 1).padStart(2, '0');\n const dd = String(d.getDate()).padStart(2, '0');\n if (!isSameDay) return `${mm}/${dd}`;\n const hh = String(d.getHours()).padStart(2, '0');\n const min = String(d.getMinutes()).padStart(2, '0');\n return `${hh}:${min}`;\n}\n\nexport function projectDisplayName(path: string): string {\n if (path === 'default') return '未分类';\n const parts = path.replace(/\\/+$/, '').split('/');\n return parts[parts.length - 1] || path;\n}\n\nexport function getProjectPaths(threads: Thread[]): string[] {\n const paths = new Set<string>();\n for (const t of threads) {\n if (t.projectPath && t.projectPath !== 'default') {\n paths.add(t.projectPath);\n }\n }\n // F095 Phase C (AC-C4): Sort by most recent thread activity, not alphabetically\n const pathList = [...paths];\n const activityMap = new Map<string, number>();\n for (const t of threads) {\n if (t.projectPath && t.projectPath !== 'default') {\n const current = activityMap.get(t.projectPath) ?? 0;\n if (t.lastActiveAt > current) activityMap.set(t.projectPath, t.lastActiveAt);\n }\n }\n\n return pathList.sort((a, b) => (activityMap.get(b) ?? 0) - (activityMap.get(a) ?? 0));\n}\n\nfunction getLatestMessageTimestamp(messages: ChatMessage[] | undefined): number {\n if (!messages || messages.length === 0) return 0;\n let latest = 0;\n for (const message of messages) {\n if (Number.isFinite(message.timestamp) && message.timestamp > latest) {\n latest = message.timestamp;\n }\n }\n return latest;\n}\n\nexport function applyRealtimeThreadActivity(\n threads: Thread[],\n threadStates: Record<string, Pick<ThreadState, 'messages'> | undefined>,\n): Thread[] {\n return threads.map((thread) => {\n const localLastActivity = getLatestMessageTimestamp(threadStates[thread.id]?.messages);\n if (localLastActivity <= thread.lastActiveAt) {\n return thread;\n }\n return { ...thread, lastActiveAt: localLastActivity };\n });\n}\n\nexport interface ThreadGroup {\n type: 'pinned' | 'recent' | 'project' | 'archived-container' | 'favorites';\n label: string;\n threads: Thread[];\n projectPath?: string;\n archivedGroups?: ThreadGroup[];\n}\n\nfunction sortByUnreadThenActive(a: Thread, b: Thread, unreadIds?: Set<string>): number {\n if (unreadIds) {\n const aUnread = unreadIds.has(a.id) ? 1 : 0;\n const bUnread = unreadIds.has(b.id) ? 1 : 0;\n if (aUnread !== bUnread) return bUnread - aUnread;\n }\n return b.lastActiveAt - a.lastActiveAt;\n}\n\nexport function sortAndGroupThreads(threads: Thread[], unreadIds?: Set<string>): ThreadGroup[] {\n const groups: ThreadGroup[] = [];\n\n // 1. Pinned threads (unread first, then by lastActiveAt desc)\n const pinned = threads\n .filter((t) => t.pinned && t.id !== 'default')\n .sort((a, b) => sortByUnreadThenActive(a, b, unreadIds));\n if (pinned.length > 0) {\n groups.push({ type: 'pinned', label: '置顶', threads: pinned });\n }\n\n // 2. Regular threads grouped by project (each group sorted)\n const regular = threads.filter((t) => !t.pinned && !t.favorited && t.id !== 'default');\n const projectGroups = groupByProject(regular, unreadIds);\n for (const [projectPath, projectThreads] of projectGroups) {\n groups.push({\n type: 'project',\n label: projectDisplayName(projectPath),\n threads: projectThreads,\n projectPath,\n });\n }\n\n // 3. Favorites (unread first, then by lastActiveAt desc, excluding pinned)\n const favorited = threads\n .filter((t) => t.favorited && !t.pinned && t.id !== 'default')\n .sort((a, b) => sortByUnreadThenActive(a, b, unreadIds));\n if (favorited.length > 0) {\n groups.push({ type: 'favorites', label: '收藏', threads: favorited });\n }\n\n return groups;\n}\n\nexport interface WorkspaceConfig {\n activeCutoffMs: number;\n recentLimit: number;\n}\n\nconst DEFAULT_CONFIG: WorkspaceConfig = {\n activeCutoffMs: 7 * 86400_000,\n recentLimit: 8,\n};\n\nexport function sortAndGroupThreadsWithWorkspace(\n threads: Thread[],\n unreadIds: Set<string> | undefined,\n pinnedProjects: Set<string>,\n config: WorkspaceConfig = DEFAULT_CONFIG,\n now: number = Date.now(),\n): ThreadGroup[] {\n const groups: ThreadGroup[] = [];\n\n const pinned = threads\n .filter((thread) => thread.pinned && thread.id !== 'default')\n .sort((a, b) => sortByUnreadThenActive(a, b, unreadIds));\n if (pinned.length > 0) {\n groups.push({ type: 'pinned', label: '置顶', threads: pinned });\n }\n\n const recent = getRecentThreads(threads, config.recentLimit, now);\n if (recent.length > 0) {\n groups.push({ type: 'recent', label: '最近会话', threads: recent });\n }\n\n const regular = threads.filter((thread) => !thread.pinned && !thread.favorited && thread.id !== 'default');\n const projectGroupEntries = groupByProject(regular, unreadIds);\n const allProjectGroups: ThreadGroup[] = projectGroupEntries.map(([projectPath, projectThreads]) => ({\n type: 'project',\n label: projectDisplayName(projectPath),\n threads: projectThreads,\n projectPath,\n }));\n\n const { active, archived } = splitIntoActiveAndArchived(\n allProjectGroups,\n threads,\n pinnedProjects,\n config.activeCutoffMs,\n now,\n );\n\n for (const group of active) {\n groups.push(group);\n }\n\n if (archived.length > 0) {\n const allArchivedThreads = archived.flatMap((group) => group.threads);\n groups.push({\n type: 'archived-container',\n label: `其他项目 (${archived.length})`,\n threads: allArchivedThreads,\n archivedGroups: archived,\n });\n }\n\n const favorited = threads\n .filter((thread) => thread.favorited && !thread.pinned && thread.id !== 'default')\n .sort((a, b) => sortByUnreadThenActive(a, b, unreadIds));\n if (favorited.length > 0) {\n groups.push({ type: 'favorites', label: '收藏', threads: favorited });\n }\n\n return groups;\n}\n\nfunction groupByProject(threads: Thread[], unreadIds?: Set<string>): [string, Thread[]][] {\n const groups = new Map<string, Thread[]>();\n for (const thread of threads) {\n const key = thread.projectPath;\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)?.push(thread);\n }\n\n for (const [, projectThreads] of groups) {\n projectThreads.sort((a, b) => sortByUnreadThenActive(a, b, unreadIds));\n }\n\n return [...groups.entries()].sort(([a], [b]) => {\n if (a === 'default') return 1;\n if (b === 'default') return -1;\n return a.localeCompare(b);\n });\n}\n"],"names":["formatRelativeTime","ts","compact","d","now","isSameDay","mm","dd","hh","min","projectDisplayName","path","parts","getProjectPaths","threads","paths","pathList","activityMap","current","a","b"],"mappings":"AASO,SAASA,EAAmBC,EAAYC,EAAU,GAAe,CACtE,GAAI,CAAC,OAAO,SAASD,CAAE,GAAKA,GAAM,EAAG,MAAO,IAC5C,MAAME,EAAI,IAAI,KAAKF,CAAE,EACrB,GAAI,OAAO,MAAME,EAAE,QAAA,CAAS,EAAG,MAAO,IACtC,MAAMC,MAAU,KACVC,EACJF,EAAE,YAAA,IAAkBC,EAAI,eACxBD,EAAE,SAAA,IAAeC,EAAI,YACrBD,EAAE,QAAA,IAAcC,EAAI,QAAA,EAChBE,EAAK,OAAOH,EAAE,SAAA,EAAa,CAAC,EAAE,SAAS,EAAG,GAAG,EAC7CI,EAAK,OAAOJ,EAAE,QAAA,CAAS,EAAE,SAAS,EAAG,GAAG,EAC9C,GAAI,CAACE,EAAW,MAAO,GAAGC,CAAE,IAAIC,CAAE,GAClC,MAAMC,EAAK,OAAOL,EAAE,SAAA,CAAU,EAAE,SAAS,EAAG,GAAG,EACzCM,EAAM,OAAON,EAAE,WAAA,CAAY,EAAE,SAAS,EAAG,GAAG,EAClD,MAAO,GAAGK,CAAE,IAAIC,CAAG,EACrB,CAEO,SAASC,EAAmBC,EAAsB,CACvD,GAAIA,IAAS,UAAW,MAAO,MAC/B,MAAMC,EAAQD,EAAK,QAAQ,OAAQ,EAAE,EAAE,MAAM,GAAG,EAChD,OAAOC,EAAMA,EAAM,OAAS,CAAC,GAAKD,CACpC,CAEO,SAASE,EAAgBC,EAA6B,CAC3D,MAAMC,MAAY,IAClB,UAAW,KAAKD,EACV,EAAE,aAAe,EAAE,cAAgB,WACrCC,EAAM,IAAI,EAAE,WAAW,EAI3B,MAAMC,EAAW,CAAC,GAAGD,CAAK,EACpBE,MAAkB,IACxB,UAAW,KAAKH,EACd,GAAI,EAAE,aAAe,EAAE,cAAgB,UAAW,CAChD,MAAMI,EAAUD,EAAY,IAAI,EAAE,WAAW,GAAK,EAC9C,EAAE,aAAeC,GAASD,EAAY,IAAI,EAAE,YAAa,EAAE,YAAY,CAC7E,CAGF,OAAOD,EAAS,KAAK,CAACG,EAAGC,KAAOH,EAAY,IAAIG,CAAC,GAAK,IAAMH,EAAY,IAAIE,CAAC,GAAK,EAAE,CACtF"}
@@ -0,0 +1,2 @@
1
+ import{P as A,r as c}from"./index-Cb4fQgom.js";import{a as H}from"./OverflowTooltip-CE5PjAb-.js";function g(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function y(e){const n=[];for(const t of e){const r=new Set;r.add(t.id.trim().toLowerCase()),r.add(t.displayName.replace(/^@/,"").trim().toLowerCase());for(const o of t.mentionPatterns)r.add(o.replace(/^@/,"").trim().toLowerCase());for(const o of r)o&&n.push([o,t.id])}return Object.fromEntries(n)}function b(e){const n=[];for(const t of e){const r=`@${t.displayName}`,o=new Set;o.add(t.id.trim().toLowerCase()),o.add(t.displayName.replace(/^@/,"").trim().toLowerCase());for(const u of t.mentionPatterns)o.add(u.replace(/^@/,"").trim().toLowerCase());for(const u of o)u&&n.push([u,r])}return Object.fromEntries(n)}function _(e){const n=Object.keys(e).sort((r,o)=>o.length-r.length);if(n.length===0)return/(?!)/g;const t=n.map(g).join("|");return new RegExp(`@(${t})(?=$|\\s|[,.:;!?()\\[\\]{}<>,。!?、:;()【】《》「」『』〈〉])`,"gi")}function E(e){return Object.fromEntries(e.map(n=>[n.id,n.color.primary]))}const z="__co-creator__",Y="用户",K="#F5A623",M=["@co-creator","@用户"],Q=Object.entries(A).map(([e,n])=>({id:e,displayName:n.displayName,mentionPatterns:[...n.mentionPatterns],color:{primary:n.color.primary}}));let w=Q,R=[],S=[...M],p=y([]),P=_(p),v=E([]),T=b([]);function q(e){const n=e.map(r=>r.trim()).filter(r=>r.length>0).map(r=>r.startsWith("@")?r:`@${r}`),t=new Set(M);for(const r of n)t.add(r);return[...t]}function C(){const e={id:z,displayName:Y,mentionPatterns:S,color:{primary:K}},n=[...w,...R,e];p=y(n),P=_(p),v=E(n),T=b(n)}C();function L(e){w=e.filter(n=>{var t;return((t=n.roster)==null?void 0:t.available)!==!1}),C()}function ge(e){R=e.map(n=>({id:n.expertId,displayName:n.displayName,mentionPatterns:n.mentionPatterns,color:{primary:U(n.category)}})),C()}function Ce(e){S=q(e),C()}function he(){return P}function Ae(){return p}function ye(){return v}function be(){return T}function U(e){return e?{design:"#FF6B6B",marketing:"#4ECDC4",growth:"#45B7D1",content:"#96CEB4"}[e]??"#7AAEFF":"#7AAEFF"}const X="=== 智能体名称 & 团队 ===",Z="=== AI 模型 & 品牌 ===",J="MCP",V="=== 框架 & 库 ===",ee="=== 工具 & CLI ===",te="=== 项目术语 ===",O={_comment_agents:X,免因:"Codex",面因:"Codex",棉因:"Codex",绵因:"Codex",免疫:"Codex",先罗:"Gemini",暹逻:"Gemini",仙罗:"Gemini",暄罗:"Gemini",产屎官:"用户",铲史官:"用户",铲是官:"用户",不偶:"Claude",献献:"宪宪",先先:"宪宪",嫌嫌:"宪宪",咸咸:"宪宪",现现:"宪宪",弦弦:"宪宪",险险:"宪宪",闲闲:"宪宪",严严:"砚砚",言言:"砚砚",烟烟:"砚砚",眼眼:"砚砚",艳艳:"砚砚",雁雁:"砚砚",燕燕:"砚砚",研研:"砚砚",岩岩:"砚砚",_comment_models:Z,icp:J,克劳德:"Claude",科德斯:"Codex",科迪克斯:"Codex",奥普斯:"Opus",欧普斯:"Opus",桑奈特:"Sonnet",索奈特:"Sonnet",海酷:"Haiku",嗨库:"Haiku",杰米尼:"Gemini",杰明尼:"Gemini",安索皮克:"Anthropic",_comment_frameworks:V,法式的:"Fastify",法斯特发一:"Fastify",为的:"void",那的js:"Node.js","type script":"TypeScript",组单的:"Zustand",锐的死:"Redis",瑞迪斯:"Redis",威士伯:"Whisper",泰尔温:"Tailwind",泰欧温德:"Tailwind",太温的:"Tailwind",优维康:"uvicorn",尤维肯:"uvicorn",_comment_tools:ee,"cloud cold":"Claude Code","cloud code":"Claude Code",QQ面试:"Claude Code",克劳德code:"Claude Code",克劳德cold:"Claude Code","work tree":"worktree","re base":"rebase","fast api":"FastAPI","web socket":"WebSocket","web sockets":"WebSocket",_comment_project:te,亨德赛特:"Hindsight",海恩赛特:"Hindsight",海因赛特:"Hindsight"};function N(e){return Object.entries(e).filter(([n])=>!n.startsWith("_comment")).map(([n,t])=>[new RegExp(g(n),"gi"),t])}const I=N(O);function _e(e){if(e.length===0)return[...I];const n={};for(const[t,r]of Object.entries(O))t.startsWith("_comment")||(n[t.toLowerCase()]=r);for(const{from:t,to:r}of e)t.trim()&&(n[t.toLowerCase()]=r);return N(n)}const ne=I;function k(e){return e.length===0?/(?!)/g:new RegExp(`(^|\\s)(?:at|艾特|@\\s*[。。\\..])\\s*(?:咱的|我的)?\\s*(${e.map(g).join("|")})(?=$|\\s|[,.:;!?()\\[\\]{}<>,。!?、:;()【】《》「」『』〈〉])`,"gi")}const re=Array.from(new Set(Object.values(A).flatMap(e=>e.mentionPatterns.map(n=>n.replace(/^@/,""))))).sort((e,n)=>n.length-e.length);let x=k(re);function F(e){const n=Array.from(new Set(e.flatMap(t=>t.mentionPatterns.map(r=>r.replace(/^@/,""))))).sort((t,r)=>r.length-t.length);x=k(n)}function oe(e){return e.replace(x,(n,t,r)=>`${t}@${r}`)}function se(e,n){let t=e;for(const[r,o]of n??ne)t=t.replace(r,o);return t}const ae=["就是说","然后呢","对对对","那个","就是","嗯","啊"],ie=new RegExp(ae.map(g).join("|"),"g");function ce(e){return e.replace(ie," ").replace(/\s+/g," ").trim()}function Ee(e,n){return ce(oe(se(e,n)))}let l=null,d=null;const h=new Set,le=3,de=1e4;function j(e){for(const n of h)n(e)}function m(){return Object.values(A).map(e=>({id:e.id,displayName:e.displayName,nickname:e.nickname,color:{primary:e.color.primary,secondary:e.color.secondary},mentionPatterns:[...e.mentionPatterns],breedId:void 0,provider:e.provider,defaultModel:e.defaultModel,avatar:e.avatar,roleDescription:e.roleDescription,personality:e.personality,teamStrengths:e.teamStrengths,caution:e.caution,strengths:e.strengths?[...e.strengths]:void 0,sessionChain:e.sessionChain,roster:null,source:"seed",creationSource:e.creationSource,expert:!1}))}async function D(){try{const e=await H("/api/agents");if(!e.ok)return{agents:m(),fromApi:!1};const n=await e.json(),t=Array.isArray(n==null?void 0:n.agents)?ue(n.agents):null;return t?{agents:t,fromApi:!0}:{agents:m(),fromApi:!1}}catch{return{agents:m(),fromApi:!1}}}function ue(e){return e.map(n=>{const t=n;return{...t,id:t.id??"",displayName:t.displayName??t.id??"",color:t.color??{primary:"#000000",secondary:"#ffffff"},mentionPatterns:Array.isArray(t.mentionPatterns)?t.mentionPatterns:[],accountRef:t.accountRef??t.providerProfileId,provider:t.provider??"openai",defaultModel:t.defaultModel??"",imageModel:t.imageModel??void 0,imageAccountRef:t.imageAccountRef??void 0,avatar:t.avatar??"",roleDescription:t.roleDescription??"",personality:t.personality??"",embeddedAcpExecutablePath:t.embeddedAcpExecutablePath,embeddedAcpConfig:t.embeddedAcpConfig,teamStrengths:t.teamStrengths,caution:t.caution,strengths:Array.isArray(t.strengths)?t.strengths:void 0,sessionChain:t.sessionChain,roster:t.roster??null,source:t.source??"seed",creationSource:t.creationSource,expert:t.expert??!1,embeddedRuntimeKind:t.embeddedRuntimeKind,skills:Array.isArray(t.skills)?t.skills:void 0}})}async function me(){l=null,d=D();const e=await d;return e.fromApi?l=e.agents:d=null,L(e.agents),F(e.agents),j(e.agents),e}function Me(){const[e,n]=c.useState(()=>l??m()),[t,r]=c.useState(!l),[o,u]=c.useState(0);c.useEffect(()=>{const s=a=>{n(a),r(!1)};return h.add(s),()=>{h.delete(s)}},[]),c.useEffect(()=>{if(l){n(l),r(!1);return}d||(d=D());let s=!1,a;return d.then(({agents:i,fromApi:f})=>{f?l=i:(d=null,o<le&&(a=setTimeout(()=>{s||u(W=>W+1)},de))),L(i),F(i),j(i),s||(n(i),r(!1))}),()=>{s=!0,clearTimeout(a)}},[o]);const $=c.useMemo(()=>async()=>{r(!0);const s=await me();return n(s.agents),r(!1),s.agents},[]),B=c.useMemo(()=>{const s=new Map(e.map(a=>[a.id,a]));return a=>s.get(a)},[e]),G=c.useMemo(()=>()=>{const s=new Map;for(const a of e){const i=a.breedId??a.id,f=s.get(i)??[];f.push(a),s.set(i,f)}return s},[e]);return{agents:e,isLoading:t,getAgentById:B,getAgentsByBreed:G,refresh:$}}function we(e){return e.variantLabel?`${e.displayName}(${e.variantLabel})`:e.displayName}function Re(){return l??m()}export{he as a,Ae as b,O as c,ye as d,be as e,we as f,Re as g,Ee as h,ge as i,_e as m,Ce as r,Me as u};
2
+ //# sourceMappingURL=useAgentData-D-k9cXfg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAgentData-D-k9cXfg.js","sources":["../../../shared/src/text-utils.ts","../../src/lib/mention-highlight.ts","../../src/utils/transcription-corrector.ts","../../src/hooks/useAgentData.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * Escape regexp metacharacters in a literal string.\n */\nexport function escapeRegExp(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * F32-b Phase 3: Mention highlighting data — refreshable from API.\n *\n * Initializes from static OFFICE_CLAW_CONFIGS (zero-load working state).\n * After useAgentData fetches /api/agents, calls refreshMentionData() to rebuild\n * regex with all agents (including dynamically added ones).\n */\n\nimport { OFFICE_CLAW_CONFIGS, escapeRegExp } from '@hualinge/relay-shared';\nimport type { AgentData } from '@/hooks/useAgentData';\n\n// ── Internal builders ───────────────────────────────────\n\nfunction buildMentionAliasToAgentId(\n agents: Array<{ id: string; displayName: string; mentionPatterns: string[] }>,\n): Record<string, string> {\n const pairs: Array<[string, string]> = [];\n for (const agent of agents) {\n const aliases = new Set<string>();\n aliases.add(agent.id.trim().toLowerCase());\n aliases.add(agent.displayName.replace(/^@/, '').trim().toLowerCase());\n for (const pattern of agent.mentionPatterns) {\n aliases.add(pattern.replace(/^@/, '').trim().toLowerCase());\n }\n for (const alias of aliases) {\n if (!alias) continue;\n pairs.push([alias, agent.id]);\n }\n }\n return Object.fromEntries(pairs);\n}\n\nfunction buildMentionLabel(\n agents: Array<{ id: string; mentionPatterns: string[]; displayName: string }>,\n): Record<string, string> {\n const pairs: Array<[string, string]> = [];\n for (const agent of agents) {\n const label = `@${agent.displayName}`;\n const aliases = new Set<string>();\n aliases.add(agent.id.trim().toLowerCase());\n aliases.add(agent.displayName.replace(/^@/, '').trim().toLowerCase());\n for (const pattern of agent.mentionPatterns) {\n aliases.add(pattern.replace(/^@/, '').trim().toLowerCase());\n }\n for (const alias of aliases) {\n if (!alias) continue;\n pairs.push([alias, label]);\n }\n }\n return Object.fromEntries(pairs);\n}\n\nfunction buildMentionRe(aliasToAgentId: Record<string, string>): RegExp {\n const aliases = Object.keys(aliasToAgentId).sort((a, b) => b.length - a.length);\n if (aliases.length === 0) return /(?!)/g; // never-match fallback\n const pattern = aliases.map(escapeRegExp).join('|');\n // Boundary chars aligned with backend AgentRouter.parseMentions\n return new RegExp(`@(${pattern})(?=$|\\\\s|[,.:;!?()\\\\[\\\\]{}<>,。!?、:;()【】《》「」『』〈〉])`, 'gi');\n}\n\nfunction buildMentionColor(agents: Array<{ id: string; color: { primary: string } }>): Record<string, string> {\n return Object.fromEntries(agents.map((agent) => [agent.id, agent.color.primary]));\n}\n\n// ── Co-Creator (用户) ───────────────────────────────────\nconst CO_CREATOR_ID = '__co-creator__';\nconst CO_CREATOR_DISPLAY_NAME = '用户';\nconst CO_CREATOR_COLOR = '#F5A623'; // warm gold\nconst DEFAULT_CO_CREATOR_MENTION_PATTERNS = ['@co-creator', '@用户'];\n\n// ── Module-level cache (starts from static OFFICE_CLAW_CONFIGS) ─\n\nconst staticMentionAgents = Object.entries(OFFICE_CLAW_CONFIGS).map(([id, c]) => ({\n id,\n displayName: c.displayName,\n mentionPatterns: [...c.mentionPatterns],\n color: { primary: c.color.primary },\n}));\n\n// Include co-creator as synthetic entry so @用户 highlights gold\nlet _mentionAgents = staticMentionAgents;\nlet _threadExpertAgents: Array<{ id: string; displayName: string; mentionPatterns: string[]; color: { primary: string } }> = [];\nlet _coCreatorMentionPatterns = [...DEFAULT_CO_CREATOR_MENTION_PATTERNS];\nlet _mentionAliasToAgentId = buildMentionAliasToAgentId([]);\nlet _mentionRe = buildMentionRe(_mentionAliasToAgentId);\nlet _mentionColor = buildMentionColor([]);\nlet _mentionLabel = buildMentionLabel([]);\n\nfunction normalizeCoCreatorMentionPatterns(mentionPatterns: readonly string[]): string[] {\n const normalized = mentionPatterns\n .map((pattern) => pattern.trim())\n .filter((pattern) => pattern.length > 0)\n .map((pattern) => (pattern.startsWith('@') ? pattern : `@${pattern}`));\n const unique = new Set(DEFAULT_CO_CREATOR_MENTION_PATTERNS);\n for (const pattern of normalized) unique.add(pattern);\n return [...unique];\n}\n\nfunction rebuildMentionCache(): void {\n const ownerEntry = {\n id: CO_CREATOR_ID,\n displayName: CO_CREATOR_DISPLAY_NAME,\n mentionPatterns: _coCreatorMentionPatterns,\n color: { primary: CO_CREATOR_COLOR },\n };\n const all = [..._mentionAgents, ..._threadExpertAgents, ownerEntry];\n _mentionAliasToAgentId = buildMentionAliasToAgentId(all);\n _mentionRe = buildMentionRe(_mentionAliasToAgentId);\n _mentionColor = buildMentionColor(all);\n _mentionLabel = buildMentionLabel(all);\n}\n\nrebuildMentionCache();\n\n// ── Public API ──────────────────────────────────────────\n\n/** Called once by useAgentData after API fetch succeeds.\n * Filters out disabled members (roster.available === false) so they don't highlight. */\nexport function refreshMentionData(agents: AgentData[]): void {\n _mentionAgents = agents.filter((agent) => agent.roster?.available !== false);\n rebuildMentionCache();\n}\n\nexport function refreshThreadExpertMentionData(\n experts: Array<{\n expertId: string;\n displayName: string;\n mentionPatterns: string[];\n category?: string;\n }>,\n): void {\n _threadExpertAgents = experts.map((expert) => ({\n id: expert.expertId,\n displayName: expert.displayName,\n mentionPatterns: expert.mentionPatterns,\n color: { primary: getExpertColor(expert.category) },\n }));\n rebuildMentionCache();\n}\n\nexport function refreshCoCreatorMentionData(mentionPatterns: readonly string[]): void {\n _coCreatorMentionPatterns = normalizeCoCreatorMentionPatterns(mentionPatterns);\n rebuildMentionCache();\n}\n\n/** Get the current mention regex (refreshed after API load) */\nexport function getMentionRe(): RegExp {\n return _mentionRe;\n}\n\n/** Map mention alias (lowercase, no @) → agentId */\nexport function getMentionToAgentId(): Record<string, string> {\n return _mentionAliasToAgentId;\n}\n\n/** Map agentId → primary color hex (e.g. \"#9B7EBD\") */\nexport function getMentionColor(): Record<string, string> {\n return _mentionColor;\n}\n\n/** Map mention alias (lowercase, no @) → rendered label (e.g. \"@办公助理\") */\nexport function getMentionLabel(): Record<string, string> {\n return _mentionLabel;\n}\n\nexport function resetMentionDataForTest(): void {\n _mentionAgents = staticMentionAgents;\n _threadExpertAgents = [];\n _coCreatorMentionPatterns = [...DEFAULT_CO_CREATOR_MENTION_PATTERNS];\n rebuildMentionCache();\n}\n\nfunction getExpertColor(category?: string): string {\n const colors: Record<string, string> = {\n design: '#FF6B6B',\n marketing: '#4ECDC4',\n growth: '#45B7D1',\n content: '#96CEB4',\n };\n return category ? (colors[category] ?? '#7AAEFF') : '#7AAEFF';\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * Transcription corrector for voice input.\n *\n * ASR engines frequently misrecognize project-specific terms\n * (e.g. \"MCP\" → \"ICP\", \"Fastify\" → \"法式的\"). This module\n * provides a three-layer pipeline:\n * 1. Term dictionary replacement (case-insensitive)\n * 2. Chinese filler-word removal\n * 3. Whitespace collapse + trim\n */\n\nimport { OFFICE_CLAW_CONFIGS, escapeRegExp } from '@hualinge/relay-shared';\nimport terms from './voice-terms.json';\n\nexport type TermEntry = readonly [RegExp, string];\n\n/* ------------------------------------------------------------------ */\n/* 1. Term dictionary */\n/* ------------------------------------------------------------------ */\n\nfunction buildTermEntries(dict: Record<string, string>): TermEntry[] {\n return Object.entries(dict)\n .filter(([k]) => !k.startsWith('_comment'))\n .map(([pattern, replacement]) => [new RegExp(escapeRegExp(pattern), 'gi'), replacement]);\n}\n\nconst builtInEntries: ReadonlyArray<TermEntry> = buildTermEntries(terms as Record<string, string>);\n\n/**\n * Merge built-in terms with user-defined custom terms (custom wins).\n * Keys are normalized to lowercase before merging so that custom \"ICP\"\n * correctly overrides built-in \"icp\" (regex matching is case-insensitive).\n */\nexport function mergeTermEntries(customTerms: ReadonlyArray<{ from: string; to: string }>): TermEntry[] {\n if (customTerms.length === 0) return [...builtInEntries];\n // Build lowercase-keyed dict from built-in terms\n const merged: Record<string, string> = {};\n for (const [k, v] of Object.entries(terms as Record<string, string>)) {\n if (!k.startsWith('_comment')) merged[k.toLowerCase()] = v;\n }\n // Custom terms override using lowercase key\n for (const { from, to } of customTerms) {\n if (from.trim()) merged[from.toLowerCase()] = to;\n }\n return buildTermEntries(merged);\n}\n\n// Keep backward-compatible module-level entries for existing callers\nconst termEntries: ReadonlyArray<TermEntry> = builtInEntries;\n\n// ── Refreshable speech mention aliases ──────────────────\nfunction buildSpeechMentionPattern(aliases: string[]): RegExp {\n if (aliases.length === 0) return /(?!)/g; // never-match fallback\n return new RegExp(\n `(^|\\\\s)(?:at|艾特|@\\\\s*[。。\\\\..])\\\\s*(?:咱的|我的)?\\\\s*(${aliases.map(escapeRegExp).join('|')})(?=$|\\\\s|[,.:;!?()\\\\[\\\\]{}<>,。!?、:;()【】《》「」『』〈〉])`,\n 'gi',\n );\n}\n\nconst staticAliases = Array.from(\n new Set(\n Object.values(OFFICE_CLAW_CONFIGS).flatMap((config) => config.mentionPatterns.map((pattern) => pattern.replace(/^@/, ''))),\n ),\n).sort((a, b) => b.length - a.length);\n\nlet _speechMentionPattern = buildSpeechMentionPattern(staticAliases);\n\n/** Refresh speech mention aliases from dynamic agent data (called by useAgentData) */\nexport function refreshSpeechAliases(agents: Array<{ mentionPatterns: string[] }>): void {\n const aliases = Array.from(new Set(agents.flatMap((agent) => agent.mentionPatterns.map((p) => p.replace(/^@/, ''))))).sort(\n (a, b) => b.length - a.length,\n );\n _speechMentionPattern = buildSpeechMentionPattern(aliases);\n}\n\n/**\n * Normalize voice-recognized mention prefix:\n * \"at 砚砚\" / \"艾特 宪宪\" → \"@砚砚\" / \"@宪宪\"\n */\nexport function normalizeSpeechMentions(text: string): string {\n return text.replace(_speechMentionPattern, (_match, prefix: string, alias: string) => `${prefix}@${alias}`);\n}\n\n/**\n * Replace known misrecognized terms with their correct forms.\n * Matching is case-insensitive; unknown terms pass through unchanged.\n * Pass custom entries to override/extend the built-in dictionary.\n */\nexport function applyTermDictionary(text: string, entries?: ReadonlyArray<TermEntry>): string {\n let result = text;\n for (const [re, replacement] of entries ?? termEntries) {\n result = result.replace(re, replacement);\n }\n return result;\n}\n\n/* ------------------------------------------------------------------ */\n/* 2. Filler removal */\n/* ------------------------------------------------------------------ */\n\n/**\n * Chinese filler / hedge words that add no semantic value in a\n * technical instruction context.\n */\nconst FILLERS = ['就是说', '然后呢', '对对对', '那个', '就是', '嗯', '啊'];\n\nconst fillerPattern = new RegExp(FILLERS.map(escapeRegExp).join('|'), 'g');\n\n/**\n * Remove common Chinese filler words, then collapse consecutive\n * whitespace and trim.\n */\nexport function removeFillers(text: string): string {\n return text.replace(fillerPattern, ' ').replace(/\\s+/g, ' ').trim();\n}\n\n/* ------------------------------------------------------------------ */\n/* 3. Full pipeline */\n/* ------------------------------------------------------------------ */\n\n/**\n * End-to-end correction: term dictionary → mention normalization → filler removal.\n * Pass merged entries (from mergeTermEntries) to use custom terms.\n */\nexport function correctTranscription(text: string, entries?: ReadonlyArray<TermEntry>): string {\n return removeFillers(normalizeSpeechMentions(applyTermDictionary(text, entries)));\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\n/**\n * F32-b Phase 3: Central hook for dynamic agent data from /api/agents.\n * Fetches once per session, caches module-level. All consumers share same data.\n * Falls back to static OFFICE_CLAW_CONFIGS from @hualinge/relay-shared during initial load.\n */\n\nimport { OFFICE_CLAW_CONFIGS } from '@hualinge/relay-shared';\nimport { useEffect, useMemo, useState } from 'react';\nimport { refreshMentionData } from '@/lib/mention-highlight';\nimport { apiFetch } from '@/utils/api-client';\nimport { refreshSpeechAliases } from '@/utils/transcription-corrector';\n\nexport interface AgentData {\n id: string;\n name?: string;\n displayName: string;\n nickname?: string;\n color: { primary: string; secondary: string };\n mentionPatterns: string[];\n breedId?: string;\n accountRef?: string;\n /** Legacy compatibility while older runtime data is migrated. */\n providerProfileId?: string;\n provider: string;\n defaultModel: string;\n imageModel?: string;\n imageAccountRef?: string;\n commandArgs?: string[];\n cliConfigArgs?: string[];\n ocProviderName?: string;\n embeddedAcpExecutablePath?: string;\n embeddedAcpConfig?: {\n executablePath?: string;\n args?: string[];\n cwd?: string;\n env?: Record<string, string>;\n provider?: 'openai_compatible' | 'bigmodel' | 'minimax' | 'echo';\n baseUrl?: string;\n apiKey?: string;\n headers?: Record<string, string>;\n sslVerify?: boolean | null;\n temperature?: number;\n topP?: number;\n maxTokens?: number;\n contextWindow?: number;\n connectTimeoutSeconds?: number;\n };\n contextBudget?: {\n maxPromptTokens: number;\n maxContextTokens: number;\n maxMessages: number;\n maxContentLengthPerMsg: number;\n };\n avatar: string;\n roleDescription: string;\n personality: string;\n teamStrengths?: string;\n caution?: string | null;\n strengths?: string[];\n sessionChain?: boolean;\n /** F32-b P4: Human-readable variant label (e.g. \"4.5\", \"Sonnet\") */\n variantLabel?: string;\n /** F32-b P4: Whether this is the default variant for its breed */\n isDefaultVariant?: boolean;\n /** F32-b P4: Breed-level display name (e.g. \"办公智能体\"), for group headings */\n breedDisplayName?: string;\n /** F127: Seed agents come from office-claw-template.json; runtime agents are added later */\n source: 'seed' | 'runtime';\n /** Optional creation provenance for runtime-created agents. */\n creationSource?: 'experts-plaza';\n /** Preset experts are hidden from the generic mention list and shown per thread. */\n expert?: boolean;\n embeddedRuntimeKind?: 'agentteams_acp';\n /** 技能白名单配置 */\n skills?: string[];\n /** F127: Roster metadata used by Hub ownership/lead markers */\n roster?: {\n family: string;\n roles: string[];\n lead: boolean;\n available: boolean;\n evaluation: string;\n } | null;\n}\n\n// ── Module-level cache ──────────────────────────────────\nlet _cached: AgentData[] | null = null;\nlet _fetchPromise: Promise<FetchResult> | null = null;\nconst _listeners = new Set<(agents: AgentData[]) => void>();\nconst MAX_RETRIES = 3;\nconst RETRY_DELAY_MS = 10_000;\n\nfunction notifyListeners(agents: AgentData[]): void {\n for (const listener of _listeners) {\n listener(agents);\n }\n}\n\nfunction buildFallbackAgents(): AgentData[] {\n return Object.values(OFFICE_CLAW_CONFIGS).map((c) => ({\n id: c.id as string,\n displayName: c.displayName,\n nickname: c.nickname,\n color: { primary: c.color.primary, secondary: c.color.secondary },\n mentionPatterns: [...c.mentionPatterns],\n breedId: undefined,\n provider: c.provider,\n defaultModel: c.defaultModel,\n avatar: c.avatar,\n roleDescription: c.roleDescription,\n personality: c.personality,\n teamStrengths: c.teamStrengths,\n caution: c.caution,\n strengths: c.strengths ? [...c.strengths] : undefined,\n sessionChain: c.sessionChain,\n roster: null,\n source: 'seed',\n creationSource: c.creationSource,\n expert: false,\n }));\n}\n\ninterface FetchResult {\n agents: AgentData[];\n fromApi: boolean;\n}\n\nasync function fetchAgents(): Promise<FetchResult> {\n try {\n const res = await apiFetch('/api/agents');\n if (!res.ok) return { agents: buildFallbackAgents(), fromApi: false };\n const data = await res.json();\n const agents = Array.isArray(data?.agents) ? normalizeAgents(data.agents) : null;\n return agents ? { agents, fromApi: true } : { agents: buildFallbackAgents(), fromApi: false };\n } catch {\n return { agents: buildFallbackAgents(), fromApi: false };\n }\n}\n\nfunction normalizeAgents(rawAgents: unknown[]): AgentData[] {\n return rawAgents.map((raw) => {\n const agent = raw as Partial<AgentData>;\n return {\n ...agent,\n id: agent.id ?? '',\n displayName: agent.displayName ?? agent.id ?? '',\n color: agent.color ?? { primary: '#000000', secondary: '#ffffff' },\n mentionPatterns: Array.isArray(agent.mentionPatterns) ? agent.mentionPatterns : [],\n accountRef: agent.accountRef ?? agent.providerProfileId,\n provider: agent.provider ?? 'openai',\n defaultModel: agent.defaultModel ?? '',\n imageModel: agent.imageModel ?? undefined,\n imageAccountRef: agent.imageAccountRef ?? undefined,\n avatar: agent.avatar ?? '',\n roleDescription: agent.roleDescription ?? '',\n personality: agent.personality ?? '',\n embeddedAcpExecutablePath: agent.embeddedAcpExecutablePath,\n embeddedAcpConfig: agent.embeddedAcpConfig,\n teamStrengths: agent.teamStrengths,\n caution: agent.caution,\n strengths: Array.isArray(agent.strengths) ? agent.strengths : undefined,\n sessionChain: agent.sessionChain,\n roster: agent.roster ?? null,\n source: agent.source ?? 'seed',\n creationSource: agent.creationSource,\n expert: agent.expert ?? false,\n embeddedRuntimeKind: agent.embeddedRuntimeKind,\n skills: Array.isArray(agent.skills) ? agent.skills : undefined,\n };\n });\n}\n\nasync function refreshAgentsNow(): Promise<FetchResult> {\n _cached = null;\n _fetchPromise = fetchAgents();\n const result = await _fetchPromise;\n if (result.fromApi) {\n _cached = result.agents;\n } else {\n _fetchPromise = null;\n }\n refreshMentionData(result.agents);\n refreshSpeechAliases(result.agents);\n notifyListeners(result.agents);\n return result;\n}\n\n// ── Hook ────────────────────────────────────────────────\n\nexport function useAgentData() {\n const [agents, setAgents] = useState<AgentData[]>(() => _cached ?? buildFallbackAgents());\n const [isLoading, setIsLoading] = useState(!_cached);\n const [retryCount, setRetryCount] = useState(0);\n\n useEffect(() => {\n const listener = (nextAgents: AgentData[]) => {\n setAgents(nextAgents);\n setIsLoading(false);\n };\n _listeners.add(listener);\n return () => {\n _listeners.delete(listener);\n };\n }, []);\n\n useEffect(() => {\n if (_cached) {\n setAgents(_cached);\n setIsLoading(false);\n return;\n }\n if (!_fetchPromise) {\n _fetchPromise = fetchAgents();\n }\n let cancelled = false;\n let retryTimer: ReturnType<typeof setTimeout> | undefined;\n _fetchPromise.then(({ agents: result, fromApi }) => {\n if (fromApi) {\n _cached = result;\n } else {\n _fetchPromise = null;\n // Schedule retry for already-mounted hooks (max 3 attempts, 10s apart)\n if (retryCount < MAX_RETRIES) {\n retryTimer = setTimeout(() => {\n if (!cancelled) setRetryCount((c) => c + 1);\n }, RETRY_DELAY_MS);\n }\n }\n refreshMentionData(result);\n refreshSpeechAliases(result);\n notifyListeners(result);\n if (!cancelled) {\n setAgents(result);\n setIsLoading(false);\n }\n });\n return () => {\n cancelled = true;\n clearTimeout(retryTimer);\n };\n }, [retryCount]);\n\n const refresh = useMemo(\n () => async () => {\n setIsLoading(true);\n const result = await refreshAgentsNow();\n setAgents(result.agents);\n setIsLoading(false);\n return result.agents;\n },\n [],\n );\n\n const getAgentById = useMemo(() => {\n const map = new Map(agents.map((a) => [a.id, a]));\n return (id: string) => map.get(id);\n }, [agents]);\n\n const getAgentsByBreed = useMemo(() => {\n return () => {\n const groups = new Map<string, AgentData[]>();\n for (const agent of agents) {\n const key = agent.breedId ?? agent.id;\n const arr = groups.get(key) ?? [];\n arr.push(agent);\n groups.set(key, arr);\n }\n return groups;\n };\n }, [agents]);\n\n return {\n agents,\n isLoading,\n getAgentById,\n getAgentsByBreed,\n refresh,\n };\n}\n\n/** Format agent name with optional variant label for multi-variant disambiguation */\nexport function formatAgentName(agent: { displayName: string; variantLabel?: string }): string {\n return agent.variantLabel ? `${agent.displayName}(${agent.variantLabel})` : agent.displayName;\n}\n\n/** Get cached agents synchronously (for non-hook contexts). Returns fallback if not loaded. */\nexport function getCachedAgents(): AgentData[] {\n return _cached ?? buildFallbackAgents();\n}\n\n/** Reset module-level cache (for testing) */\nexport function _resetAgentDataCache(): void {\n _cached = null;\n _fetchPromise = null;\n _listeners.clear();\n}\n"],"names":["escapeRegExp","text","buildMentionAliasToAgentId","agents","pairs","agent","aliases","pattern","alias","buildMentionLabel","label","buildMentionRe","aliasToAgentId","a","b","buildMentionColor","CO_CREATOR_ID","CO_CREATOR_DISPLAY_NAME","CO_CREATOR_COLOR","DEFAULT_CO_CREATOR_MENTION_PATTERNS","staticMentionAgents","OFFICE_CLAW_CONFIGS","id","c","_mentionAgents","_threadExpertAgents","_coCreatorMentionPatterns","_mentionAliasToAgentId","_mentionRe","_mentionColor","_mentionLabel","normalizeCoCreatorMentionPatterns","mentionPatterns","normalized","unique","rebuildMentionCache","ownerEntry","all","refreshMentionData","_a","refreshThreadExpertMentionData","experts","expert","getExpertColor","refreshCoCreatorMentionData","getMentionRe","getMentionToAgentId","getMentionColor","getMentionLabel","category","buildTermEntries","dict","k","replacement","builtInEntries","terms","mergeTermEntries","customTerms","merged","v","from","to","termEntries","buildSpeechMentionPattern","staticAliases","config","_speechMentionPattern","refreshSpeechAliases","p","normalizeSpeechMentions","_match","prefix","applyTermDictionary","entries","result","re","FILLERS","fillerPattern","removeFillers","correctTranscription","_cached","_fetchPromise","_listeners","MAX_RETRIES","RETRY_DELAY_MS","notifyListeners","listener","buildFallbackAgents","fetchAgents","res","apiFetch","data","normalizeAgents","rawAgents","raw","refreshAgentsNow","useAgentData","setAgents","useState","isLoading","setIsLoading","retryCount","setRetryCount","useEffect","nextAgents","cancelled","retryTimer","fromApi","refresh","useMemo","getAgentById","map","getAgentsByBreed","groups","key","arr","formatAgentName","getCachedAgents"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import{r as u}from"./index-Cb4fQgom.js";function m({enabled:e=!0,onEscape:t}){const r=u.useCallback(f=>{e&&f.key==="Escape"&&(t==null||t())},[e,t]);u.useEffect(()=>{if(!(!e||!t))return document.addEventListener("keydown",r),()=>document.removeEventListener("keydown",r)},[e,t,r])}export{m as u};
2
+ //# sourceMappingURL=useEscapeKey-CEQ6-8GR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEscapeKey-CEQ6-8GR.js","sources":["../../src/hooks/useEscapeKey.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { useCallback, useEffect } from 'react';\n\nexport interface UseEscapeKeyOptions {\n enabled?: boolean;\n onEscape?: () => void;\n}\n\nexport function useEscapeKey({ enabled = true, onEscape }: UseEscapeKeyOptions): void {\n const handleEscape = useCallback(\n (event: KeyboardEvent) => {\n if (enabled && event.key === 'Escape') {\n onEscape?.();\n }\n },\n [enabled, onEscape],\n );\n\n useEffect(() => {\n if (!enabled || !onEscape) return;\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [enabled, onEscape, handleEscape]);\n}\n"],"names":["useEscapeKey","enabled","onEscape","handleEscape","useCallback","event","useEffect"],"mappings":"wCAaO,SAASA,EAAa,CAAE,QAAAC,EAAU,GAAM,SAAAC,GAAuC,CACpF,MAAMC,EAAeC,EAAAA,YAClBC,GAAyB,CACpBJ,GAAWI,EAAM,MAAQ,WAC3BH,GAAA,MAAAA,IAEJ,EACA,CAACD,EAASC,CAAQ,CAAA,EAGpBI,EAAAA,UAAU,IAAM,CACd,GAAI,GAACL,GAAW,CAACC,GAEjB,gBAAS,iBAAiB,UAAWC,CAAY,EAC1C,IAAM,SAAS,oBAAoB,UAAWA,CAAY,CACnE,EAAG,CAACF,EAASC,EAAUC,CAAY,CAAC,CACtC"}
@@ -0,0 +1,2 @@
1
+ import{r as i}from"./index-Cb4fQgom.js";import{a as x}from"./OverflowTooltip-CE5PjAb-.js";const f={insight:{primary:"#9B59B6",secondary:"#EDE0F5"},finance:{primary:"#3498DB",secondary:"#D8EFF8"},product:{primary:"#E67E22",secondary:"#FDEBD0"},business:{primary:"#2ECC71",secondary:"#D8F7E4"},office:{primary:"#95A5A6",secondary:"#E8EAED"}};let a=null,o=null;const p=new Set;function l(r){for(const t of p)t(r)}function E(r){return r.map(t=>{const e=t;return{expertId:e.expertId??"",displayName:e.displayName??e.expertId??"",nickname:e.nickname,avatar:e.avatar??"",color:f[e.category??"office"]??f.office,category:e.category??"office",mentionPatterns:Array.isArray(e.mentionPatterns)?e.mentionPatterns:[],roleDescription:e.roleDescription??"",personality:e.personality,skills:Array.isArray(e.skills)?e.skills:void 0,defaultModel:e.defaultModel,providerProfileId:e.providerProfileId}})}async function u(){try{const r=await x("/api/experts");if(!r||typeof r.ok!="boolean")return{experts:[],fromApi:!1};if(!r.ok)return{experts:[],fromApi:!1};const t=await r.json();return{experts:Array.isArray(t==null?void 0:t.experts)?E(t.experts):[],fromApi:!0}}catch{return{experts:[],fromApi:!1}}}async function A(){a=null,o=u();const r=await o;return r.fromApi?a=r.experts:o=null,l(r.experts),r}function D(){const[r,t]=i.useState(()=>a??[]),[e,c]=i.useState(!a);i.useEffect(()=>{const s=n=>{t(n),c(!1)};return p.add(s),()=>{p.delete(s)}},[]),i.useEffect(()=>{if(a){t(a),c(!1);return}o||(o=u());let s=!1;return o.then(({experts:n,fromApi:m})=>{m?a=n:o=null,l(n),s||(t(n),c(!1))}),()=>{s=!0}},[]);const y=i.useMemo(()=>async()=>{c(!0);const s=await A();return t(s.experts),c(!1),s.experts},[]),d=i.useMemo(()=>{const s=new Map(r.map(n=>[n.expertId,n]));return n=>s.get(n)},[r]);return{experts:r,isLoading:e,refresh:y,getExpertById:d}}export{D as u};
2
+ //# sourceMappingURL=useExpertCatalog-BZdw1CYs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useExpertCatalog-BZdw1CYs.js","sources":["../../src/hooks/useExpertCatalog.ts"],"sourcesContent":["/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useEffect, useMemo, useState } from 'react';\nimport { apiFetch } from '@/utils/api-client';\nimport type { AgentData } from './useAgentData';\n\nexport interface ExpertCatalogItem {\n expertId: string;\n displayName: string;\n nickname?: string;\n avatar: string;\n color: { primary: string; secondary: string };\n category: string;\n mentionPatterns: string[];\n roleDescription: string;\n personality?: string;\n skills?: string[];\n defaultModel?: string;\n providerProfileId?: string;\n}\n\nconst EXPERT_CATEGORY_COLORS: Record<string, { primary: string; secondary: string }> = {\n insight: { primary: '#9B59B6', secondary: '#EDE0F5' },\n finance: { primary: '#3498DB', secondary: '#D8EFF8' },\n product: { primary: '#E67E22', secondary: '#FDEBD0' },\n business: { primary: '#2ECC71', secondary: '#D8F7E4' },\n office: { primary: '#95A5A6', secondary: '#E8EAED' },\n};\n\ninterface FetchResult {\n experts: ExpertCatalogItem[];\n fromApi: boolean;\n}\n\nlet _cached: ExpertCatalogItem[] | null = null;\nlet _fetchPromise: Promise<FetchResult> | null = null;\nconst _listeners = new Set<(experts: ExpertCatalogItem[]) => void>();\n\nfunction notifyListeners(experts: ExpertCatalogItem[]): void {\n for (const listener of _listeners) {\n listener(experts);\n }\n}\n\nfunction normalizeExperts(rawExperts: unknown[]): ExpertCatalogItem[] {\n return rawExperts.map((raw) => {\n const expert = raw as Partial<ExpertCatalogItem> & { expertId?: string; category?: string };\n return {\n expertId: expert.expertId ?? '',\n displayName: expert.displayName ?? expert.expertId ?? '',\n nickname: expert.nickname,\n avatar: expert.avatar ?? '',\n color: EXPERT_CATEGORY_COLORS[expert.category ?? 'office'] ?? EXPERT_CATEGORY_COLORS.office,\n category: expert.category ?? 'office',\n mentionPatterns: Array.isArray(expert.mentionPatterns) ? expert.mentionPatterns : [],\n roleDescription: expert.roleDescription ?? '',\n personality: expert.personality,\n skills: Array.isArray(expert.skills) ? expert.skills : undefined,\n defaultModel: expert.defaultModel,\n providerProfileId: expert.providerProfileId,\n };\n });\n}\n\nasync function fetchExperts(): Promise<FetchResult> {\n try {\n const res = await apiFetch('/api/experts');\n if (!res || typeof (res as Response).ok !== 'boolean') return { experts: [], fromApi: false };\n if (!res.ok) return { experts: [], fromApi: false };\n const data = await res.json();\n const experts = Array.isArray(data?.experts) ? normalizeExperts(data.experts) : [];\n return { experts, fromApi: true };\n } catch {\n return { experts: [], fromApi: false };\n }\n}\n\nasync function refreshExpertsNow(): Promise<FetchResult> {\n _cached = null;\n _fetchPromise = fetchExperts();\n const result = await _fetchPromise;\n if (result.fromApi) {\n _cached = result.experts;\n } else {\n _fetchPromise = null;\n }\n notifyListeners(result.experts);\n return result;\n}\n\nexport function useExpertCatalog() {\n const [experts, setExperts] = useState<ExpertCatalogItem[]>(() => _cached ?? []);\n const [isLoading, setIsLoading] = useState(!_cached);\n\n useEffect(() => {\n const listener = (nextExperts: ExpertCatalogItem[]) => {\n setExperts(nextExperts);\n setIsLoading(false);\n };\n _listeners.add(listener);\n return () => {\n _listeners.delete(listener);\n };\n }, []);\n\n useEffect(() => {\n if (_cached) {\n setExperts(_cached);\n setIsLoading(false);\n return;\n }\n if (!_fetchPromise) {\n _fetchPromise = fetchExperts();\n }\n let cancelled = false;\n _fetchPromise.then(({ experts: result, fromApi }) => {\n if (fromApi) {\n _cached = result;\n } else {\n _fetchPromise = null;\n }\n notifyListeners(result);\n if (!cancelled) {\n setExperts(result);\n setIsLoading(false);\n }\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n const refresh = useMemo(\n () => async () => {\n setIsLoading(true);\n const result = await refreshExpertsNow();\n setExperts(result.experts);\n setIsLoading(false);\n return result.experts;\n },\n [],\n );\n\n const getExpertById = useMemo(() => {\n const map = new Map(experts.map((expert) => [expert.expertId, expert]));\n return (expertId: string) => map.get(expertId);\n }, [experts]);\n\n return {\n experts,\n isLoading,\n refresh,\n getExpertById,\n };\n}\n\nexport function getCachedExperts(): ExpertCatalogItem[] {\n return _cached ?? [];\n}\n\nexport function expertToAgentData(expert: ExpertCatalogItem): AgentData {\n return {\n id: expert.expertId,\n name: expert.displayName,\n displayName: expert.displayName,\n nickname: expert.nickname?.trim() || undefined,\n color: expert.color,\n mentionPatterns: [...expert.mentionPatterns],\n breedId: expert.category,\n accountRef: expert.providerProfileId,\n providerProfileId: expert.providerProfileId,\n provider: 'relayclaw',\n defaultModel: expert.defaultModel ?? 'glm-5',\n avatar: expert.avatar,\n roleDescription: expert.roleDescription,\n personality: expert.personality ?? '',\n skills: expert.skills,\n source: 'runtime',\n expert: true,\n roster: {\n family: expert.category,\n roles: [],\n lead: false,\n available: true,\n evaluation: 'preset expert',\n },\n };\n}\n\nexport function _resetExpertCatalogCache(): void {\n _cached = null;\n _fetchPromise = null;\n _listeners.clear();\n}\n"],"names":["EXPERT_CATEGORY_COLORS","_cached","_fetchPromise","_listeners","notifyListeners","experts","listener","normalizeExperts","rawExperts","raw","expert","fetchExperts","res","apiFetch","data","refreshExpertsNow","result","useExpertCatalog","setExperts","useState","isLoading","setIsLoading","useEffect","nextExperts","cancelled","fromApi","refresh","useMemo","getExpertById","map","expertId"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import"./index-Cb4fQgom.js";function t(n){var s;const i=((s=n.split(".").pop())==null?void 0:s.toLowerCase())??"";return i==="pdf"?"/icons/files-pdf.svg":i==="doc"||i==="docx"?"/icons/files-docx.svg":i==="xls"||i==="xlsx"||i==="xlsm"||i==="xlsb"?"/icons/files-xlsx.svg":i==="ppt"||i==="pptx"?"/icons/files-ppt.svg":i==="md"?"/icons/file-md.svg":i==="csv"?"/icons/files-csv.svg":i==="txt"||i==="text"?"/icons/files-txt.svg":i==="html"||i==="htm"?"/icons/file-html.svg":i==="py"||i==="python"?"/icons/file-py.svg":i==="json"?"/icons/file-json.svg":i==="ini"||i==="cfg"||i==="conf"?"/icons/file-ini.svg":i==="sh"||i==="bash"||i==="zsh"?"/icons/file-sh.svg":i==="gitignore"?"/icons/file-gitignore.svg":i==="zip"||i==="rar"||i==="7z"||i==="tar"||i==="gz"?"/icons/file-zip.svg":"/icons/file.svg"}export{t as g};
2
+ //# sourceMappingURL=usePromptBlocks-5sz8Qh51.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePromptBlocks-5sz8Qh51.js","sources":["../../src/hooks/usePromptBlocks.ts"],"sourcesContent":["/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { useMemo } from 'react';\nimport { parsePromptTemplate, type ParsedPrompt } from '@/utils/promptParser';\n\n/**\n * Hook to parse prompt template into blocks\n */\nexport function usePromptBlocks(template: string | null): ParsedPrompt | null {\n return useMemo(() => {\n if (!template) return null;\n return parsePromptTemplate(template);\n }, [template]);\n}\n\n/**\n * Get file type icon based on file extension\n */\nexport function getFileTypeIcon(fileName: string): string {\n const ext = fileName.split('.').pop()?.toLowerCase() ?? '';\n\n if (ext === 'pdf') return '/icons/files-pdf.svg';\n if (ext === 'doc' || ext === 'docx') return '/icons/files-docx.svg';\n if (ext === 'xls' || ext === 'xlsx' || ext === 'xlsm' || ext === 'xlsb') return '/icons/files-xlsx.svg';\n if (ext === 'ppt' || ext === 'pptx') return '/icons/files-ppt.svg';\n if (ext === 'md') return '/icons/file-md.svg';\n if (ext === 'csv') return '/icons/files-csv.svg';\n if (ext === 'txt' || ext === 'text') return '/icons/files-txt.svg';\n if (ext === 'html' || ext === 'htm') return '/icons/file-html.svg';\n if (ext === 'py' || ext === 'python') return '/icons/file-py.svg';\n if (ext === 'json') return '/icons/file-json.svg';\n if (ext === 'ini' || ext === 'cfg' || ext === 'conf') return '/icons/file-ini.svg';\n if (ext === 'sh' || ext === 'bash' || ext === 'zsh') return '/icons/file-sh.svg';\n if (ext === 'gitignore') return '/icons/file-gitignore.svg';\n if (ext === 'zip' || ext === 'rar' || ext === '7z' || ext === 'tar' || ext === 'gz') return '/icons/file-zip.svg';\n\n return '/icons/file.svg';\n}"],"names":["getFileTypeIcon","fileName","ext","_a"],"mappings":"4BAqBO,SAASA,EAAgBC,EAA0B,OACxD,MAAMC,IAAMC,EAAAF,EAAS,MAAM,GAAG,EAAE,IAAA,IAApB,YAAAE,EAA2B,gBAAiB,GAExD,OAAID,IAAQ,MAAc,uBACtBA,IAAQ,OAASA,IAAQ,OAAe,wBACxCA,IAAQ,OAASA,IAAQ,QAAUA,IAAQ,QAAUA,IAAQ,OAAe,wBAC5EA,IAAQ,OAASA,IAAQ,OAAe,uBACxCA,IAAQ,KAAa,qBACrBA,IAAQ,MAAc,uBACtBA,IAAQ,OAASA,IAAQ,OAAe,uBACxCA,IAAQ,QAAUA,IAAQ,MAAc,uBACxCA,IAAQ,MAAQA,IAAQ,SAAiB,qBACzCA,IAAQ,OAAe,uBACvBA,IAAQ,OAASA,IAAQ,OAASA,IAAQ,OAAe,sBACzDA,IAAQ,MAAQA,IAAQ,QAAUA,IAAQ,MAAc,qBACxDA,IAAQ,YAAoB,4BAC5BA,IAAQ,OAASA,IAAQ,OAASA,IAAQ,MAAQA,IAAQ,OAASA,IAAQ,KAAa,sBAErF,iBACT"}
@@ -0,0 +1 @@
1
+ ._container_1wioq_15{--card-radius: 12px;--card-height: 194px;--card-min-width: 205px;--card-max-width: 300px;--card-gap: 16px;background-color:var(--picker-container-bg);display:flex;flex-direction:column;padding:24px;height:100%;min-height:0}._tabSection_1wioq_31{flex:1}._tabRow_1wioq_35{position:relative;display:flex;align-items:center}._searchSection_1wioq_41{flex-shrink:0;margin-top:16px}._cardGrid_1wioq_46{flex:1 1 auto;min-height:0;overflow-y:auto;padding-right:4px;max-height:calc(var(--card-height) * 2 + var(--card-gap));margin-top:16px}@media(max-height:700px){._cardGrid_1wioq_46{max-height:var(--card-height)}}._grid_1wioq_63{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width),1fr));gap:var(--card-gap)}._closeBtn_1wioq_71{position:absolute;right:0;top:50%;transform:translateY(-50%);display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;border-radius:6px;border:none;background:transparent;color:var(--text-muted);cursor:pointer;transition:color .15s ease,background-color .15s ease}._closeBtn_1wioq_71:hover{color:var(--text-primary);background-color:var(--surface-hover-muted)}._card_1wioq_46{position:relative;border-radius:var(--card-radius);background:var(--picker-card-bg);overflow:hidden;border:1px solid var(--picker-border);height:var(--card-height);width:100%;max-width:var(--card-max-width);transition:box-shadow .15s ease,background-color .15s ease,border-color .15s ease}._card_1wioq_46:hover{box-shadow:var(--card-hover-shadow);border-color:var(--picker-hover-border, #1476FF)}._cardSelected_1wioq_116{border-color:var(--picker-hover-border, #1476FF)}._cardDisabled_1wioq_120{cursor:not-allowed;opacity:.6}._previewContainer_1wioq_125{position:absolute;right:-116px;top:44px;width:290px;border-radius:12px;overflow:hidden;pointer-events:none;transform:rotate(-5deg)}._previewImage_1wioq_136{width:100%;height:100%;-o-object-fit:cover;object-fit:cover}._cardTitleArea_1wioq_142{position:absolute;top:16px;left:16px;right:16px;text-align:left;display:flex;align-items:center;justify-content:space-between}._cardName_1wioq_153{font-size:var(--font-size-md);color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._cardNameTooltip_1wioq_161{overflow:hidden;min-width:0}._moreMenuBtn_1wioq_167{flex-shrink:0;opacity:0;transition:opacity .15s ease}._card_1wioq_46:hover ._moreMenuBtn_1wioq_167{opacity:1}._cardAction_1wioq_179{position:absolute;bottom:16px;left:50%;transform:translate(-50%);opacity:0;pointer-events:none;transition:opacity .15s ease;z-index:1}._card_1wioq_46:hover ._cardAction_1wioq_179{opacity:1;pointer-events:auto}._cardActionBtn_1wioq_195{height:32px;padding:0 16px;border-radius:8px;border:none;font-size:14px;font-weight:500;cursor:pointer;white-space:nowrap;display:flex;align-items:center}._uploadCard_1wioq_210{position:relative;border-radius:var(--card-radius);background:var(--button-default-bg);overflow:hidden;cursor:pointer;transition:box-shadow .15s ease,background-color .15s ease;border:1px dashed var(--picker-border);height:var(--card-height);width:100%;max-width:var(--card-max-width)}._uploadCard_1wioq_210:hover{box-shadow:var(--card-hover-shadow)}._uploadCardDragOver_1wioq_229{border-style:dashed;border-color:var(--accent-primary);background-color:var(--surface-selected)}._uploadCardDisabled_1wioq_235{cursor:not-allowed;opacity:.6}._uploadCardDisabled_1wioq_235:hover{box-shadow:none}._uploadContent_1wioq_244{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;height:100%;padding:16px}._uploadIcon_1wioq_254{color:var(--text-muted);width:16px;height:16px}._uploadText_1wioq_260{font-size:var(--font-size-md);color:var(--text-primary);text-align:center}._uploadHint_1wioq_266{font-size:var(--font-size-sm, 12px);color:var(--text-label-secondary);text-align:center}._uploadCardFull_1wioq_273{grid-column:1 / -1;height:var(--card-height);max-width:none;width:100%}._uploadCardFull_1wioq_273 ._uploadContent_1wioq_244{height:100%}._loadingCard_1wioq_286{position:relative;border-radius:var(--card-radius);background-image:url(/images/ppt-preview/placeholder-main.webp);background-size:300%;background-position:center center;background-repeat:no-repeat;overflow:hidden;cursor:not-allowed;opacity:.8;border:1px solid var(--picker-border);height:var(--card-height);width:100%;max-width:var(--card-max-width);padding:16px}._loadingLabel_1wioq_303{font-size:var(--font-size-sm, 12px);color:#191919}._failedCard_1wioq_308{background-color:var(--picker-card-bg);background-image:none;background-size:cover;background-position:center;opacity:1;padding:16px;overflow:hidden;border:1px solid var(--picker-border)}._failedTitleArea_1wioq_319{display:flex;align-items:center;justify-content:space-between;gap:8px}._failedNameArea_1wioq_326{display:flex;align-items:center;gap:4px;flex:1;overflow:hidden;min-width:0}._failedNameTooltip_1wioq_335{display:flex;align-items:center;flex-shrink:1;overflow:hidden;min-width:0}._failedErrorIcon_1wioq_343{flex-shrink:0;width:16px;height:16px}._failedInfoIcon_1wioq_349{flex-shrink:0;width:16px;height:16px;color:var(--picker-failed-info-icon-color);cursor:pointer}._failedName_1wioq_326{flex-shrink:1;min-width:0;font-size:var(--font-size-md);color:var(--text-primary);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}._failedDeleteBtn_1wioq_367{flex-shrink:0;cursor:pointer;display:flex;align-items:center;color:var(--text-secondary);transition:color .15s ease}._failedDeleteBtn_1wioq_367:hover{color:var(--state-error-text)}._failedDeleteIcon_1wioq_380{width:16px;height:16px;color:var(--text-secondary)}._emptyState_1wioq_388{grid-column:1 / -1;display:flex;align-items:center;justify-content:center;padding:32px 0;color:var(--text-muted);font-size:var(--font-size-md)}