@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":"useSocket-y3-zWhVL.js","sources":["../../../shared/src/agent-error-transform.ts","../../src/utils/promptParser.ts","../../src/components/ChatEmptyState.tsx","../../src/shared/constants.ts","../../src/components/chat-input/components/rich-textarea-token-rendering.ts","../../src/stores/placeholderStore.ts","../../src/hooks/useInspirationTemplate.ts","../../src/hooks/usePathCompletion.ts","../../src/stores/inputHistoryStore.ts","../../src/components/experts-panel/hooks/useInvitedExpertsForThread.ts","../../src/components/chat-input/components/ChatDragUploadOverlay.tsx","../../src/components/chat-input/hooks/useBottomLeftControls.ts","../../src/components/chat-input/hooks/useSkillMenuInput.ts","../../src/components/chat-input/components/SkillMenuPanel.tsx","../../src/components/icons/GuidedModeIcon.tsx","../../src/components/chat-input/components/ChatInputSkillControls.tsx","../../src/components/chat-input/components/ChatInputBottomLeft.tsx","../../src/stores/voiceSettingsStore.ts","../../src/hooks/useVoiceInput.ts","../../src/components/icons/LoadingIcon.tsx","../../src/components/icons/MicIcon.tsx","../../src/components/icons/RotatingBorderStopIcon.tsx","../../src/components/icons/SendIcon.tsx","../../src/components/icons/StopRecordingIcon.tsx","../../src/components/chat-input/components/ChatInputActionButton.tsx","../../src/components/chat-input/hooks/useBottomRightActions.ts","../../src/components/chat-input/components/ChatInputBottomRight.tsx","../../src/components/chat-input/hooks/useMentionMenuInput.ts","../../src/components/chat-input/components/ChatInputMenus.tsx","../../src/utils/queue-inline-segments.ts","../../src/components/Lightbox.tsx","../../src/components/chat-input/components/ImagePreview.tsx","../../src/components/chat-input/components/icons/QueueEditIcon.tsx","../../src/components/chat-input/components/icons/QueueTopIcon.tsx","../../src/components/chat-input/components/icons/QueueDeleteIcon.tsx","../../src/components/chat-input/components/ChatInputQueuePanel.tsx","../../src/components/chat-input/components/HistorySearchModal.tsx","../../src/components/chat-input/components/PathCompletionMenu.tsx","../../src/components/chat-input/components/QuickActionsPanel.tsx","../../src/components/chat-input/hooks/usePromptBlockKeyboardNavigation.ts","../../src/hooks/usePlaceholderFileUpload.ts","../../src/components/chat-input/components/FilePlaceholderBlock.tsx","../../src/components/chat-input/components/TextPlaceholderBlock.tsx","../../src/components/chat-input/components/RichTextareaPromptBlocks.tsx","../../src/components/chat-input/components/RichTextarea.tsx","../../src/components/shared/Dropdown.tsx","../../src/components/shared/PromptDialog.tsx","../../src/components/chat-input/components/TemplatePicker.tsx","../../src/components/chat-input/components/ChatInputLayout.tsx","../../src/components/chat-input/chat-input-upload-state.ts","../../src/components/chat-input/hooks/useAttachmentManager.ts","../../src/components/chat-input/hooks/useChatInputInputFlow.ts","../../src/components/chat-input/hooks/useChatInputKeyboard.ts","../../src/components/chat-input/hooks/useChatInputMenus.ts","../../src/components/chat-input/hooks/useQuickActions.ts","../../src/components/chat-input/hooks/useChatInputSendFlow.ts","../../src/components/chat-input/hooks/useChatInputTemplateFlow.ts","../../src/components/chat-input/hooks/useCloseMenusCoordinator.ts","../../src/components/chat-input/hooks/useDraftSync.ts","../../src/components/chat-input/hooks/useHistorySuggestionSync.ts","../../src/components/chat-input/hooks/useMentionMenuPositioning.ts","../../src/components/chat-input/hooks/useMentionSkillActions.ts","../../src/components/chat-input/hooks/usePanelMenuCoordinator.ts","../../src/components/chat-input/hooks/usePanelSearchFill.ts","../../src/components/chat-input/hooks/usePendingChatInsertSync.ts","../../src/components/chat-input/hooks/useQueueEditDraftManager.ts","../../src/components/chat-input/hooks/useQueueManager.ts","../../src/components/chat-input/hooks/useSkillOptionsSource.ts","../../src/components/chat-input/hooks/useTemplateMode.ts","../../src/components/chat-input/hooks/useWorkspaceMenu.ts","../../src/components/chat-input/ChatInput.tsx","../../src/utils/desktop-notification.ts","../../src/hooks/thread-live-refresh.ts","../../src/hooks/agent-error-fallback.ts","../../src/hooks/scheduler-placeholder.ts","../../src/components/ppt-studio/ppt-studio-types.ts","../../src/hooks/parse-system-info.ts","../../src/hooks/useSocket-background-system-info.ts","../../src/hooks/useSocket-background.ts","../../src/hooks/useSocket-persistence.ts","../../src/services/PlaybackManager.ts","../../src/stores/voiceSessionStore.ts","../../src/hooks/useVoiceStream.ts","../../src/hooks/useSocket.ts"],"sourcesContent":["/*\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nexport const MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE = 'ModelArts.81011';\nexport const MODEL_ARTS_RATE_LIMIT_ERROR_CODE = 'ModelArts.81101';\nexport const APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE = 'APIG.0308';\nconst MODEL_ARTS_SENSITIVE_INPUT_MESSAGE_FRAGMENT = 'Input text May contain sensitive information';\nconst MODEL_ARTS_RATE_LIMIT_MESSAGE = '当前请求较多,模型暂时限流,请稍后重试。';\nconst INSUFFICIENT_QUOTA_MESSAGE = '当前模型额度或账单余额不足,暂时无法处理请求。请检查账户配额/余额后再试。';\nconst CONTEXT_LENGTH_MESSAGE = '这次输入内容超出模型上下文长度限制。请精简内容或新开会话后重试。';\nconst AUTH_ERROR_MESSAGE = '模型服务鉴权失败(如 API Key 无效、过期或权限不足)。请检查凭据配置后重试。';\nconst SERVICE_UNAVAILABLE_MESSAGE = '模型服务当前繁忙或暂不可用,请稍后重试。';\nconst DAILY_QUOTA_EXHAUSTED_MESSAGE = `您好,截至目前您今日的免费模型使用额度已用尽。\n如需继续使用服务,可选择[购买](https://console.huaweicloud.com/modelarts/?region=cn-southwest-2#/model-studio/deployment)华为云MaaS模型服务进行接入;或于次日再次访问,系统将为您重置免费额度。`;\nconst STREAM_CONNECTION_ERROR_MESSAGE = '响应中断了,可能因为电脑休眠或网络不稳定。请稍后重试。';\n\n// LLM 流式连接错误特征码\nconst STREAM_ERROR_PATTERNS = ['openAI API async stream error', '[181001]', 'async stream error'];\n\nexport type ErrorFallbackKind =\n | 'timeout' // 响应超时\n | 'connection' // 连接失败\n | 'config' // 配置错误\n | 'abrupt_exit' // CLI 异常退出\n | 'max_iterations' // 达到最大迭代次数\n | 'rate_limit' // 模型瞬时限流\n | 'daily_quota' // 当日额度耗尽\n | 'insufficient_quota' // 账号配额/余额不足\n | 'context_length' // 上下文长度超限\n | 'auth' // 鉴权失败\n | 'service_unavailable' // 服务繁忙或不可用\n | 'sensitive_input' // 敏感词校验\n | 'stream_error' // LLM 流式连接中断\n | 'unknown'; // 未分类错误\n\nexport interface ErrorFallbackMetadata {\n v: 1;\n kind: ErrorFallbackKind;\n rawError: string;\n timestamp: number;\n serial?: string;\n}\n\n/**\n * 生成错误序列号,格式: E-MMdd-HHmm-xxxx\n * 用于用户报错时运维快速定位原始错误日志。\n */\nexport function generateErrorSerial(): string {\n const now = new Date();\n const datePart = [\n String(now.getMonth() + 1).padStart(2, '0'),\n String(now.getDate()).padStart(2, '0'),\n ].join('');\n const timePart = [\n String(now.getHours()).padStart(2, '0'),\n String(now.getMinutes()).padStart(2, '0'),\n ].join('');\n const rand = ((Math.random() * 0x10000) | 0).toString(16).padStart(4, '0');\n return `E-${datePart}-${timePart}-${rand}`;\n}\n\nexport interface ErrorLike {\n agentId?: string;\n error?: string;\n errorCode?: string;\n metadata?: { provider?: string; model?: string };\n}\n\nfunction normalizeQuotedText(rawError: string): string {\n return rawError.replace(/['']/g, \"'\").replace(/[\"\"]/g, '\"');\n}\n\nfunction matchesGenericRateLimit(normalizedError: string): boolean {\n return (\n /\\b429\\b/.test(normalizedError) ||\n /too many requests/i.test(normalizedError) ||\n /rate[\\s_-]*limit(ed|ing)?/i.test(normalizedError) ||\n /toomanyrequests/i.test(normalizedError) ||\n /限流|请求过于频繁|请求较多/.test(normalizedError)\n );\n}\n\nexport function isSensitiveInputError(msg: ErrorLike | string): boolean {\n if (typeof msg === 'string') {\n const normalized = normalizeQuotedText(msg);\n return (\n normalized.includes(MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE) &&\n normalized.toLowerCase().includes(MODEL_ARTS_SENSITIVE_INPUT_MESSAGE_FRAGMENT.toLowerCase())\n );\n }\n if (msg.errorCode === MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE) return true;\n const rawError = msg.error?.trim();\n if (!rawError) return false;\n const normalized = normalizeQuotedText(rawError);\n return (\n normalized.includes(MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE) &&\n normalized.toLowerCase().includes(MODEL_ARTS_SENSITIVE_INPUT_MESSAGE_FRAGMENT.toLowerCase())\n );\n}\n\nexport function isRateLimitError(msg: ErrorLike | string): boolean {\n if (typeof msg === 'string') {\n const normalized = normalizeQuotedText(msg);\n if (isDailyQuotaExhaustedError(normalized)) return false;\n return normalized.includes(MODEL_ARTS_RATE_LIMIT_ERROR_CODE) || matchesGenericRateLimit(normalized);\n }\n\n if (msg.errorCode === APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE) return false;\n if (msg.errorCode === MODEL_ARTS_RATE_LIMIT_ERROR_CODE) return true;\n\n const rawError = msg.error?.trim();\n if (!rawError) return false;\n const normalized = normalizeQuotedText(rawError);\n if (isDailyQuotaExhaustedError(normalized)) return false;\n return normalized.includes(MODEL_ARTS_RATE_LIMIT_ERROR_CODE) || matchesGenericRateLimit(normalized);\n}\n\nexport function isDailyQuotaExhaustedError(msg: ErrorLike | string): boolean {\n if (typeof msg === 'string') {\n const normalized = normalizeQuotedText(msg);\n return normalized.includes(APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE);\n }\n if (msg.errorCode === APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE) return true;\n const rawError = msg.error?.trim();\n if (!rawError) return false;\n const normalized = normalizeQuotedText(rawError);\n return normalized.includes(APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE);\n}\n\nfunction isTimeoutError(rawError: string): boolean {\n return /响应超时|timed out|timeout/i.test(rawError);\n}\n\nfunction isAbruptExitError(rawError: string): boolean {\n // 排除 \"connection closed unexpectedly\" 因为它应该归类为连接错误\n // 只匹配 CLI 异常退出相关的错误\n return /CLI\\s*异常退出|abnormal exit|exited unexpectedly|subprocess exited/i.test(rawError);\n}\n\nfunction isConnectionError(rawError: string): boolean {\n return /connection failed|connection closed unexpectedly|WebSocket connection closed/i.test(rawError);\n}\n\nfunction isStreamConnectionError(rawError: string): boolean {\n return STREAM_ERROR_PATTERNS.some((p) => rawError.includes(p));\n}\n\nfunction isMaxIterationsReachedError(rawError: string): boolean {\n return /max iterations reached|max_iterations_reached/i.test(rawError);\n}\n\nfunction isHuaweiMaaSSessionError(rawError: string): boolean {\n return /huawei maas session (not found|expired)/i.test(rawError);\n}\n\nfunction isInsufficientQuotaError(rawError: string): boolean {\n return (\n /insufficient[\\s_-]*quota|quota[\\s_-]*exceeded|insufficient[\\s_-]*credit/i.test(rawError) ||\n /billing[\\s_-]*(hard|soft)?[\\s_-]*limit/i.test(rawError) ||\n /额度不足|配额不足|余额不足|账单额度不足/.test(rawError)\n );\n}\n\nfunction isContextLengthError(rawError: string): boolean {\n return (\n /context length|context window|maximum context length|max(?:imum)? tokens?/i.test(rawError) ||\n /prompt (is )?too long|too many tokens/i.test(rawError) ||\n /上下文(长度)?超限|超出.*(上下文|token).*限制/.test(rawError)\n );\n}\n\nfunction isAuthError(rawError: string): boolean {\n return (\n /\\b(401|403)\\b/.test(rawError) ||\n /unauthorized|forbidden|authentication failed|invalid api[\\s_-]*key|access denied|permission denied/i.test(\n rawError,\n ) ||\n /未授权|鉴权失败|权限不足|密钥无效|token无效/.test(rawError)\n );\n}\n\nfunction isServiceUnavailableError(rawError: string): boolean {\n return (\n /\\b(503|529)\\b/.test(rawError) ||\n /service unavailable|server overloaded|model overloaded|temporarily unavailable|upstream overload/i.test(\n rawError,\n ) ||\n /服务繁忙|服务不可用|模型繁忙|系统繁忙|过载/.test(rawError)\n );\n}\n\ntype ConfigurationMatch = {\n pattern: RegExp;\n message: string;\n};\n\nconst CONFIGURATION_MATCHES: ConfigurationMatch[] = [\n {\n pattern: /WebSocket URL is not configured/i,\n message: '当前智能体缺少 WebSocket 地址配置,暂时无法启动。请先配置对应智能体的连接地址后再重试。',\n },\n {\n pattern: /provider profile is not configured|bound provider profile/i,\n message: '当前智能体未绑定可用的 provider profile,暂时无法处理请求。请先检查并绑定正确的 provider profile。',\n },\n {\n pattern: /requires a default model profile|default model profile|model profile is missing/i,\n message: '当前智能体缺少默认 model profile 配置,暂时无法处理请求。请先为对应 provider profile 配置默认模型。',\n },\n {\n pattern: /model profile \".+\" not found or missing apiKey|missing apiKey|API key/i,\n message:\n '当前智能体的模型配置缺少 API Key 或模型档案不存在,暂时无法处理请求。请检查对应 model profile 的 API Key 配置。',\n },\n];\n\nfunction isConfigurationError(rawError: string): boolean {\n return (\n CONFIGURATION_MATCHES.some(({ pattern }) => pattern.test(rawError)) ||\n /not configured|sidecar exited|CLI path/i.test(rawError)\n );\n}\n\nfunction getConfigurationErrorMessage(rawError: string): string {\n const matched = CONFIGURATION_MATCHES.find(({ pattern }) => pattern.test(rawError));\n if (matched) return matched.message;\n return `当前智能体配置存在问题,暂时无法处理这次请求。请检查配置后重试。原始错误:${rawError}`;\n}\n\nexport function classifyError(rawError: string): ErrorFallbackKind {\n if (isDailyQuotaExhaustedError(rawError)) return 'daily_quota';\n if (isInsufficientQuotaError(rawError)) return 'insufficient_quota';\n if (isRateLimitError(rawError)) return 'rate_limit';\n if (isSensitiveInputError(rawError)) return 'sensitive_input';\n if (isContextLengthError(rawError)) return 'context_length';\n if (isAuthError(rawError)) return 'auth';\n if (isServiceUnavailableError(rawError)) return 'service_unavailable';\n if (isTimeoutError(rawError)) return 'timeout';\n if (isAbruptExitError(rawError)) return 'abrupt_exit';\n if (isConfigurationError(rawError)) return 'config';\n if (isStreamConnectionError(rawError)) return 'stream_error';\n if (isConnectionError(rawError)) return 'connection';\n if (isMaxIterationsReachedError(rawError)) return 'max_iterations';\n return 'unknown';\n}\n\nexport function getRateLimitMessage(): string {\n return MODEL_ARTS_RATE_LIMIT_MESSAGE;\n}\n\nexport function getDailyQuotaExhaustedMessage(): string {\n return DAILY_QUOTA_EXHAUSTED_MESSAGE;\n}\n\nexport function getFriendlyAgentErrorMessage(msg: ErrorLike, serial?: string): string {\n let rawError = msg.error?.trim() || 'Unknown error';\n\n // 截断过长的错误消息(统一在共享模块处理)\n const MAX_RAW_ERROR_LENGTH = 1000;\n if (rawError.length > MAX_RAW_ERROR_LENGTH) {\n rawError = rawError.slice(0, MAX_RAW_ERROR_LENGTH) + '... (truncated)';\n }\n\n let message: string;\n\n if (isDailyQuotaExhaustedError(msg)) {\n message = getDailyQuotaExhaustedMessage();\n } else if (isInsufficientQuotaError(rawError)) {\n message = INSUFFICIENT_QUOTA_MESSAGE;\n } else if (isRateLimitError(msg)) {\n message = getRateLimitMessage();\n } else if (isSensitiveInputError(msg)) {\n message = '检测到输入内容触发了敏感词校验。请重新打开一个新会话后再试。';\n } else if (isContextLengthError(rawError)) {\n message = CONTEXT_LENGTH_MESSAGE;\n } else if (isAuthError(rawError)) {\n message = AUTH_ERROR_MESSAGE;\n } else if (isServiceUnavailableError(rawError)) {\n message = SERVICE_UNAVAILABLE_MESSAGE;\n } else if (isTimeoutError(rawError)) {\n message = '这次响应超时了,我先结束本次尝试。请稍后直接重试。';\n } else if (isAbruptExitError(rawError)) {\n message = '这次响应中断了,我没能稳定完成处理。请重试一次;如果连续出现,请稍后再试。';\n } else if (isConfigurationError(rawError)) {\n message = getConfigurationErrorMessage(rawError);\n } else if (isConnectionError(rawError)) {\n message = '当前智能体连接不稳定,暂时无法完成这次处理。请稍后重试;如果持续出现,说明后端服务可能需要检查。';\n } else if (isStreamConnectionError(rawError)) {\n message = STREAM_CONNECTION_ERROR_MESSAGE;\n } else if (isMaxIterationsReachedError(rawError)) {\n message = '已达到本次对话允许的最大思考轮数,任务未在限定的轮数内完成。';\n } else {\n message = '这次处理没有顺利完成。我先结束本次尝试,请稍后重试。';\n }\n\n if (serial) {\n message += `\\n[错误参考号: ${serial}]`;\n }\n return message;\n}\n\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nexport interface TextPlaceholder {\n id: string;\n type: 'text';\n defaultText: string;\n}\n\nexport interface FilePlaceholder {\n id: string;\n type: 'file';\n defaultText: string;\n fileType: string;\n formats: string[];\n}\n\nexport interface FixedBlock {\n type: 'fixed';\n content: string;\n}\n\nexport interface PlaceholderBlock {\n type: 'placeholder';\n placeholder: TextPlaceholder | FilePlaceholder;\n}\n\nexport type PromptBlock = FixedBlock | PlaceholderBlock;\n\nexport interface ParsedPrompt {\n blocks: PromptBlock[];\n placeholderIds: string[];\n}\n\nconst PLACEHOLDER_REGEX = /\\{\\{(file):([^:}]+)(?::([^:}]+))?(?::\\[([^\\]]+)\\])?\\}\\}|\\{\\{([^:}]+)\\}\\}/g;\n\nlet placeholderCounter = 0;\n\nfunction generatePlaceholderId(): string {\n return `ph_${placeholderCounter++}`;\n}\n\n/**\n * 解析模板字符串,识别占位符\n * 支持格式:\n * - {{text:提示文字}} - 文本占位符\n * - {{提示文字}} - 文本占位符(简写)\n * - {{file:提示文字}} - 文件占位符\n * - {{file:提示文字:类型}} - 文件占位符带类型\n * - {{file:提示文字:[png,jpg]}} - 文件占位符带格式\n */\nexport function parsePromptTemplate(template: string): ParsedPrompt {\n placeholderCounter = 0;\n const blocks: PromptBlock[] = [];\n const placeholderIds: string[] = [];\n\n let lastIndex = 0;\n let match: RegExpExecArray | null;\n\n PLACEHOLDER_REGEX.lastIndex = 0;\n\n while ((match = PLACEHOLDER_REGEX.exec(template)) !== null) {\n const matchStart = match.index;\n\n // 添加固定文本块\n if (matchStart > lastIndex) {\n blocks.push({\n type: 'fixed',\n content: template.slice(lastIndex, matchStart),\n });\n }\n\n // 判断匹配到的格式\n if (match[1] === 'file') {\n // {{file:提示文字}} 或 {{file:提示文字:类型}} 或 {{file:提示文字:[png,jpg]}}\n const [, , defaultText, fileType, formatsStr] = match;\n const id = generatePlaceholderId();\n placeholderIds.push(id);\n\n const formats = formatsStr ? formatsStr.split(',').map((f) => f.trim()) : [];\n\n blocks.push({\n type: 'placeholder',\n placeholder: {\n id,\n type: 'file',\n defaultText,\n fileType: fileType || 'document',\n formats,\n },\n });\n } else if (match[5]) {\n // {{提示文字}} - 简写文本占位符\n const defaultText = match[5];\n const id = generatePlaceholderId();\n placeholderIds.push(id);\n\n blocks.push({\n type: 'placeholder',\n placeholder: {\n id,\n type: 'text',\n defaultText,\n },\n });\n }\n\n lastIndex = matchStart + match[0].length;\n }\n\n // 添加最后的固定文本\n if (lastIndex < template.length) {\n blocks.push({\n type: 'fixed',\n content: template.slice(lastIndex),\n });\n } else if (blocks[blocks.length - 1]?.type === 'placeholder') {\n blocks.push({\n type: 'fixed',\n content: '',\n });\n }\n\n return { blocks, placeholderIds };\n}\n\n/**\n * 重置占位符计数器(用于测试)\n */\nexport function resetPlaceholderCounter(): void {\n placeholderCounter = 0;\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\ninterface ChatEmptyStateProps {\n onAgentsClick?: () => void;\n onChannelsClick?: () => void;\n fillAvailableHeight?: boolean;\n}\n\ninterface EmptyStateCard {\n id: 'agents' | 'channels';\n title: string;\n description: string;\n imageSrc: string;\n imageAlt: string;\n}\n\nconst heroCards: EmptyStateCard[] = [\n {\n id: 'agents',\n title: '智能体配置',\n description: '设置智能体人设,让 OfficeClaw 更了解你。',\n imageSrc: '/images/chat-empty-agent.svg',\n imageAlt: '智能体配置',\n },\n {\n id: 'channels',\n title: '一键接入渠道',\n description: '一键接入飞书、微信、钉钉、小艺渠道,无缝推进办公流程。',\n imageSrc: '/images/chat-empty-im.svg',\n imageAlt: '一键接入渠道',\n },\n];\n\nexport function ChatEmptyState({ onAgentsClick, onChannelsClick, fillAvailableHeight = false }: ChatEmptyStateProps) {\n const sectionClassName = fillAvailableHeight ? 'chat-layout-rail' : 'chat-layout-rail min-h-full py-10';\n const contentClassName = fillAvailableHeight\n ? 'mx-auto flex w-full items-center justify-center'\n : 'mx-auto flex min-h-[calc(100vh-21rem)] w-full items-center justify-center';\n\n const handleCardClick = (cardId: EmptyStateCard['id']) => {\n if (cardId === 'agents') {\n onAgentsClick?.();\n return;\n }\n\n onChannelsClick?.();\n };\n\n return (\n <section className={sectionClassName} data-testid=\"chat-empty-state\">\n <div className={contentClassName}>\n <div className=\"w-full text-center\">\n <div className=\"mx-auto max-w-2xl\">\n <h2 className=\"mx-auto flex w-fit flex-wrap items-center justify-center gap-2 text-[34px] font-semibold leading-tight tracking-[-0.03em] text-[var(--text-primary)] sm:text-[36px]\">\n <img\n data-testid=\"chat-empty-officeclaw-logo\"\n src=\"/images/OfficeClaw.svg\"\n alt=\"OfficeClaw\"\n className=\"h-[60px] w-auto shrink-0\"\n />\n </h2>\n <p className=\"mx-auto mt-[8px] max-w-xl text-[16px] font-normal leading-[30px] text-[var(--text-secondary)]\">\n AI深度赋能全场景办公,专家团协作决策,安全高效更懂你\n </p>\n </div>\n\n <div\n className=\"mx-auto mt-10 grid w-full grid-cols-1 gap-6 min-[1280px]:grid-cols-2\"\n data-testid=\"chat-empty-card-grid\"\n >\n {heroCards.map((card) => (\n <button\n key={card.id}\n type=\"button\"\n onClick={() => handleCardClick(card.id)}\n className=\"rounded-[16px] border border-[var(--card-border)] bg-[var(--card-bg)] px-6 py-6 text-left transition-[transform,border-color,background-color,box-shadow] duration-200 hover:-translate-y-0.5 hover:border-[var(--card-hover-border)] hover:bg-[var(--card-hover-bg)] hover:shadow-[var(--card-hover-shadow)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--text-accent)] focus-visible:ring-offset-2 focus-visible:ring-offset-[var(--surface-panel)]\"\n data-testid={`chat-empty-card-${card.id}`}\n >\n <div className=\"flex items-start gap-4\">\n <div className=\"flex h-14 w-14 shrink-0 items-center justify-center rounded-2xl bg-[var(--surface-panel)]\">\n <img src={card.imageSrc} alt={card.imageAlt} className=\"h-14 w-14 object-contain\" />\n </div>\n <div className=\"min-w-0\">\n <h3 className=\"text-base font-semibold text-[var(--text-primary)]\">{card.title}</h3>\n <p className=\"mt-2 text-sm leading-6 text-[var(--text-label-secondary)]\">{card.description}</p>\n </div>\n </div>\n </button>\n ))}\n </div>\n </div>\n </div>\n </section>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport const MAIN_PANEL_MIN_WIDTH = 544;\n","import { getMentionToAgentId } from '@/lib/mention-highlight';\n\nexport interface RichSkillOption {\n name: string;\n iconUrl?: string | null;\n}\n\nexport interface RichQuickActionOption {\n label: string;\n icon?: string;\n token?: string;\n}\n\nexport type RichTextareaSegment =\n | { type: 'text'; text: string }\n | { type: 'mention'; text: string }\n | { type: 'skill'; text: string; token: string; iconUrl?: string | null }\n | { type: 'quick_action'; text: string; icon?: string; token: string };\n\ntype BuildSegmentsOptions = {\n allowTerminalMention?: boolean;\n};\n\nconst MENTION_RIGHT_WHITESPACE_RE = /\\s/;\nconst SKILL_TOKEN_PREFIX = '[[skill:';\nconst SKILL_TOKEN_SUFFIX = ']]';\nconst QUICK_ACTION_TOKEN_PREFIX = '[[quick_action:';\nconst QUICK_ACTION_TOKEN_SUFFIX = ']]';\n\nexport function isVisuallyEmptyRichTextareaValue(value: string): boolean {\n return value.replace(/[\\s\\u200B-\\u200D\\u2060\\uFEFF]/g, '').length === 0;\n}\n\nfunction createSkillToken(name: string, token: string, iconUrl?: string | null): RichTextareaSegment {\n return { type: 'skill', text: name, token, iconUrl };\n}\n\nfunction createQuickActionToken(label: string, token: string, icon?: string): RichTextareaSegment {\n return { type: 'quick_action', text: label, icon, token };\n}\n\nexport function buildRichTextareaSegments(\n value: string,\n skillOptions: RichSkillOption[],\n quickActionOptions: RichQuickActionOption[],\n options: BuildSegmentsOptions = {},\n): RichTextareaSegment[] {\n if (!value) return [{ type: 'text', text: '' }];\n\n const allowTerminalMention = options.allowTerminalMention ?? false;\n const skillOptionByName = new Map(skillOptions.map((item) => [item.name.trim(), item] as const));\n const quickActionIconByLabel = new Map(quickActionOptions.map((item) => [item.label, item.icon]));\n const mentionToAgentId = getMentionToAgentId();\n const mentionAliases = Object.keys(mentionToAgentId).sort((a, b) => b.length - a.length);\n const segments: RichTextareaSegment[] = [];\n let textBuffer = '';\n let cursor = 0;\n const flushText = () => {\n if (!textBuffer) return;\n segments.push({ type: 'text', text: textBuffer });\n textBuffer = '';\n };\n\n while (cursor < value.length) {\n if (value.startsWith(SKILL_TOKEN_PREFIX, cursor)) {\n const end = value.indexOf(SKILL_TOKEN_SUFFIX, cursor + SKILL_TOKEN_PREFIX.length);\n if (end > cursor) {\n const token = value.slice(cursor, end + SKILL_TOKEN_SUFFIX.length);\n const name = value.slice(cursor + SKILL_TOKEN_PREFIX.length, end).trim();\n if (name) {\n const skill = skillOptionByName.get(name);\n flushText();\n segments.push(createSkillToken(name, token, skill?.iconUrl));\n cursor = end + SKILL_TOKEN_SUFFIX.length;\n continue;\n }\n }\n }\n\n if (value.startsWith(QUICK_ACTION_TOKEN_PREFIX, cursor)) {\n const end = value.indexOf(QUICK_ACTION_TOKEN_SUFFIX, cursor + QUICK_ACTION_TOKEN_PREFIX.length);\n if (end > cursor) {\n const token = value.slice(cursor, end + QUICK_ACTION_TOKEN_SUFFIX.length);\n const label = value.slice(cursor + QUICK_ACTION_TOKEN_PREFIX.length, end);\n flushText();\n segments.push(createQuickActionToken(label, token, quickActionIconByLabel.get(label)));\n cursor = end + QUICK_ACTION_TOKEN_SUFFIX.length;\n continue;\n }\n }\n\n const prev = cursor > 0 ? value[cursor - 1] : ' ';\n if (value[cursor] === '@' && /\\s/.test(prev)) {\n let matched: { text: string; len: number } | null = null;\n for (const alias of mentionAliases) {\n if (!alias) continue;\n const token = `@${alias}`;\n const raw = value.slice(cursor, cursor + token.length);\n if (raw.toLowerCase() !== token.toLowerCase()) continue;\n const next = value[cursor + token.length];\n if (!next) {\n if (!allowTerminalMention) continue;\n } else if (!MENTION_RIGHT_WHITESPACE_RE.test(next)) {\n continue;\n }\n matched = { text: raw, len: token.length };\n break;\n }\n if (matched) {\n flushText();\n segments.push({ type: 'mention', text: matched.text });\n cursor += matched.len;\n continue;\n }\n }\n\n textBuffer += value[cursor] ?? '';\n cursor += 1;\n }\n\n flushText();\n return segments;\n}\n\nexport function serializeRichTextareaNode(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) return (node.textContent ?? '').replace(/\\u00A0/g, ' ');\n if (node.nodeType !== Node.ELEMENT_NODE) return '';\n const el = node as HTMLElement;\n if (el.dataset.tokenType === 'skill' || el.dataset.tokenType === 'quick-action') return el.dataset.tokenValue ?? '';\n let out = '';\n for (const child of Array.from(el.childNodes)) out += serializeRichTextareaNode(child);\n return out;\n}\n\nexport function serializeRichTextareaNodeSignature(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) return `t:${(node.textContent ?? '').replace(/\\u00A0/g, ' ')}`;\n if (node.nodeType !== Node.ELEMENT_NODE) return '';\n const el = node as HTMLElement;\n if (el.dataset.tokenType === 'skill') return `s:${el.dataset.tokenValue ?? ''}`;\n if (el.dataset.tokenType === 'quick-action') return `q:${el.dataset.tokenValue ?? ''}`;\n if (el.dataset.tokenType === 'mention') return `m:${el.textContent ?? ''}`;\n let out = '';\n for (const child of Array.from(el.childNodes)) out += serializeRichTextareaNodeSignature(child);\n return out;\n}\n\nexport function appendRichTextareaSegment(frag: DocumentFragment, segment: RichTextareaSegment): void {\n if (segment.type === 'text') {\n frag.appendChild(document.createTextNode(segment.text));\n return;\n }\n\n if (segment.type === 'mention') {\n const span = document.createElement('span');\n span.setAttribute('data-token-type', 'mention');\n span.className = 'text-[var(--text-accent)]';\n span.textContent = segment.text;\n frag.appendChild(span);\n return;\n }\n\n if (segment.type === 'quick_action') {\n const token = document.createElement('span');\n token.setAttribute('data-token-type', 'quick-action');\n token.setAttribute('data-token-value', segment.token);\n token.setAttribute('contenteditable', 'false');\n token.className =\n 'group/quick-action inline-flex max-w-full cursor-pointer items-center gap-1 rounded-full border text-[14px] font-normal leading-[22px] text-[var(--text-primary)] align-middle';\n token.style.padding = '2px 8px';\n token.style.marginBottom = '2px';\n token.style.borderColor = 'var(--border-accent)';\n token.style.backgroundColor = 'var(--accent-soft)';\n token.style.cursor = 'pointer';\n\n if (segment.icon) {\n const icon = createMaskIconElement(segment.icon,'h-4 w-4 text-[var(--mask-icon)] group-hover/quick-action:hidden');\n token.appendChild(icon);\n } else {\n const fallback = document.createElement('span');\n fallback.setAttribute('aria-hidden', 'true');\n fallback.className = 'h-2 w-2 rounded-full bg-[var(--text-accent)] group-hover/quick-action:hidden';\n token.appendChild(fallback);\n }\n\n const remove = document.createElement('span');\n remove.setAttribute('data-remove-quick-action', '1');\n remove.setAttribute('aria-hidden', 'true');\n remove.className =\n 'hidden h-4 w-4 shrink-0 cursor-pointer items-center justify-center rounded-full text-[var(--text-muted)] group-hover/quick-action:inline-flex hover:text-[var(--text-accent)]';\n remove.style.fontSize = '18px';\n remove.style.lineHeight = '18px';\n remove.style.marginBottom = '2px';\n remove.textContent = '×';\n token.appendChild(remove);\n\n const label = document.createElement('span');\n label.textContent = segment.text;\n token.appendChild(label);\n frag.appendChild(token);\n return;\n }\n\n const token = document.createElement('span');\n token.setAttribute('data-token-type', 'skill');\n token.setAttribute('data-token-value', segment.token);\n token.setAttribute('contenteditable', 'false');\n token.className =\n 'inline-flex max-w-full translate-y-[-1px] items-center gap-1 text-[var(--text-accent)] text-[16px] leading-5 align-middle';\n\n const icon = document.createElement('span');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = 'inline-block h-4 w-4 shrink-0';\n icon.style.backgroundColor = 'currentColor';\n icon.style.maskImage = \"url('/icons/menu/skills.svg')\";\n icon.style.maskRepeat = 'no-repeat';\n icon.style.maskPosition = 'center';\n icon.style.maskSize = 'contain';\n icon.style.webkitMaskImage = \"url('/icons/menu/skills.svg')\";\n icon.style.webkitMaskRepeat = 'no-repeat';\n icon.style.webkitMaskPosition = 'center';\n icon.style.webkitMaskSize = 'contain';\n token.appendChild(icon);\n\n const label = document.createElement('span');\n label.className = 'truncate';\n label.textContent = segment.text;\n token.appendChild(label);\n frag.appendChild(token);\n}\n\nfunction createMaskIconElement(src: string, className: string): HTMLElement {\n const icon = document.createElement('span');\n icon.setAttribute('aria-hidden', 'true');\n icon.className = ['shrink-0 bg-current', className].filter(Boolean).join(' ');\n icon.style.setProperty('-webkit-mask', `url(\"${src}\") center / contain no-repeat`);\n icon.style.setProperty('mask', `url(\"${src}\") center / contain no-repeat`);\n return icon;\n}\n\nexport function renderRichTextareaSegments(root: HTMLElement, segments: RichTextareaSegment[]): void {\n const frag = document.createDocumentFragment();\n for (const segment of segments) {\n appendRichTextareaSegment(frag, segment);\n }\n root.replaceChildren(frag);\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { create } from 'zustand';\nimport { buildInspirationUploadPath } from '@/utils/inspiration-workspace-path';\n\nexport interface FileValue {\n path: string;\n name: string;\n file?: File;\n}\n\ninterface PlaceholderState {\n // placeholderId -> 用户输入的文本内容\n textValues: Record<string, string>;\n // placeholderId -> 已上传的文件信息\n fileValues: Record<string, FileValue>;\n workspacePath: string | null;\n\n setTextValue: (id: string, value: string) => void;\n getTextValue: (id: string) => string;\n setFileValue: (id: string, file: FileValue) => void;\n getFileValue: (id: string) => FileValue | null;\n setWorkspacePath: (path: string | null) => void;\n removeFileValue: (id: string) => void;\n clearPlaceholder: (id: string) => void;\n clearAll: () => void;\n}\n\nexport const usePlaceholderStore = create<PlaceholderState>((set, get) => ({\n textValues: {},\n fileValues: {},\n workspacePath: null,\n\n setTextValue: (id, value) => {\n set((state) => ({\n textValues: {\n ...state.textValues,\n [id]: value,\n },\n }));\n },\n\n getTextValue: (id) => {\n return get().textValues[id] ?? '';\n },\n\n setFileValue: (id, file) => {\n set((state) => ({\n fileValues: {\n ...state.fileValues,\n [id]: file,\n },\n }));\n },\n\n getFileValue: (id) => {\n return get().fileValues[id] ?? null;\n },\n\n setWorkspacePath: (path) => {\n const workspacePath = path?.trim() || null;\n set((state) => {\n const fileEntries = Object.entries(state.fileValues);\n if (fileEntries.length === 0) return { workspacePath };\n\n const fileValues = Object.fromEntries(\n fileEntries.map(([id, file]) => [\n id,\n {\n ...file,\n path: buildInspirationUploadPath(workspacePath ?? '', file.name),\n },\n ]),\n );\n return { workspacePath, fileValues };\n });\n },\n\n removeFileValue: (id) => {\n set((state) => {\n const newFileValues = { ...state.fileValues };\n delete newFileValues[id];\n return { fileValues: newFileValues };\n });\n },\n\n clearPlaceholder: (id) => {\n set((state) => {\n const newTextValues = { ...state.textValues };\n const newFileValues = { ...state.fileValues };\n delete newTextValues[id];\n delete newFileValues[id];\n return { textValues: newTextValues, fileValues: newFileValues };\n });\n },\n\n clearAll: () => {\n set({ textValues: {}, fileValues: {}, workspacePath: null });\n },\n}));\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport type { RefObject } from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { RichTextareaHandle } from '@/components/chat-input/components/RichTextarea';\nimport {\n isVisuallyEmptyRichTextareaValue,\n serializeRichTextareaNode,\n} from '@/components/chat-input/components/rich-textarea-token-rendering';\nimport { useChatStore } from '@/stores/chatStore';\nimport { usePlaceholderStore } from '@/stores/placeholderStore';\nimport { type ParsedPrompt, parsePromptTemplate } from '@/utils/promptParser';\n\nfunction buildPendingTemplateInput(currentInput: string, pendingText: string): string {\n const separator = currentInput && !currentInput.endsWith('\\n') ? '\\n' : '';\n return `${currentInput}${separator}${pendingText}`;\n}\n\nfunction normalizeDeletedTemplateInput(value: string): string {\n return isVisuallyEmptyRichTextareaValue(value) ? '' : value;\n}\n\ninterface UseInspirationTemplateOptions {\n input: string;\n setInput: (next: string | ((prev: string) => string)) => void;\n textareaRef: RefObject<RichTextareaHandle>;\n onSend?: (finalText: string, files: File[]) => void;\n}\n\nexport interface InspirationTemplateState {\n isTemplate: boolean;\n parsed: ParsedPrompt | null;\n activePlaceholderId: string | null;\n setActivePlaceholder: (id: string | null) => void;\n handlePlaceholderFocus: (id: string) => void;\n handlePlaceholderBlur: () => void;\n handlePlaceholderDelete: (id: string) => void;\n handlePlaceholderTabNext: (currentId: string) => void;\n buildSendContent: () => { text: string; files: File[] };\n syncInputFromTemplate: () => void;\n resetTemplate: () => void;\n}\n\n/**\n * Hook to handle inspiration template flow\n * - Detects if current input is a template with placeholders\n * - Manages placeholder focus/edit state\n * - Builds final content for sending\n */\nfunction buildSendContentFromPromptRoot(root: HTMLElement): { text: string; files: File[] } {\n const fileValues = usePlaceholderStore.getState().fileValues;\n let text = '';\n const files: File[] = [];\n\n for (const child of Array.from(root.childNodes)) {\n if (child instanceof Text) {\n text += serializeRichTextareaNode(child);\n continue;\n }\n if (\n child instanceof HTMLElement &&\n child.dataset.placeholderControl === 'true' &&\n child.dataset.placeholderType === 'file'\n ) {\n const placeholderId = child.dataset.placeholderId ?? '';\n const fileValue = fileValues[placeholderId];\n text += fileValue?.path ?? child.getAttribute('data-placeholder') ?? child.textContent ?? '';\n if (fileValue?.file) {\n files.push(fileValue.file);\n }\n continue;\n }\n\n if (\n child instanceof HTMLElement &&\n child.dataset.placeholderControl === 'true' &&\n child.dataset.placeholderType === 'text'\n ) {\n const placeholderId = child.dataset.placeholderId ?? '';\n const textValue = usePlaceholderStore.getState().textValues[placeholderId];\n text += textValue && textValue.length > 0 ? textValue : (child.getAttribute('data-placeholder') ?? '');\n continue;\n }\n\n text += serializeRichTextareaNode(child);\n }\n\n return { text, files };\n}\n\nfunction buildInputFromParsedPrompt(parsed: ParsedPrompt): string {\n const textValues = usePlaceholderStore.getState().textValues;\n const fileValues = usePlaceholderStore.getState().fileValues;\n\n let resultText = '';\n\n for (const block of parsed.blocks) {\n if (block.type === 'fixed') {\n resultText += block.content;\n } else if (block.type === 'placeholder') {\n const placeholder = block.placeholder;\n if (placeholder.type === 'text') {\n const textValue = textValues[placeholder.id];\n resultText += textValue ?? placeholder.defaultText;\n } else if (placeholder.type === 'file') {\n const fileValue = fileValues[placeholder.id];\n resultText += fileValue?.name ?? placeholder.defaultText;\n }\n }\n }\n\n return resultText;\n}\n\nfunction syncFixedBlocksFromPromptRoot(parsed: ParsedPrompt, root: HTMLElement | null): ParsedPrompt {\n if (!root) return parsed;\n\n return {\n placeholderIds: parsed.placeholderIds,\n blocks: parsed.blocks.map((block, index) => {\n if (block.type !== 'fixed') return block;\n const fixedElement = root.querySelector<HTMLElement>(`[data-block-index=\"${index}\"]`);\n if (!fixedElement) return block;\n return {\n ...block,\n content: serializeRichTextareaNode(fixedElement),\n };\n }),\n };\n}\n\nexport function useInspirationTemplate({\n input,\n setInput,\n textareaRef,\n}: UseInspirationTemplateOptions): InspirationTemplateState {\n const pendingChatInsert = useChatStore((s) => s.pendingChatInsert);\n const setPendingChatInsert = useChatStore((s) => s.setPendingChatInsert);\n\n const [activePlaceholderId, setActivePlaceholderId] = useState<string | null>(null);\n const [, bumpParsedVersion] = useState(0);\n const consumedRef = useRef<boolean>(false);\n const pendingRef = useRef(pendingChatInsert);\n const parsedPersistRef = useRef<ParsedPrompt | null>(null);\n\n const commitParsedPrompt = useCallback((nextParsed: ParsedPrompt) => {\n parsedPersistRef.current = nextParsed;\n setActivePlaceholderId((current) => current ?? nextParsed.placeholderIds[0] ?? null);\n bumpParsedVersion((version) => version + 1);\n }, []);\n\n useEffect(() => {\n pendingRef.current = pendingChatInsert;\n }, [pendingChatInsert]);\n\n const templateText = pendingChatInsert?.inspirationData?.prompt ?? pendingChatInsert?.text;\n const insertedTemplateText = pendingChatInsert?.text ?? templateText;\n const inputIsTemplate = Boolean(input?.includes('{{'));\n const isTemplateCandidate = Boolean(templateText?.includes('{{')) || inputIsTemplate;\n\n // Handle re-mount case: when ChatInput remounts (e.g., navigating back to new session),\n // pendingChatInsert may already be null but input still contains template syntax.\n // Re-parse the input to restore placeholder state.\n useEffect(() => {\n if (parsedPersistRef.current) return;\n if (!inputIsTemplate) return;\n\n const newParsed = parsePromptTemplate(input);\n if (newParsed.placeholderIds.length === 0) return;\n commitParsedPrompt(newParsed);\n }, [commitParsedPrompt, input, inputIsTemplate]);\n\n useEffect(() => {\n if (templateText && isTemplateCandidate && !consumedRef.current) {\n const parseSource =\n inputIsTemplate || !insertedTemplateText ? input : buildPendingTemplateInput(input, insertedTemplateText);\n const newParsed = parsePromptTemplate(parseSource);\n commitParsedPrompt(newParsed);\n consumedRef.current = true;\n setPendingChatInsert(null);\n }\n }, [\n commitParsedPrompt,\n input,\n inputIsTemplate,\n insertedTemplateText,\n templateText,\n isTemplateCandidate,\n setPendingChatInsert,\n ]);\n\n useEffect(() => {\n const currentParsed = parsedPersistRef.current;\n if (currentParsed && currentParsed.placeholderIds.length > 0) {\n setActivePlaceholderId(currentParsed.placeholderIds[0]);\n }\n }, []);\n\n const isTemplate = Boolean(parsedPersistRef.current);\n\n useEffect(() => {\n if (!parsedPersistRef.current) return;\n if (!isVisuallyEmptyRichTextareaValue(input)) return;\n\n const root = textareaRef.current?.getElement();\n if (root?.querySelector('[data-placeholder-control=\"true\"]')) return;\n const rootValue = root\n ? Array.from(root.childNodes)\n .map((node) => serializeRichTextareaNode(node))\n .join('')\n : input;\n if (!isVisuallyEmptyRichTextareaValue(rootValue)) return;\n\n parsedPersistRef.current = null;\n consumedRef.current = false;\n setActivePlaceholderId(null);\n usePlaceholderStore.getState().clearAll();\n setInput('');\n bumpParsedVersion((version) => version + 1);\n }, [input, setInput, textareaRef]);\n\n const setActivePlaceholder = useCallback((id: string | null) => {\n setActivePlaceholderId(id);\n }, []);\n\n const handlePlaceholderFocus = useCallback((id: string) => {\n setActivePlaceholderId(id);\n }, []);\n\n const handlePlaceholderBlur = useCallback(() => {\n // Don't blur immediately if there are pending changes\n }, []);\n\n const handlePlaceholderTabNext = useCallback((currentId: string) => {\n const currentParsed = parsedPersistRef.current;\n if (!currentParsed) return;\n const currentIdx = currentParsed.placeholderIds.indexOf(currentId);\n if (currentIdx < currentParsed.placeholderIds.length - 1) {\n setActivePlaceholderId(currentParsed.placeholderIds[currentIdx + 1]);\n }\n }, []);\n\n const syncInputFromTemplate = useCallback(() => {\n const currentParsed = parsedPersistRef.current;\n if (!currentParsed) return;\n\n setInput(buildInputFromParsedPrompt(currentParsed));\n }, [setInput]);\n\n const resetTemplate = useCallback(() => {\n parsedPersistRef.current = null;\n consumedRef.current = false;\n setActivePlaceholderId(null);\n bumpParsedVersion((version) => version + 1);\n }, []);\n\n const handlePlaceholderDelete = useCallback(\n (id: string) => {\n if (activePlaceholderId === id) {\n setActivePlaceholderId(null);\n }\n\n const persistedParsed = parsedPersistRef.current;\n if (!persistedParsed) return;\n const currentParsed = syncFixedBlocksFromPromptRoot(persistedParsed, textareaRef.current?.getElement() ?? null);\n\n const blockIndex = currentParsed.blocks.findIndex(\n (block) => block.type === 'placeholder' && block.placeholder.id === id,\n );\n if (blockIndex < 0) return;\n\n const newBlocks = currentParsed.blocks.filter((_, idx) => idx !== blockIndex);\n const newPlaceholderIds = currentParsed.placeholderIds.filter((pid) => pid !== id);\n\n const nextParsed: ParsedPrompt = {\n blocks: newBlocks,\n placeholderIds: newPlaceholderIds,\n };\n\n usePlaceholderStore.getState().clearPlaceholder(id);\n\n if (newPlaceholderIds.length === 0) {\n const nextInput = normalizeDeletedTemplateInput(buildInputFromParsedPrompt(nextParsed));\n parsedPersistRef.current = null;\n consumedRef.current = false;\n setActivePlaceholderId(null);\n usePlaceholderStore.getState().clearAll();\n setInput(nextInput);\n return;\n }\n\n parsedPersistRef.current = nextParsed;\n setInput(buildInputFromParsedPrompt(nextParsed));\n },\n [activePlaceholderId, setInput, textareaRef],\n );\n\n const buildSendContent = useCallback(() => {\n const currentParsed = parsedPersistRef.current;\n const root = textareaRef.current?.getElement();\n if (!currentParsed || !root) {\n return { text: input, files: [] };\n }\n return buildSendContentFromPromptRoot(root);\n }, [input, textareaRef]);\n\n return {\n isTemplate,\n parsed: parsedPersistRef.current,\n activePlaceholderId,\n setActivePlaceholder,\n handlePlaceholderFocus,\n handlePlaceholderBlur,\n handlePlaceholderDelete,\n handlePlaceholderTabNext,\n buildSendContent,\n syncInputFromTemplate,\n resetTemplate,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * F080-P2: Path completion hook.\n * Detects path patterns in input text and fetches completions from the API.\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { useChatStore } from '@/stores/chatStore';\nimport { apiFetch } from '@/utils/api-client';\n\nexport interface PathEntry {\n name: string;\n path: string;\n isDirectory: boolean;\n}\n\n/** Regex to detect path-like suffixes at end of input */\nconst PATH_PATTERN = /(?:^|\\s)([.~/][\\w/._-]*|packages\\/[\\w/._-]*)$/;\n\nconst DEBOUNCE_MS = 200;\n\nexport function usePathCompletion(input: string) {\n const [entries, setEntries] = useState<PathEntry[]>([]);\n const [isOpen, setIsOpen] = useState(false);\n const [selectedIdx, setSelectedIdx] = useState(0);\n const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const lastPrefixRef = useRef<string>('');\n const cwd = useChatStore((s) => s.currentProjectPath);\n\n const detectPath = useCallback((text: string): string | null => {\n const match = text.match(PATH_PATTERN);\n return match ? match[1] : null;\n }, []);\n\n const isOpenRef = useRef(false);\n\n const close = useCallback(() => {\n setIsOpen(false);\n isOpenRef.current = false;\n setEntries([]);\n setSelectedIdx(0);\n // NOTE: do NOT clear lastPrefixRef — it prevents the effect from\n // re-fetching the same prefix after Esc/select (P1 fix from codex R1)\n }, []);\n\n const selectEntry = useCallback(\n (entry: PathEntry): string => {\n // Replace the path prefix in input with the completed path\n const match = input.match(PATH_PATTERN);\n if (!match) return input;\n const beforePath = input.slice(0, match.index! + (match[0].startsWith(' ') ? 1 : 0));\n const completedName = entry.isDirectory ? entry.name : entry.name;\n // Build the completed prefix: parent path + selected name\n const pathPrefix = match[1];\n const lastSlash = pathPrefix.lastIndexOf('/');\n const parentPart = lastSlash >= 0 ? pathPrefix.slice(0, lastSlash + 1) : '';\n const newText = beforePath + parentPart + completedName;\n // Pre-set lastPrefixRef to the new completed path so the effect\n // won't re-fetch and reopen the menu (P1 fix from codex R1)\n const newPathMatch = newText.match(PATH_PATTERN);\n if (newPathMatch) lastPrefixRef.current = newPathMatch[1];\n close();\n return newText;\n },\n [input, close],\n );\n\n useEffect(() => {\n const pathPrefix = detectPath(input);\n\n if (!pathPrefix) {\n // Abort any in-flight fetch — prevents stale response from reopening\n // the menu after user deletes the path token (cloud review P1 fix)\n abortRef.current?.abort();\n if (timerRef.current) {\n clearTimeout(timerRef.current);\n timerRef.current = null;\n }\n if (isOpenRef.current) close();\n return;\n }\n\n // Don't re-fetch for same prefix (prevents reopen after Esc/select)\n if (pathPrefix === lastPrefixRef.current) return;\n lastPrefixRef.current = pathPrefix;\n\n // Cancel previous\n if (timerRef.current) clearTimeout(timerRef.current);\n abortRef.current?.abort();\n\n timerRef.current = setTimeout(async () => {\n const controller = new AbortController();\n abortRef.current = controller;\n\n try {\n const cwdParam = cwd && cwd !== 'default' ? `&cwd=${encodeURIComponent(cwd)}` : '';\n const res = await apiFetch(\n `/api/projects/complete?prefix=${encodeURIComponent(pathPrefix)}&limit=10${cwdParam}`,\n );\n if (controller.signal.aborted) return;\n if (!res.ok) {\n close();\n return;\n }\n const data = await res.json();\n if (controller.signal.aborted) return;\n const items: PathEntry[] = data.entries ?? [];\n setEntries(items);\n setIsOpen(items.length > 0);\n isOpenRef.current = items.length > 0;\n setSelectedIdx(0);\n } catch {\n if (!controller.signal.aborted) close();\n }\n }, DEBOUNCE_MS);\n\n return () => {\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, [input, cwd, detectPath, close]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n abortRef.current?.abort();\n if (timerRef.current) clearTimeout(timerRef.current);\n };\n }, []);\n\n return {\n entries,\n isOpen,\n selectedIdx,\n setSelectedIdx,\n selectEntry,\n close,\n detectPath,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { create } from 'zustand';\n\nconst STORAGE_KEY = 'office-claw-input-history';\nconst LEGACY_STORAGE_KEY = 'cat-cafe-input-history';\nconst MAX_ENTRIES = 500;\n\nfunction loadEntries(): string[] {\n if (typeof window === 'undefined') return [];\n try {\n let raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) raw = localStorage.getItem(LEGACY_STORAGE_KEY);\n if (!raw) return [];\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n const entries = parsed.filter((item): item is string => typeof item === 'string');\n if (localStorage.getItem(STORAGE_KEY) === null && localStorage.getItem(LEGACY_STORAGE_KEY) !== null && entries.length) {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(entries));\n localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n }\n return entries;\n } catch {\n return [];\n }\n}\n\nfunction saveEntries(entries: string[]): void {\n if (typeof window === 'undefined') return;\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(entries));\n try {\n localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n } catch {\n // localStorage full or unavailable\n }\n}\n\ninterface InputHistoryState {\n entries: string[];\n addEntry: (text: string) => void;\n findMatch: (prefix: string) => string | null;\n search: (query: string) => string[];\n loadFromStorage: () => void;\n clearHistory: () => void;\n}\n\nexport const useInputHistoryStore = create<InputHistoryState>((set, get) => ({\n entries: loadEntries(),\n\n addEntry: (text: string) => {\n const trimmed = text.trim();\n if (!trimmed) return;\n set((state) => {\n const filtered = state.entries.filter((e) => e !== trimmed);\n const next = [trimmed, ...filtered].slice(0, MAX_ENTRIES);\n saveEntries(next);\n return { entries: next };\n });\n },\n\n findMatch: (prefix: string) => {\n if (!prefix) return null;\n const lower = prefix.toLowerCase();\n const { entries } = get();\n for (const entry of entries) {\n if (entry.toLowerCase().startsWith(lower) && entry.toLowerCase() !== lower) {\n return entry;\n }\n }\n return null;\n },\n\n search: (query: string) => {\n if (!query) return [];\n const lower = query.toLowerCase();\n return get().entries.filter((e) => e.toLowerCase().includes(lower));\n },\n\n loadFromStorage: () => {\n set({ entries: loadEntries() });\n },\n\n clearHistory: () => {\n if (typeof window !== 'undefined') {\n try {\n localStorage.removeItem(STORAGE_KEY);\n localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n }\n set({ entries: [] });\n },\n}));\n","import { useEffect, useState } from 'react';\nimport { apiFetch } from '@/utils/api-client';\nimport type { InvitedExpert } from '../types/expert';\n\ninterface UseInvitedExpertsForThreadOptions {\n threadId: string | null;\n}\n\nexport function useInvitedExpertsForThread(options: UseInvitedExpertsForThreadOptions) {\n const { threadId } = options;\n const [invitedExperts, setInvitedExperts] = useState<InvitedExpert[]>([]);\n const [isLoading, setIsLoading] = useState(false);\n\n useEffect(() => {\n if (!threadId) {\n setInvitedExperts([]);\n return;\n }\n\n let cancelled = false;\n setIsLoading(true);\n\n async function fetchInvitedExperts() {\n try {\n const response = await apiFetch(`/api/threads/${threadId}/experts`);\n if (!response.ok) throw new Error('Failed to fetch invited experts');\n const data = await response.json();\n if (!cancelled) {\n setInvitedExperts(data.invitedExperts ?? []);\n }\n } catch (err) {\n console.error('Failed to fetch invited experts:', err);\n if (!cancelled) {\n setInvitedExperts([]);\n }\n } finally {\n if (!cancelled) {\n setIsLoading(false);\n }\n }\n }\n\n void fetchInvitedExperts();\n\n return () => {\n cancelled = true;\n };\n }, [threadId]);\n\n return { invitedExperts, isLoading };\n}","import { createPortal } from 'react-dom';\n\ntype ChatDragUploadOverlayProps = {\n isVisible: boolean;\n host: HTMLElement | null;\n};\n\nexport function ChatDragUploadOverlay({ isVisible, host }: ChatDragUploadOverlayProps) {\n if (!isVisible || !host) return null;\n\n return createPortal(\n <div\n className=\"pointer-events-none absolute inset-0 z-[2147483648]\"\n style={{\n background: 'var(--chat-drag-upload-bg, rgba(255, 255, 255, 0.8))',\n backdropFilter: 'blur(15px)',\n WebkitBackdropFilter: 'blur(15px)',\n }}\n >\n <div\n className=\"absolute inset-[48px] flex items-center justify-center rounded-[40px] border border-dashed\"\n style={{\n borderColor: 'var(--chat-drag-upload-border, rgba(128, 128, 128, 1))',\n }}\n >\n <div className=\"flex flex-col items-center justify-center gap-3 px-6 text-center text-[var(--text-primary)]\">\n <img src=\"/icons/icon-drag-file.svg\" alt=\"\" aria-hidden=\"true\" className=\"h-20 w-20 select-none\" draggable={false} />\n <p className=\"text-[16px] font-bold leading-[19px]\">将附件拖放到此处完成上传</p>\n <p className=\"text-[14px] font-normal leading-[20px] text-[var(--text-secondary)]\">总计最多上传5个附件(每个100MB以内)</p>\n <p className=\"text-[14px] font-normal leading-[20px] text-[var(--text-secondary)]\">支持格式:doc、docx、pdf、txt、xls、xlsx、csv、ppt、pptx</p>\n </div>\n </div>\n </div>,\n host,\n );\n}\n","import { useCallback } from 'react';\nimport type { MouseEvent, MutableRefObject, RefObject } from 'react';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\n\ninterface UseBottomLeftControlsParams {\n input: string;\n textareaRef: RefObject<RichTextareaHandle>;\n skillInsertAnchorRef: MutableRefObject<{ start: number; end: number } | null>;\n closeMenus: () => void;\n routerPush: (path: string) => void;\n}\n\nexport function useBottomLeftControls({\n input,\n textareaRef,\n skillInsertAnchorRef,\n closeMenus,\n routerPush,\n}: UseBottomLeftControlsParams) {\n const onSkillMouseDown = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n e.preventDefault();\n const ta = textareaRef.current;\n const start = ta?.getSelectionStart() ?? input.length;\n const end = ta?.getSelectionEnd() ?? input.length;\n skillInsertAnchorRef.current = { start, end };\n },\n [input, textareaRef, skillInsertAnchorRef],\n );\n\n const onOpenSkillManager = useCallback(() => {\n closeMenus();\n routerPush('/skills');\n }, [closeMenus, routerPush]);\n\n return {\n onSkillMouseDown,\n onOpenSkillManager,\n };\n}\n","import { useCallback } from 'react';\nimport type { Dispatch, KeyboardEvent, SetStateAction } from 'react';\nimport type { SkillOption } from '@/utils/skill-options-cache';\n\ninterface UseSkillMenuInputParams {\n filteredSkillOptions: SkillOption[];\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n onInsertSkill: (name: string) => void;\n onClose: () => void;\n onSkillFilterChange: (value: string) => void;\n}\n\nexport function useSkillMenuInput({\n filteredSkillOptions,\n selectedIdx,\n setSelectedIdx,\n onInsertSkill,\n onClose,\n onSkillFilterChange,\n}: UseSkillMenuInputParams) {\n const handleSkillFilterChange = useCallback(\n (value: string) => {\n onSkillFilterChange(value);\n setSelectedIdx(0);\n },\n [onSkillFilterChange, setSelectedIdx],\n );\n\n const handleSkillFilterKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (filteredSkillOptions.length === 0) {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedIdx((idx) => (idx + 1) % filteredSkillOptions.length);\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedIdx((idx) => (idx - 1 + filteredSkillOptions.length) % filteredSkillOptions.length);\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const skill = filteredSkillOptions[selectedIdx];\n if (skill) onInsertSkill(skill.name);\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n }\n },\n [filteredSkillOptions, onClose, onInsertSkill, selectedIdx, setSelectedIdx],\n );\n\n return {\n handleSkillFilterChange,\n handleSkillFilterKeyDown,\n };\n}\n","'use client';\n\nimport type { Dispatch, MutableRefObject, RefObject, SetStateAction } from 'react';\nimport type { SkillOption } from '@/utils/skill-options-cache';\nimport { OverflowTooltip } from '../../shared/OverflowTooltip';\nimport { useSkillMenuInput } from '../hooks/useSkillMenuInput';\n\nconst SKILL_MENU_CLASS =\n 'ui-overlay-card absolute bottom-full left-0 mb-2 z-[200] flex w-[240px] flex-col overflow-visible rounded-xl p-2 shadow-[var(--overlay-shadow)]';\nconst SKILL_MENU_ITEM_CLASS =\n 'relative flex h-[32px] w-full items-center gap-2 rounded-[6px] px-2 py-[7px] text-left text-[12px] font-normal text-[var(--overlay-text)] transition-colors';\n\nfunction getSkillInitial(name: string): string {\n const trimmed = name.trim();\n if (!trimmed) return '?';\n const [initial] = Array.from(trimmed);\n return /[a-z]/i.test(initial) ? initial.toUpperCase() : initial;\n}\n\nfunction SkillOptionIcon({ name, iconUrl }: { name: string; iconUrl?: string | null }) {\n if (iconUrl) {\n return <img src={iconUrl} alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4 shrink-0 rounded-sm object-cover\" />;\n }\n return (\n <span className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm bg-[var(--surface-card-muted)] text-[10px] font-semibold text-[var(--text-label-secondary)]\">\n {getSkillInitial(name)}\n </span>\n );\n}\n\ninterface SkillMenuPanelProps {\n menuRef: RefObject<HTMLDivElement | null>;\n skillFilter: string;\n onSkillFilterChange: (value: string) => void;\n filteredSkillOptions: SkillOption[];\n skillOptionsLoading: boolean;\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n skillOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n onInsertSkill: (name: string) => void;\n onClose: () => void;\n onOpenSkillManager: () => void;\n}\n\nexport function SkillMenuPanel({\n menuRef,\n skillFilter,\n onSkillFilterChange,\n filteredSkillOptions,\n skillOptionsLoading,\n selectedIdx,\n setSelectedIdx,\n skillOptionRefs,\n onInsertSkill,\n onClose,\n onOpenSkillManager,\n}: SkillMenuPanelProps) {\n const { handleSkillFilterChange, handleSkillFilterKeyDown } = useSkillMenuInput({\n filteredSkillOptions,\n selectedIdx,\n setSelectedIdx,\n onInsertSkill,\n onClose,\n onSkillFilterChange,\n });\n\n return (\n <div ref={menuRef} className={SKILL_MENU_CLASS}>\n <div className=\"px-1 pt-0 pb-2\">\n <div className=\"relative\">\n <svg\n className=\"pointer-events-none absolute left-0 top-1/2 h-5 w-5 -translate-y-1/2 text-[var(--text-label-secondary)]\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"M20 20l-3.5-3.5\" />\n </svg>\n <input\n value={skillFilter}\n onChange={(e) => handleSkillFilterChange(e.target.value)}\n onKeyDown={handleSkillFilterKeyDown}\n placeholder=\"请输入关键字搜索\"\n className=\"ui-input ui-input-underline w-full py-1 pl-6 pr-0 text-sm\"\n />\n </div>\n </div>\n <div className=\"-mr-1 max-h-[260px] overflow-x-visible overflow-y-auto pr-1 [scrollbar-gutter:auto]\">\n {skillOptionsLoading &&\n Array.from({ length: 5 }).map((_, i) => (\n <div\n key={`skill-loading-${i}`}\n className=\"flex h-[24px] w-full items-center gap-2 rounded-[6px] p-2\"\n style={{ animationDelay: `${i * 70}ms` }}\n >\n <div className=\"h-4 w-4 shrink-0 rounded-sm bg-[var(--surface-card-muted)] animate-pulse\" />\n <div className=\"h-3 w-[120px] rounded bg-[var(--surface-card-muted)] animate-pulse\" />\n </div>\n ))}\n {!skillOptionsLoading &&\n filteredSkillOptions.map((skill, i) => (\n <button\n key={skill.name}\n type=\"button\"\n ref={(node) => {\n skillOptionRefs.current[i] = node;\n }}\n className={`${SKILL_MENU_ITEM_CLASS} ${\n i === selectedIdx ? 'bg-[var(--overlay-item-hover-bg)]' : 'hover:bg-[var(--overlay-item-hover-bg)]'\n }`}\n onMouseDown={(e) => {\n e.preventDefault();\n onInsertSkill(skill.name);\n }}\n onMouseEnter={() => {\n setSelectedIdx(i);\n }}\n >\n {skill.description?.trim() ? (\n <OverflowTooltip\n content={skill.description.trim()}\n forceShow\n placement=\"right\"\n className=\"flex min-w-0 w-full items-center gap-2\"\n gap={8}\n >\n <span className=\"flex min-w-0 w-full items-center gap-2\">\n <SkillOptionIcon name={skill.name} iconUrl={skill.iconUrl} />\n <span className=\"truncate\">{skill.name}</span>\n </span>\n </OverflowTooltip>\n ) : (\n <span className=\"flex min-w-0 w-full items-center gap-2\">\n <SkillOptionIcon name={skill.name} iconUrl={skill.iconUrl} />\n <span className=\"truncate\">{skill.name}</span>\n </span>\n )}\n </button>\n ))}\n {!skillOptionsLoading && filteredSkillOptions.length === 0 && (\n <div className=\"px-2 py-2 text-xs text-[var(--text-label-secondary)]\">无匹配技能</div>\n )}\n </div>\n <div className=\"p-2\">\n <div className=\"h-px w-full bg-[var(--panel-divider)]\" />\n </div>\n <button\n type=\"button\"\n className=\"ui-button-default mx-2 inline-flex h-[24px] min-w-0 items-center justify-center px-3 text-[12px]\"\n onMouseDown={(e) => {\n e.preventDefault();\n onOpenSkillManager();\n }}\n >\n 管理技能\n </button>\n </div>\n );\n}\n\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function GuidedModeIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\">\n <circle cx=\"8\" cy=\"8\" r=\"7\" stroke=\"currentColor\" strokeWidth=\"1\" />\n <path\n d=\"M5.03389 10.0209C4.95343 10.1842 5.0206 10.3819 5.18391 10.4623C5.25705 10.4984 5.34095 10.506 5.4194 10.4838L7.95473 9.76606L10.581 10.4881C10.7565 10.5364 10.9379 10.4332 10.9862 10.2577C11.008 10.1786 10.9994 10.0943 10.9623 10.0211L8.25303 4.68058C8.17066 4.51822 7.97226 4.45337 7.80989 4.53574C7.74628 4.56801 7.69485 4.62004 7.66333 4.68403L5.03389 10.0209Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}","import type { Dispatch, MouseEvent, MutableRefObject, RefObject, SetStateAction } from 'react';\nimport type { QuickActionConfig } from '@/config/quick-actions';\nimport type { SkillOption } from '@/utils/skill-options-cache';\nimport type { SelectedTemplateSummary } from '../types';\nimport { MaskIcon } from '@/components/shared/MaskIcon';\nimport { SkillMenuPanel } from '@/components/chat-input/components/SkillMenuPanel';\nimport { GuidedModeIcon } from '@/components/icons/GuidedModeIcon';\nimport { OverflowTooltip } from '@/components/shared/OverflowTooltip';\nimport { SKILL_TRIGGER_BUTTON_CLASS } from '../utils/constants';\n\n\ninterface ChatInputSkillControlsProps {\n skillBtnRef: RefObject<HTMLButtonElement>;\n styleTemplateBtnRef: RefObject<HTMLButtonElement>;\n onSkillMouseDown: (e: MouseEvent<HTMLButtonElement>) => void;\n onSkillClick: () => void;\n selectedQuickAction: QuickActionConfig | null;\n guidedModeEnabled: boolean;\n onToggleGuidedMode: () => void;\n hasPptSkillInInput: boolean;\n selectedTemplate: SelectedTemplateSummary | null;\n onStyleTemplateClick: () => void;\n onClearSelectedTemplate: () => void;\n showSkillMenu: boolean;\n menuRef: RefObject<HTMLDivElement>;\n skillFilter: string;\n onSkillFilterChange: (value: string) => void;\n filteredSkillOptions: SkillOption[];\n skillOptionsLoading: boolean;\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n skillOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n onInsertSkill: (skillName: string) => void;\n onCloseMenus: () => void;\n onOpenSkillManager: () => void;\n}\n\nexport function ChatInputSkillControls({\n skillBtnRef,\n styleTemplateBtnRef,\n onSkillMouseDown,\n onSkillClick,\n selectedQuickAction,\n guidedModeEnabled,\n onToggleGuidedMode,\n hasPptSkillInInput,\n selectedTemplate,\n onStyleTemplateClick,\n onClearSelectedTemplate,\n showSkillMenu,\n menuRef,\n skillFilter,\n onSkillFilterChange,\n filteredSkillOptions,\n skillOptionsLoading,\n selectedIdx,\n setSelectedIdx,\n skillOptionRefs,\n onInsertSkill,\n onCloseMenus,\n onOpenSkillManager,\n}: ChatInputSkillControlsProps) {\n return (\n <div className=\"relative inline-flex items-center gap-[8px]\">\n <button\n ref={skillBtnRef}\n type=\"button\"\n onMouseDown={onSkillMouseDown}\n onClick={onSkillClick}\n className={SKILL_TRIGGER_BUTTON_CLASS}\n >\n <MaskIcon src=\"/icons/menu/skills.svg\" className=\"h-4 w-4 text-[var(--mask-icon)]\" />\n 技能\n </button>\n {selectedQuickAction?.label === '幻灯片' && (\n <OverflowTooltip\n content=\"开启引导模式后,将在生成前主动追问并确认细节,确保内容精准贴合需求。\"\n forceShow\n className=\"inline-flex\"\n >\n <button\n type=\"button\"\n onClick={onToggleGuidedMode}\n className={SKILL_TRIGGER_BUTTON_CLASS}\n style={\n guidedModeEnabled\n ? {\n color: 'var(--accent-pill-text)',\n backgroundColor: 'var(--accent-pill-bg)',\n borderColor: 'var(--accent-pill-text)',\n }\n : undefined\n }\n >\n <GuidedModeIcon className=\"h-4 w-4 shrink-0\" />\n 引导模式\n </button>\n </OverflowTooltip>\n )}\n {(selectedQuickAction?.label === '幻灯片' || hasPptSkillInInput) && (\n <>\n {!selectedTemplate ? (\n <button\n ref={styleTemplateBtnRef}\n type=\"button\"\n onClick={onStyleTemplateClick}\n className={SKILL_TRIGGER_BUTTON_CLASS}\n data-testid=\"chat-input-style-template-trigger\"\n >\n <MaskIcon src=\"/icons/userprofile/style-template.svg\" className=\"h-4 w-4 text-[var(--mask-icon)]\" />\n 风格模板\n </button>\n ) : (\n <OverflowTooltip content={selectedTemplate.name} className=\"inline-flex\">\n <span\n className=\"inline-flex max-w-[200px] items-center gap-1 rounded-full border border-[#1476ff] bg-[#f0f7ff] px-3 py-[7px] text-xs text-[#1476ff] transition-colors hover:bg-[#e0f0ff] cursor-pointer\"\n data-testid=\"chat-input-selected-template-pill\"\n onClick={onStyleTemplateClick}\n >\n <span\n role=\"button\"\n className=\"inline-flex h-4 w-4 items-center justify-center rounded-full hover:bg-[#dbeaff]\"\n aria-label=\"删除已选模板\"\n onClick={(e) => {\n e.stopPropagation();\n onClearSelectedTemplate();\n }}\n >\n <MaskIcon name=\"close\" className=\"h-3 w-3\" />\n </span>\n <span className=\"truncate\">{selectedTemplate.name}</span>\n </span>\n </OverflowTooltip>\n )}\n </>\n )}\n {showSkillMenu && (\n <SkillMenuPanel\n menuRef={menuRef}\n skillFilter={skillFilter}\n onSkillFilterChange={onSkillFilterChange}\n filteredSkillOptions={filteredSkillOptions}\n skillOptionsLoading={skillOptionsLoading}\n selectedIdx={selectedIdx}\n setSelectedIdx={setSelectedIdx}\n skillOptionRefs={skillOptionRefs}\n onInsertSkill={onInsertSkill}\n onClose={onCloseMenus}\n onOpenSkillManager={onOpenSkillManager}\n />\n )}\n </div>\n );\n}\n\n","import type { Dispatch, MutableRefObject, RefObject, SetStateAction } from 'react';\nimport type { QuickActionConfig } from '@/config/quick-actions';\nimport type { SkillOption } from '@/utils/skill-options-cache';\nimport type { SelectedTemplateSummary } from '../types';\nimport type { RichTextareaHandle } from './RichTextarea';\nimport { useBottomLeftControls } from '../hooks/useBottomLeftControls';\nimport { ChatInputSkillControls } from './ChatInputSkillControls';\n\ninterface ChatInputBottomLeftProps {\n input: string;\n textareaRef: RefObject<RichTextareaHandle>;\n skillInsertAnchorRef: MutableRefObject<{ start: number; end: number } | null>;\n closeMenus: () => void;\n routerPush: (path: string) => void;\n skillBtnRef: RefObject<HTMLButtonElement>;\n styleTemplateBtnRef: RefObject<HTMLButtonElement>;\n selectedQuickAction: QuickActionConfig | null;\n guidedModeEnabled: boolean;\n hasPptSkillInInput: boolean;\n selectedTemplate: SelectedTemplateSummary | null;\n showSkillMenu: boolean;\n menuRef: RefObject<HTMLDivElement>;\n skillFilter: string;\n onSkillFilterChange: (value: string) => void;\n filteredSkillOptions: SkillOption[];\n skillOptionsLoading: boolean;\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n skillOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n onInsertSkill: (skillName: string) => void;\n onCloseMenus: () => void;\n onSkillClick: () => void;\n onToggleGuidedMode: () => void;\n onStyleTemplateClick: () => void;\n onClearSelectedTemplate: () => void;\n}\n\nexport function ChatInputBottomLeft({\n input,\n textareaRef,\n skillInsertAnchorRef,\n closeMenus,\n routerPush,\n ...rest\n}: ChatInputBottomLeftProps) {\n const { onSkillMouseDown, onOpenSkillManager } = useBottomLeftControls({\n input,\n textareaRef,\n skillInsertAnchorRef,\n closeMenus,\n routerPush,\n });\n\n return (\n <ChatInputSkillControls\n {...rest}\n onSkillMouseDown={onSkillMouseDown}\n onOpenSkillManager={onOpenSkillManager}\n />\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { create } from 'zustand';\n\nconst STORAGE_KEY = 'office-claw-voice-settings';\nconst LEGACY_STORAGE_KEY = 'cat-cafe-voice-settings';\n\nexport interface CustomTerm {\n from: string;\n to: string;\n}\n\nexport interface VoiceSettings {\n customTerms: CustomTerm[];\n customPrompt: string | null; // null = use default\n language: 'zh' | 'en' | ''; // '' = auto-detect\n}\n\nconst DEFAULT_SETTINGS: VoiceSettings = {\n customTerms: [],\n customPrompt: null,\n language: 'zh',\n};\n\nconst VALID_LANGUAGES = new Set<VoiceSettings['language']>(['zh', 'en', '']);\n\nfunction isValidTerm(item: unknown): item is CustomTerm {\n return (\n typeof item === 'object' &&\n item !== null &&\n typeof (item as CustomTerm).from === 'string' &&\n typeof (item as CustomTerm).to === 'string'\n );\n}\n\nfunction normalizeSettings(parsed: unknown): VoiceSettings {\n if (typeof parsed !== 'object' || parsed === null) return DEFAULT_SETTINGS;\n const obj = parsed as Record<string, unknown>;\n\n const customTerms = Array.isArray(obj.customTerms) ? obj.customTerms.filter(isValidTerm) : [];\n\n const customPrompt = typeof obj.customPrompt === 'string' ? obj.customPrompt : null;\n\n const language = VALID_LANGUAGES.has(obj.language as VoiceSettings['language'])\n ? (obj.language as VoiceSettings['language'])\n : 'zh';\n\n return { customTerms, customPrompt, language };\n}\n\nfunction loadFromStorage(): VoiceSettings {\n if (typeof window === 'undefined') return DEFAULT_SETTINGS;\n try {\n let raw = window.localStorage.getItem(STORAGE_KEY);\n if (!raw) raw = window.localStorage.getItem(LEGACY_STORAGE_KEY);\n if (!raw) return DEFAULT_SETTINGS;\n const settings = normalizeSettings(JSON.parse(raw));\n if (window.localStorage.getItem(STORAGE_KEY) === null && window.localStorage.getItem(LEGACY_STORAGE_KEY) !== null) {\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\n window.localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n }\n return settings;\n } catch {\n return DEFAULT_SETTINGS;\n }\n}\n\nfunction saveToStorage(settings: VoiceSettings): void {\n if (typeof window === 'undefined') return;\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\n try {\n window.localStorage.removeItem(LEGACY_STORAGE_KEY);\n } catch {\n /* ignore */\n }\n } catch {\n // localStorage full or unavailable — silently ignore\n }\n}\n\ninterface VoiceSettingsState {\n settings: VoiceSettings;\n\n addTerm: (from: string, to: string) => void;\n removeTerm: (index: number) => void;\n updateTerm: (index: number, from: string, to: string) => void;\n setCustomPrompt: (prompt: string | null) => void;\n setLanguage: (language: VoiceSettings['language']) => void;\n loadSettings: () => void;\n resetAll: () => void;\n}\n\nexport const useVoiceSettingsStore = create<VoiceSettingsState>((set) => ({\n settings: loadFromStorage(),\n\n addTerm: (from, to) =>\n set((state) => {\n const next = {\n ...state.settings,\n customTerms: [...state.settings.customTerms, { from, to }],\n };\n saveToStorage(next);\n return { settings: next };\n }),\n\n removeTerm: (index) =>\n set((state) => {\n const next = {\n ...state.settings,\n customTerms: state.settings.customTerms.filter((_, i) => i !== index),\n };\n saveToStorage(next);\n return { settings: next };\n }),\n\n updateTerm: (index, from, to) =>\n set((state) => {\n if (index < 0 || index >= state.settings.customTerms.length) return state;\n const terms = [...state.settings.customTerms];\n terms[index] = { from, to };\n const next = { ...state.settings, customTerms: terms };\n saveToStorage(next);\n return { settings: next };\n }),\n\n setCustomPrompt: (prompt) =>\n set((state) => {\n const next = { ...state.settings, customPrompt: prompt };\n saveToStorage(next);\n return { settings: next };\n }),\n\n setLanguage: (language) =>\n set((state) => {\n const next = { ...state.settings, language };\n saveToStorage(next);\n return { settings: next };\n }),\n\n loadSettings: () => {\n set({ settings: loadFromStorage() });\n },\n\n resetAll: () => {\n saveToStorage(DEFAULT_SETTINGS);\n set({ settings: DEFAULT_SETTINGS });\n },\n}));\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useVoiceSettingsStore } from '@/stores/voiceSettingsStore';\nimport { correctTranscription, mergeTermEntries, type TermEntry } from '@/utils/transcription-corrector';\n\nexport type VoiceState = 'idle' | 'recording' | 'transcribing';\n\ntype DesktopVoiceEventPayload = {\n type?: string;\n sessionId?: string;\n text?: string;\n error?: string;\n};\n\ntype DesktopMessageEvent = {\n data?: unknown;\n};\n\ntype WebViewBridge = {\n postMessage(message: string): void;\n addEventListener?(eventName: 'message', listener: (event: DesktopMessageEvent) => void): void;\n removeEventListener?(eventName: 'message', listener: (event: DesktopMessageEvent) => void): void;\n};\n\ntype DesktopWindow = Window & {\n chrome?: { webview?: WebViewBridge };\n webkit?: {\n messageHandlers?: {\n officeClawDesktop?: { postMessage(message: string): void };\n };\n };\n};\n\nconst DESKTOP_MESSAGE_EVENT = 'office-claw-desktop-message';\n\nfunction getDesktopBridge(): WebViewBridge | { postMessage(message: string): void } | null {\n if (typeof window === 'undefined') return null;\n const desktopWindow = window as DesktopWindow;\n return desktopWindow.chrome?.webview ?? desktopWindow.webkit?.messageHandlers?.officeClawDesktop ?? null;\n}\n\nfunction parseDesktopPayload(input: unknown): DesktopVoiceEventPayload | null {\n if (!input || typeof input !== 'object') return null;\n return input as DesktopVoiceEventPayload;\n}\n\nexport function useVoiceInput() {\n const settings = useVoiceSettingsStore((s) => s.settings);\n const language = settings.language;\n\n const mergedEntries: ReadonlyArray<TermEntry> = useMemo(\n () => mergeTermEntries(settings.customTerms),\n [settings.customTerms],\n );\n\n const [state, setState] = useState<VoiceState>('idle');\n const [transcript, setTranscript] = useState('');\n const [partialTranscript, setPartialTranscript] = useState('');\n const [error, setError] = useState<string | null>(null);\n const [duration, setDuration] = useState(0);\n\n const desktopSessionRef = useRef<string | null>(null);\n const desktopListenerRef = useRef<((event: DesktopMessageEvent) => void) | null>(null);\n const desktopCustomEventRef = useRef<((event: Event) => void) | null>(null);\n const timerRef = useRef<ReturnType<typeof setInterval> | null>(null);\n const startTimeRef = useRef<number>(0);\n const versionRef = useRef(0);\n const entriesRef = useRef(mergedEntries);\n\n const clearTimers = useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n timerRef.current = null;\n }\n }, []);\n\n const detachDesktopListeners = useCallback(() => {\n if (typeof window === 'undefined') return;\n const desktopWindow = window as DesktopWindow;\n const webview = desktopWindow.chrome?.webview;\n if (webview?.removeEventListener && desktopListenerRef.current) {\n webview.removeEventListener('message', desktopListenerRef.current);\n }\n if (desktopCustomEventRef.current) {\n window.removeEventListener(DESKTOP_MESSAGE_EVENT, desktopCustomEventRef.current as EventListener);\n }\n desktopListenerRef.current = null;\n desktopCustomEventRef.current = null;\n }, []);\n\n const startRecording = useCallback(async () => {\n setError(null);\n setTranscript('');\n setPartialTranscript('');\n setDuration(0);\n versionRef.current += 1;\n entriesRef.current = mergedEntries;\n\n const bridge = getDesktopBridge();\n if (!bridge) {\n setError('当前为浏览器模式,无法使用桌面端原生语音转写');\n setState('idle');\n return;\n }\n\n detachDesktopListeners();\n const sessionId = `voice-${Date.now()}-${versionRef.current}`;\n desktopSessionRef.current = sessionId;\n const myVersion = versionRef.current;\n\n const handlePayload = (payload: DesktopVoiceEventPayload | null) => {\n if (!payload || myVersion !== versionRef.current) return;\n if (!payload.type?.startsWith('voice.transcription.')) return;\n if (payload.sessionId && payload.sessionId !== desktopSessionRef.current) return;\n\n if (payload.type === 'voice.transcription.partial') {\n setPartialTranscript(correctTranscription(payload.text ?? '', entriesRef.current));\n return;\n }\n\n if (payload.type === 'voice.transcription.final') {\n setTranscript(correctTranscription(payload.text ?? '', entriesRef.current));\n setPartialTranscript('');\n setState('idle');\n clearTimers();\n detachDesktopListeners();\n return;\n }\n\n if (payload.type === 'voice.transcription.error') {\n setError(payload.error || '原生语音转写失败');\n setState('idle');\n clearTimers();\n detachDesktopListeners();\n }\n };\n\n const webviewListener = (event: DesktopMessageEvent) => {\n handlePayload(parseDesktopPayload(event.data));\n };\n const customEventListener = (event: Event) => {\n const detail = (event as CustomEvent<unknown>).detail;\n handlePayload(parseDesktopPayload(detail));\n };\n\n desktopListenerRef.current = webviewListener;\n desktopCustomEventRef.current = customEventListener;\n const desktopWindow = window as DesktopWindow;\n desktopWindow.chrome?.webview?.addEventListener?.('message', webviewListener);\n window.addEventListener(DESKTOP_MESSAGE_EVENT, customEventListener as EventListener);\n\n bridge.postMessage(\n JSON.stringify({\n type: 'voice.transcription.start',\n sessionId,\n language: language === 'en' ? 'en-US' : language === 'zh' ? 'zh-CN' : '',\n }),\n );\n\n startTimeRef.current = Date.now();\n setState('recording');\n timerRef.current = setInterval(() => {\n setDuration(Math.floor((Date.now() - startTimeRef.current) / 1000));\n }, 1000);\n }, [clearTimers, detachDesktopListeners, language, mergedEntries]);\n\n const stopRecording = useCallback(() => {\n const bridge = getDesktopBridge();\n if (bridge && state === 'recording') {\n bridge.postMessage(\n JSON.stringify({\n type: 'voice.transcription.stop',\n sessionId: desktopSessionRef.current,\n }),\n );\n clearTimers();\n // Stop should immediately exit recording UI so mic button reappears.\n setState('idle');\n }\n }, [clearTimers, state]);\n\n useEffect(() => {\n return () => {\n clearTimers();\n detachDesktopListeners();\n };\n }, [clearTimers, detachDesktopListeners]);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent('office-claw:voice-state', { detail: { state } }));\n }, [state]);\n\n return {\n state,\n transcript,\n partialTranscript,\n error,\n duration,\n startRecording,\n stopRecording,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function LoadingIcon({ className = 'w-5 h-5' }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" className={`animate-spin ${className}`} stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 12L21 9M21 15L18 12\" />\n <path d=\"M3 12H18\" />\n <path d=\"M3 12L6 8M6 16L3 12\" />\n <path d=\"M10 8V16\" />\n <path d=\"M14 8V16\" />\n </svg>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function MicIcon({ className = 'w-5 h-5' }: { className?: string }) {\n return (\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 32 32\" width=\"32.000000\" height=\"32.000000\" fill=\"none\">\n\t<defs>\n\t\t<clipPath id=\"clipPath_1\">\n\t\t\t<rect width=\"32.000000\" height=\"32.000000\" x=\"0.000000\" y=\"0.000000\" rx=\"8.000000\" fill=\"rgb(255,255,255)\"/>\n\t\t</clipPath>\n\t\t<linearGradient id=\"paint_linear_0\" x1=\"13\" x2=\"20.0000038\" y1=\"21.1280823\" y2=\"7.00000095\" gradientUnits=\"userSpaceOnUse\">\n\t\t\t<stop stopColor=\"rgb(226,128,255)\" offset=\"0\" stopOpacity=\"1\"/>\n\t\t\t<stop stopColor=\"rgb(102,134,255)\" offset=\"0.517614722\" stopOpacity=\"1\"/>\n\t\t\t<stop stopColor=\"rgb(77,221,255)\" offset=\"1\" stopOpacity=\"1\"/>\n\t\t</linearGradient>\n\t</defs>\n\t<rect id=\"语音按钮\" width=\"32.000000\" height=\"32.000000\" x=\"0.000000\" y=\"0.000000\" rx=\"8.000000\"/>\n\t<g id=\"编组 19\">\n\t\t<rect id=\"矩形\" width=\"32.000000\" height=\"32.000000\" x=\"0.000000\" y=\"0.000000\" rx=\"8.000000\" fill=\"rgb(0,0,0)\" fillOpacity=\"0\"/>\n\t\t<rect id=\"矩形\" width=\"31.000000\" height=\"31.000000\" x=\"0.500000\" y=\"0.500000\" rx=\"7.500000\" stroke=\"rgb(151,151,151)\" strokeOpacity=\"0\" strokeWidth=\"1\"/>\n\t\t<rect id=\"矩形\" width=\"24.000000\" height=\"24.000000\" x=\"4.000000\" y=\"4.000000\" fill=\"rgb(216,216,216)\" fillOpacity=\"0\"/>\n\t\t<rect id=\"矩形\" width=\"23.000000\" height=\"23.000000\" x=\"4.500000\" y=\"4.500000\" stroke=\"rgb(151,151,151)\" strokeOpacity=\"0\" strokeWidth=\"1\"/>\n\t\t<g id=\"编组 18\">\n\t\t\t<rect id=\"矩形\" width=\"7.000000\" height=\"11.000000\" x=\"13.000000\" y=\"7.000000\" rx=\"3.500000\" fill=\"url(#paint_linear_0)\" fillOpacity=\"0\"/>\n\t\t\t<rect id=\"矩形\" width=\"7.000000\" height=\"11.000000\" x=\"13.000000\" y=\"7.000000\" rx=\"3.500000\" stroke=\"rgb(128,128,128)\" strokeLinejoin=\"round\" strokeWidth=\"1.20000005\"/>\n\t\t\t<path id=\"路径\" d=\"M9 14C9 18.4183 12.3579 22 16.5 22C20.6421 22 24 18.4183 24 14\" fill=\"rgb(216,216,216)\" fillOpacity=\"0\" fillRule=\"evenodd\"/>\n\t\t\t<path id=\"路径\" d=\"M9 14C9 18.4183 12.3579 22 16.5 22C20.6421 22 24 18.4183 24 14\" fillRule=\"evenodd\" stroke=\"rgb(128,128,128)\" strokeLinecap=\"round\" strokeWidth=\"1.20000005\"/>\n\t\t\t<path id=\"路径 2\" d=\"M0 0L2.78809 0\" stroke=\"rgb(128,128,128)\" strokeLinecap=\"round\" strokeWidth=\"1.20000005\" transform=\"matrix(0,1,-1,0,16.5,22.5811)\"/>\n\t\t</g>\n\t</g>\n</svg>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function RotatingBorderStopIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 20 20\" aria-hidden=\"true\">\n <g>\n <path\n d=\"M10 1.5A8.5 8.5 0 0 1 18.5 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M18.5 10A8.5 8.5 0 1 1 10 1.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeOpacity=\"0.24\"\n strokeWidth=\"1.8\"\n strokeLinecap=\"round\"\n />\n <animateTransform\n attributeName=\"transform\"\n type=\"rotate\"\n from=\"0 10 10\"\n to=\"360 10 10\"\n dur=\"1s\"\n repeatCount=\"indefinite\"\n />\n </g>\n <rect x=\"6.3\" y=\"6.3\" width=\"7.4\" height=\"7.4\" rx=\"1.5\" fill=\"currentColor\" />\n </svg>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function SendIcon({ className = 'w-5 h-5' }: { className?: string }) {\n return (\n <svg viewBox=\"0 0 32 32\" xmlns=\"http://www.w3.org/2000/svg\" width=\"32.000000\" height=\"32.000000\" fill=\"none\">\n <rect id=\"发送按钮\" width=\"32.000000\" height=\"32.000000\" x=\"0.000000\" y=\"0.000000\" />\n <rect id=\"Rectangle\" width=\"32.000000\" height=\"32.000000\" x=\"0.000000\" y=\"0.000000\" rx=\"16.000000\" fill=\"currentColor\" />\n <rect id=\"Rectangle\" width=\"31.000000\" height=\"31.000000\" x=\"0.500000\" y=\"0.500000\" rx=\"15.500000\" stroke=\"rgb(0,0,0)\" strokeOpacity=\"0\" strokeWidth=\"1\" />\n <g id=\"编组 2\">\n <rect id=\"矩形\" width=\"20.000000\" height=\"20.000000\" x=\"6.000000\" y=\"6.000000\" fill=\"rgb(216,216,216)\" fillOpacity=\"0\" />\n <rect id=\"矩形\" width=\"19.000000\" height=\"19.000000\" x=\"6.500000\" y=\"6.500000\" stroke=\"rgb(151,151,151)\" strokeOpacity=\"0\" strokeWidth=\"1\" />\n <g id=\"编组\">\n <path id=\"Fill 1\" d=\"M23.4524 7.7341L7.10455 15.5113C6.74775 15.681 6.74268 16.1869 7.09622 16.3636L11.169 18.3998C11.3653 18.4981 11.6011 18.47 11.7691 18.3289L20.9288 10.6295C21.0811 10.5014 21.2814 10.7159 21.1432 10.8591L13.2495 19.0414C13.0854 19.2117 13.006 19.4465 13.0331 19.6815L13.522 23.9124C13.5692 24.321 14.0787 24.4798 14.3498 24.1705L16.3212 21.9191C16.4448 21.7782 16.4169 21.5609 16.2622 21.4554L14.6302 20.3428C14.5321 20.2757 14.6204 20.1255 14.7265 20.1787L16.8956 21.2631L19.447 22.5386C19.7084 22.6693 20.0245 22.5348 20.1115 22.256L24.3965 8.55372C24.5742 7.9856 23.99 7.47826 23.4524 7.7341Z\" fill=\"rgb(255,255,255)\" fillRule=\"evenodd\" />\n <path id=\"形状结合\" d=\"M13.0195 19.5098C13.0169 19.5355 13.0156 19.5615 13.0156 19.5875C13.0156 19.6177 13.0174 19.648 13.0209 19.6783L13.5097 23.9092C13.557 24.3178 14.0665 24.4766 14.3375 24.1673L16.3089 21.9159C16.3611 21.8564 16.3863 21.7832 16.3863 21.7106C16.3863 21.6113 16.3393 21.5131 16.2499 21.4522L14.6179 20.3396C14.5976 20.3257 14.5853 20.3083 14.5795 20.2898L13.0195 19.5098Z\" opacity=\"0.0500000007\" fill=\"rgb(0,0,0)\" fillOpacity=\"0\" fillRule=\"evenodd\" />\n </g>\n </g>\n </svg>\n\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function StopRecordingIcon({ className = 'w-5 h-5' }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 1024 1024\">\n <path d=\"M365.014704 657.815846H657.084939V365.74561H365.014704V657.815846z m584.140471-146.035118c0-240.906781-197.125482-438.105353-438.105353-438.105353-240.979872 0-438.105353 197.198572-438.105354 438.105353 0 240.979872 197.125482 438.178444 438.105354 438.178444 240.979872 0 438.105353-197.198572 438.105353-438.178444zM511.634547 0.730906c281.399001 0 511.634547 230.235546 511.634547 511.634547s-230.235546 511.634547-511.634547 511.634547-511.634547-230.235546-511.634547-511.634547 230.235546-511.634547 511.634547-511.634547z\" p-id=\"12240\"></path></svg>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useEffect, useState } from 'react';\nimport { useVoiceInput } from '@/hooks/useVoiceInput';\nimport { LoadingIcon } from '../../icons/LoadingIcon';\nimport { MicIcon } from '../../icons/MicIcon';\nimport { RotatingBorderStopIcon } from '../../icons/RotatingBorderStopIcon';\nimport { SendIcon } from '../../icons/SendIcon';\nimport { StopRecordingIcon } from '../../icons/StopRecordingIcon';\nimport { OverflowTooltip } from '../../shared/OverflowTooltip';\n\ninterface ChatInputActionButtonProps {\n onTranscript: (text: string) => void;\n onSend: () => void;\n /** F39: Queue-mode send (content will be queued behind running invocation) */\n onQueueSend?: () => void;\n onStop?: () => void;\n disabled?: boolean;\n sendDisabled?: boolean;\n hideIdleMic?: boolean;\n /** Whether the thread has an active invocation (broader than disabled/isLoading) */\n hasActiveInvocation?: boolean;\n hasText: boolean;\n queueLimitReached?: boolean;\n showQueueTooltip?: boolean;\n}\n\n/** Renders the action button states:\n * 1. Stop recording\n * 2. Transcribing\n * 3. Queue send (F39: active invocation)\n * 4. Normal send (has text)\n * 5. Mic (default)\n *\n * Plus voice recording status overlays (REC badge, error).\n * Keyboard shortcut: Option+V toggles recording. */\nexport function ChatInputActionButton({\n onTranscript,\n onSend,\n onQueueSend,\n onStop,\n disabled,\n sendDisabled,\n hideIdleMic,\n hasActiveInvocation,\n hasText,\n queueLimitReached,\n showQueueTooltip,\n}: ChatInputActionButtonProps) {\n const voice = useVoiceInput();\n const [visibleError, setVisibleError] = useState<string | null>(null);\n const isSendDisabled = Boolean(disabled || sendDisabled);\n\n useEffect(() => {\n if (voice.transcript) onTranscript(voice.transcript);\n }, [voice.transcript, onTranscript]);\n\n useEffect(() => {\n if (!voice.error) return;\n setVisibleError(voice.error);\n const timer = window.setTimeout(() => {\n setVisibleError(null);\n }, 5000);\n return () => window.clearTimeout(timer);\n }, [voice.error]);\n\n // Global keyboard shortcut: Option+V (Alt+V) toggles voice recording\n const { state: voiceState, startRecording, stopRecording } = voice;\n useEffect(() => {\n const handleKeydown = (e: KeyboardEvent) => {\n if (e.altKey && e.code === 'KeyV') {\n e.preventDefault();\n if (voiceState === 'recording') {\n stopRecording();\n } else if (voiceState === 'idle' && !disabled) {\n startRecording();\n }\n }\n };\n const handleToggleVoice = () => {\n if (voiceState === 'recording') {\n stopRecording();\n } else if (voiceState === 'idle' && !disabled) {\n startRecording();\n }\n };\n document.addEventListener('keydown', handleKeydown);\n window.addEventListener('toggle-voice-recording', handleToggleVoice);\n return () => {\n document.removeEventListener('keydown', handleKeydown);\n window.removeEventListener('toggle-voice-recording', handleToggleVoice);\n };\n }, [voiceState, startRecording, stopRecording, disabled]);\n\n // F39: Whether we're in queue mode (cat running + user has typed)\n const isQueueMode = Boolean(hasActiveInvocation && onQueueSend);\n const showIdleMic = !hideIdleMic && voice.state === 'idle';\n const queueTooltip = queueLimitReached\n ? '待执行任务已达到 20 条上限,请等待完成或减少后重试'\n : '加入待执行任务';\n\n if (voice.state === 'recording') {\n return (\n <div className=\"relative flex w-full items-center\">\n {visibleError && (\n <div className=\"absolute bottom-full right-0 mb-2 w-[240px] max-w-[70vw] break-words rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs leading-5 text-red-600 shadow-sm\">\n {visibleError}\n </div>\n )}\n <div className=\"relative h-10 w-full overflow-hidden rounded-xl flex items-center justify-center\">\n <img src=\"/icons/chart/home-loading.webp\" alt=\"loading\" className=\"h-full w-[auto] object-cover\" />\n <button\n onClick={voice.stopRecording}\n className=\"absolute right-2 top-1/2 inline-flex h-8 w-8 -translate-y-1/2 items-center justify-center rounded-xl transition-opacity hover:opacity-90\"\n title=\"停止录音\"\n aria-label=\"停止录音\"\n >\n <StopRecordingIcon className=\"h-6 w-6\" />\n </button>\n </div>\n </div>\n );\n }\n\n return (\n <div className=\"relative flex shrink-0 items-center justify-end\">\n {/* Voice recording status */}\n {visibleError && (\n <div className=\"absolute bottom-full right-0 mb-2 w-[240px] max-w-[70vw] break-words rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-xs leading-5 text-red-600 shadow-sm\">\n {visibleError}\n </div>\n )}\n\n {showIdleMic && (\n <button\n onClick={voice.startRecording}\n disabled={disabled}\n className=\"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-xl text-gray-400 transition-colors hover:bg-white hover:text-cocreator-primary disabled:cursor-not-allowed disabled:opacity-40\"\n aria-label=\"开始语音输入 (Alt+V)\"\n title=\"语音输入 (Alt+V)\"\n >\n <MicIcon className=\"w-5 h-5\" />\n </button>\n )}\n\n {/* Primary action button priority chain */}\n {voice.state === 'transcribing' ? (\n <button\n disabled\n className=\"inline-flex h-8 w-8 shrink-0 cursor-wait items-center justify-center rounded-xl bg-gray-300 text-white\"\n title=\"转写中\"\n aria-label=\"转写中\"\n >\n <LoadingIcon className=\"w-5 h-5\" />\n </button>\n ) : isQueueMode ? (\n hasText ? (\n showQueueTooltip ? (\n <OverflowTooltip content={queueTooltip} forceShow className=\"ml-2 inline-flex\">\n <button\n onClick={onQueueSend}\n disabled={isSendDisabled}\n className=\"inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-[20px] text-white transition-colors disabled:cursor-not-allowed disabled:opacity-40 chat-input-send-message\"\n aria-label=\"加入待执行任务\"\n >\n <SendIcon className=\"w-5 h-5\" />\n </button>\n </OverflowTooltip>\n ) : (\n <button\n onClick={onQueueSend}\n disabled={isSendDisabled}\n className=\"ml-2 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-[20px] text-white transition-colors disabled:cursor-not-allowed disabled:opacity-40 chat-input-send-message\"\n aria-label=\"加入待执行任务\"\n >\n <SendIcon className=\"w-5 h-5\" />\n </button>\n )\n ) : onStop ? (\n <button\n onClick={() => onStop()}\n className=\"ml-2 inline-flex shrink-0 items-center gap-2 rounded-full px-3 py-1.5 text-[12px] font-medium transition-colors hover:bg-blue-50 chat-input-stop-generation\"\n aria-label=\"停止回答\"\n title=\"停止回答\"\n >\n <RotatingBorderStopIcon className=\"h-5 w-5 shrink-0\" />\n <span>停止回答</span>\n </button>\n ) : null\n ) : hasText ? (\n <button\n onClick={onSend}\n disabled={isSendDisabled}\n className=\"ml-2 inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-[20px] text-white transition-colors disabled:cursor-not-allowed disabled:opacity-40 chat-input-send-message\"\n aria-label=\"发送消息\"\n >\n <SendIcon className=\"w-5 h-5\" />\n </button>\n ) : null}\n </div>\n );\n}\n\n","import { useCallback } from 'react';\nimport type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react';\nimport type { WorkspaceMenuItem } from '../types';\n\ninterface UseBottomRightActionsParams {\n fileInputRef: RefObject<HTMLInputElement>;\n workspaceMenuItems: WorkspaceMenuItem[];\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n setWorkspaceFilter: Dispatch<SetStateAction<string>>;\n closeMenus: () => void;\n selectWorkspaceMenuItem: (item: WorkspaceMenuItem) => void;\n}\n\nexport function useBottomRightActions({\n fileInputRef,\n workspaceMenuItems,\n selectedIdx,\n setSelectedIdx,\n setWorkspaceFilter,\n closeMenus,\n selectWorkspaceMenuItem,\n}: UseBottomRightActionsParams) {\n const handleAttachClick = useCallback(() => {\n fileInputRef.current?.click();\n }, [fileInputRef]);\n\n const handleWorkspaceFilterChange = useCallback(\n (value: string) => {\n setWorkspaceFilter(value);\n setSelectedIdx(0);\n },\n [setWorkspaceFilter, setSelectedIdx],\n );\n\n const handleWorkspaceSearchKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (workspaceMenuItems.length === 0) {\n if (e.key === 'Escape') {\n e.preventDefault();\n closeMenus();\n }\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedIdx((idx) => (idx + 1) % workspaceMenuItems.length);\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedIdx((idx) => (idx - 1 + workspaceMenuItems.length) % workspaceMenuItems.length);\n return;\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n const item = workspaceMenuItems[selectedIdx];\n if (item) selectWorkspaceMenuItem(item);\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n closeMenus();\n }\n },\n [closeMenus, selectWorkspaceMenuItem, selectedIdx, setSelectedIdx, workspaceMenuItems],\n );\n\n return {\n handleAttachClick,\n handleWorkspaceFilterChange,\n handleWorkspaceSearchKeyDown,\n };\n}\n\n","import { useEffect, useState, type MutableRefObject, type RefObject, type Dispatch, type SetStateAction } from 'react';\nimport { ChatInputActionButton } from './ChatInputActionButton';\nimport { MaskIcon } from '@/components/shared/MaskIcon';\nimport { OverflowTooltip } from '@/components/shared/OverflowTooltip';\nimport { ICON_BUTTON_CLASS, MAX_ATTACHMENT_FILES } from '../utils/constants';\nimport type { WorkspaceMenuItem } from '../types';\nimport { useBottomRightActions } from '../hooks/useBottomRightActions';\n\ninterface ChatInputBottomRightProps {\n fileInputRef: RefObject<HTMLInputElement>;\n setWorkspaceFilter: Dispatch<SetStateAction<string>>;\n closeMenus: () => void;\n folderSelectionEnabled: boolean;\n selectedFolderTitle: string | null;\n folderButtonLabel: string;\n shouldShowFolderTooltip: boolean;\n folderBtnRef: RefObject<HTMLButtonElement>;\n menuRef: RefObject<HTMLDivElement>;\n workspaceSearchInputRef: RefObject<HTMLInputElement>;\n workspaceFilter: string;\n showWorkspaceMenu: boolean;\n workspaceMenuItems: WorkspaceMenuItem[];\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n workspaceOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n isFolderButtonDisabled: boolean;\n queueAwareDisabled: boolean;\n sendTemporarilyDisabled: boolean;\n imagesCount: number;\n hasActiveInvocation?: boolean;\n inputTrimmed: boolean;\n queueSendDisabled: boolean;\n queueCount: number;\n onWorkspaceClick: () => void;\n onWorkspaceSelect: (item: WorkspaceMenuItem) => void;\n onTranscript: (text: string) => void;\n onSend: () => void;\n onStop?: () => void;\n onQueueSend: () => void;\n}\n\nexport function ChatInputBottomRight({\n fileInputRef,\n setWorkspaceFilter,\n closeMenus,\n folderSelectionEnabled,\n selectedFolderTitle,\n folderButtonLabel,\n shouldShowFolderTooltip,\n folderBtnRef,\n menuRef,\n workspaceSearchInputRef,\n workspaceFilter,\n showWorkspaceMenu,\n workspaceMenuItems,\n selectedIdx,\n setSelectedIdx,\n workspaceOptionRefs,\n isFolderButtonDisabled,\n queueAwareDisabled,\n sendTemporarilyDisabled,\n imagesCount,\n hasActiveInvocation,\n inputTrimmed,\n queueSendDisabled,\n queueCount,\n onWorkspaceClick,\n onWorkspaceSelect,\n onTranscript,\n onSend,\n onStop,\n onQueueSend,\n}: ChatInputBottomRightProps) {\n const [isVoiceRecording, setIsVoiceRecording] = useState(false);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const handleVoiceState = (event: Event) => {\n const customEvent = event as CustomEvent<{ state?: string }>;\n setIsVoiceRecording(customEvent.detail?.state === 'recording');\n };\n window.addEventListener('office-claw:voice-state', handleVoiceState as EventListener);\n return () => {\n window.removeEventListener('office-claw:voice-state', handleVoiceState as EventListener);\n };\n }, []);\n\n const { handleAttachClick, handleWorkspaceFilterChange, handleWorkspaceSearchKeyDown } = useBottomRightActions({\n fileInputRef,\n workspaceMenuItems,\n selectedIdx,\n setSelectedIdx,\n setWorkspaceFilter,\n closeMenus,\n selectWorkspaceMenuItem: onWorkspaceSelect,\n });\n\n return (\n <div className={isVoiceRecording ? `absolute inset-x-0 bottom-0 z-30 flex w-full justify-center` : `flex items-center`}>\n {!isVoiceRecording && folderSelectionEnabled && (\n <div className=\"relative mr-2 flex items-center\">\n <OverflowTooltip\n content={selectedFolderTitle?.trim() || folderButtonLabel}\n forceShow={shouldShowFolderTooltip}\n copyable={shouldShowFolderTooltip}\n className=\"flex items-center\"\n >\n <button\n ref={folderBtnRef}\n type=\"button\"\n data-testid=\"folder-select-button\"\n onClick={onWorkspaceClick}\n disabled={isFolderButtonDisabled}\n className=\"ui-button-default inline-flex h-8 min-w-0 max-w-[160px] items-center gap-1 rounded-[16px] px-3 text-xs shadow-none\"\n >\n <MaskIcon src=\"/icons/chart/folder.svg\" testId=\"folder-select-icon\" className='h-6 w-6 shrink-0 text-[var(--mask-icon)]' />\n <span className=\"truncate\">{folderButtonLabel}</span>\n <MaskIcon src=\"/icons/chevron-right.svg\" className=\"h-3.5 w-3.5 shrink-0 rotate-90 text-[var(--text-label-secondary)]\" />\n </button>\n </OverflowTooltip>\n {showWorkspaceMenu && (\n <div\n ref={menuRef}\n data-testid=\"workspace-select-menu\"\n className=\"ui-overlay-card absolute bottom-full left-0 mb-2 z-[200] flex w-[200px] max-h-[302px] flex-col overflow-hidden rounded-xl border border-[var(--overlay-border)] px-2 py-2 shadow-[var(--overlay-shadow)]\"\n >\n <div className=\"px-1 pt-0 pb-2\">\n <div className=\"relative\">\n <svg\n className=\"pointer-events-none absolute left-0 top-1/2 h-5 w-5 -translate-y-1/2 text-[var(--text-label-secondary)]\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"M20 20l-3.5-3.5\" />\n </svg>\n <input\n ref={workspaceSearchInputRef}\n data-testid=\"workspace-select-search\"\n value={workspaceFilter}\n onChange={(e) => handleWorkspaceFilterChange(e.target.value)}\n onKeyDown={handleWorkspaceSearchKeyDown}\n placeholder=\"请输入关键字搜索\"\n className=\"ui-input ui-input-underline w-full py-1 pl-6 pr-0 text-[12px]\"\n />\n </div>\n </div>\n <div className=\"-mr-1 min-h-0 flex-1 overflow-y-auto pr-1 [scrollbar-gutter:auto]\">\n {workspaceMenuItems.map((item, i) => {\n const label =\n item.kind === 'empty'\n ? '从空文件夹开始'\n : item.kind === 'open'\n ? '打开新文件夹'\n : item.option.name;\n const detail = item.kind === 'workspace' ? item.option.title?.trim() || item.option.path : null;\n const tooltipContent = detail || label;\n return (\n <button\n key={item.kind === 'workspace' ? `${item.option.path}:${item.option.name}` : item.kind}\n type=\"button\"\n data-testid={\n item.kind === 'empty'\n ? 'workspace-menu-item-empty'\n : item.kind === 'open'\n ? 'workspace-menu-item-open'\n : `workspace-menu-item-${i}`\n }\n ref={(node) => {\n workspaceOptionRefs.current[i] = node;\n }}\n className={`flex h-12 w-full items-center rounded-[6px] px-2 py-[6px] text-left text-[12px] font-normal text-[var(--overlay-text)] transition-colors ${\n i === selectedIdx\n ? 'bg-[var(--overlay-item-hover-bg)]'\n : 'hover:bg-[var(--overlay-item-hover-bg)]'\n }`}\n onMouseEnter={() => setSelectedIdx(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n onWorkspaceSelect(item);\n }}\n >\n <OverflowTooltip\n content={tooltipContent}\n forceShow={item.kind === 'workspace'}\n copyable={item.kind === 'workspace'}\n className=\"min-w-0 flex-1\"\n >\n <span className=\"block min-w-0\">\n <span className=\"block truncate\">{label}</span>\n {detail && <span className=\"block truncate text-[10px] text-[var(--text-label-secondary)]\">{detail}</span>}\n </span>\n </OverflowTooltip>\n </button>\n );\n })}\n {workspaceMenuItems.length === 2 && (\n <div className=\"px-2 py-2 text-xs text-[var(--text-label-secondary)]\">无匹配工作空间</div>\n )}\n </div>\n </div>\n )}\n </div>\n )}\n\n {!isVoiceRecording && (\n <OverflowTooltip content=\"选择附件\" forceShow className=\"inline-flex\">\n <button\n type=\"button\"\n data-testid=\"attach-file-button\"\n onClick={handleAttachClick}\n disabled={queueAwareDisabled || sendTemporarilyDisabled || imagesCount >= MAX_ATTACHMENT_FILES}\n className={ICON_BUTTON_CLASS}\n aria-label=\"上传附件\"\n >\n <MaskIcon name=\"attach\" className=\"h-8 w-8 text-[var(--mask-icon)]\" />\n </button>\n </OverflowTooltip>\n )}\n\n <ChatInputActionButton\n onTranscript={onTranscript}\n onSend={onSend}\n onStop={onStop}\n onQueueSend={onQueueSend}\n disabled={queueAwareDisabled}\n sendDisabled={sendTemporarilyDisabled || queueSendDisabled}\n hasActiveInvocation={hasActiveInvocation}\n hasText={inputTrimmed}\n queueLimitReached={queueSendDisabled}\n showQueueTooltip={queueCount > 0}\n />\n </div>\n );\n}\n\n","import { useCallback } from 'react';\nimport type { KeyboardEvent } from 'react';\nimport type { AgentOption } from '../chat-input-options';\n\ninterface UseMentionMenuInputParams {\n agentOptions: AgentOption[];\n selectedIdx: number;\n onSelectIdx: (i: number) => void;\n onInsertMention: (opt: AgentOption) => void;\n onCloseMentionMenu: () => void;\n onMentionFilterChange: (value: string) => void;\n}\n\nexport function useMentionMenuInput({\n agentOptions,\n selectedIdx,\n onSelectIdx,\n onInsertMention,\n onCloseMentionMenu,\n onMentionFilterChange,\n}: UseMentionMenuInputParams) {\n const handleMentionFilterChange = useCallback(\n (value: string) => {\n onMentionFilterChange(value);\n onSelectIdx(0);\n },\n [onMentionFilterChange, onSelectIdx],\n );\n\n const handleMentionFilterKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (agentOptions.length === 0) {\n if (e.key === 'Escape') {\n e.preventDefault();\n onCloseMentionMenu();\n }\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n onSelectIdx((selectedIdx + 1) % agentOptions.length);\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n onSelectIdx((selectedIdx - 1 + agentOptions.length) % agentOptions.length);\n return;\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n const opt = agentOptions[selectedIdx];\n if (opt) onInsertMention(opt);\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n onCloseMentionMenu();\n }\n },\n [agentOptions, onCloseMentionMenu, onInsertMention, onSelectIdx, selectedIdx],\n );\n\n return {\n handleMentionFilterChange,\n handleMentionFilterKeyDown,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { type CSSProperties, type RefObject, useCallback, useEffect, useRef, useState } from 'react';\nimport { type AgentOption } from '../chat-input-options';\nimport { useMentionMenuInput } from '../hooks/useMentionMenuInput';\n\ninterface ChatInputMenusProps {\n agentOptions: AgentOption[];\n showMentions: boolean;\n mentionFilter: string;\n onMentionFilterChange: (value: string) => void;\n onCloseMentionMenu: () => void;\n selectedIdx: number;\n onSelectIdx: (i: number) => void;\n onInsertMention: (opt: AgentOption) => void;\n menuRef: RefObject<HTMLDivElement>;\n mentionMenuStyle?: CSSProperties;\n}\n\nfunction catInitial(name?: string): string {\n if (!name) return '?';\n const normalized = name.replace(/^@/, '').trim();\n return (normalized.slice(0, 1) || '?').toUpperCase();\n}\n\nfunction renderMentionAvatar(opt: AgentOption) {\n const avatar = opt.avatar?.trim() ?? '';\n const isImageAvatar = /^(https?:\\/\\/|\\/|data:image)/.test(avatar);\n\n if (isImageAvatar) {\n return (\n <img\n src={avatar}\n alt={opt.label}\n className=\"w-[18px] h-[18px] rounded-full shrink-0 object-cover\"\n onError={(e) => {\n (e.target as HTMLImageElement).style.display = 'none';\n }}\n />\n );\n }\n\n return (\n <span\n aria-hidden=\"true\"\n className=\"inline-flex h-[18px] w-[18px] shrink-0 items-center justify-center rounded-full text-[10px] font-semibold text-white\"\n style={{ backgroundColor: opt.color || '#7AAEFF' }}\n >\n {avatar || catInitial(opt.label)}\n </span>\n );\n}\n\nexport function ChatInputMenus({\n agentOptions,\n showMentions,\n mentionFilter,\n onMentionFilterChange,\n onCloseMentionMenu,\n selectedIdx,\n onSelectIdx,\n onInsertMention,\n menuRef,\n mentionMenuStyle,\n}: ChatInputMenusProps) {\n const { handleMentionFilterChange, handleMentionFilterKeyDown } = useMentionMenuInput({\n agentOptions,\n selectedIdx,\n onSelectIdx,\n onInsertMention,\n onCloseMentionMenu,\n onMentionFilterChange,\n });\n const scrollRef = useRef<HTMLDivElement>(null);\n const [canScrollDown, setCanScrollDown] = useState(false);\n\n // Auto-scroll selected item into view on keyboard navigation\n const selectedRef = useCallback((node: HTMLButtonElement | null) => {\n if (node && typeof node.scrollIntoView === 'function') {\n node.scrollIntoView({ block: 'nearest' });\n }\n }, []);\n\n // Detect if more items are hidden below\n useEffect(() => {\n const el = scrollRef.current;\n if (!el) {\n setCanScrollDown(false);\n return;\n }\n const check = () => setCanScrollDown(el.scrollHeight > el.clientHeight + el.scrollTop + 4);\n check();\n el.addEventListener('scroll', check);\n return () => el.removeEventListener('scroll', check);\n }, []);\n\n return (\n <>\n {showMentions && (\n <div\n ref={menuRef}\n className=\"fixed bg-white rounded-xl shadow-lg overflow-hidden w-[200px] z-20 flex flex-col p-2\"\n style={mentionMenuStyle}\n >\n <div className=\"px-1 pt-0 pb-2\">\n <div className=\"relative\">\n <svg\n className=\"pointer-events-none absolute left-0 top-1/2 h-5 w-5 -translate-y-1/2 text-gray-400\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n <circle cx=\"11\" cy=\"11\" r=\"7\" />\n <path d=\"M20 20l-3.5-3.5\" />\n </svg>\n <input\n value={mentionFilter}\n onChange={(e) => handleMentionFilterChange(e.target.value)}\n onKeyDown={handleMentionFilterKeyDown}\n placeholder=\"请输入关键字搜索\"\n className=\"ui-input ui-input-underline w-full py-1 pl-6 pr-0 text-[12px]\"\n />\n </div>\n </div>\n <div ref={scrollRef} className=\"max-h-[220px] overflow-y-auto flex-1 border-0\">\n {agentOptions.map((opt, i) => (\n <button\n key={opt.id}\n ref={i === selectedIdx ? selectedRef : undefined}\n className={`w-full h-[34px] text-left p-2 rounded-[6px] flex items-center gap-2 transition-colors ${i === selectedIdx ? 'bg-[rgba(245,245,245,1)]' : 'hover:bg-[rgba(245,245,245,1)]'}`}\n onMouseEnter={() => onSelectIdx(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n onInsertMention(opt);\n }}\n title={opt.label}\n >\n {renderMentionAvatar(opt)}\n <div className=\"min-w-0 flex-1 truncate text-[12px] leading-[18px] font-normal text-[#191919]\">\n {opt.label}\n </div>\n </button>\n ))}\n </div>\n {canScrollDown && (\n <div className=\"px-4 py-1 text-[10px] text-gray-400 text-center bg-gradient-to-t from-white shrink-0\">\n ↓ 还有更多智能体\n </div>\n )}\n {agentOptions.length === 0 && <div className=\"px-4 py-2.5 text-xs text-gray-400\">无匹配智能体</div>}\n </div>\n )}\n </>\n );\n}\n\n\n","import { QUICK_ACTIONS } from '@/config/quick-actions';\nimport { getMentionLabel, getMentionRe } from '@/lib/mention-highlight';\nimport { getCachedSkillOptions } from '@/utils/skill-options-cache';\nimport {\n QUICK_ACTION_TOKEN_PREFIX,\n QUICK_ACTION_TOKEN_SUFFIX,\n SKILL_TOKEN_PREFIX,\n SKILL_TOKEN_SUFFIX,\n} from '@/components/chat-input/utils/constants';\n\nconst QUICK_ACTIONS_SORTED = [...QUICK_ACTIONS].sort((a, b) => b.label.length - a.label.length);\n\nexport type QueueInlineToken =\n | { kind: 'mention'; label: string; start: number; end: number }\n | { kind: 'skill'; label: string; start: number; end: number }\n | { kind: 'quick'; label: string; icon?: string; start: number; end: number };\n\nexport type QueueInlineSegment = { kind: 'text'; text: string } | QueueInlineToken;\n\nfunction isWhitespaceBoundary(input: string, index: number, length: number): boolean {\n const prev = index > 0 ? input[index - 1] : ' ';\n const next = index + length < input.length ? input[index + length] : ' ';\n return /\\s/.test(prev) && /\\s/.test(next);\n}\n\nfunction extractQueueInlineTokens(content: string): QueueInlineToken[] {\n const tokens: QueueInlineToken[] = [];\n const mentionRe = getMentionRe();\n const mentionLabelMap = getMentionLabel();\n const skillNameSet = new Set(\n (getCachedSkillOptions() ?? [])\n .map((item) => item.name.trim().toLowerCase())\n .filter(Boolean),\n );\n\n mentionRe.lastIndex = 0;\n let mentionMatch: RegExpExecArray | null;\n while ((mentionMatch = mentionRe.exec(content)) !== null) {\n const alias = (mentionMatch[1] ?? '').toLowerCase();\n const label = mentionLabelMap[alias] ?? mentionMatch[0];\n if (!label) continue;\n const full = mentionMatch[0] ?? '';\n tokens.push({ kind: 'mention', label, start: mentionMatch.index, end: mentionMatch.index + full.length });\n }\n\n const skillPhraseRe = /(使用\\s+)([^\\n,。!?,.!?]{1,60}?)(\\s+技能)/g;\n let skillMatch: RegExpExecArray | null;\n while ((skillMatch = skillPhraseRe.exec(content)) !== null) {\n const skillName = (skillMatch[2] ?? '').trim();\n if (!skillName) continue;\n if (skillNameSet.size > 0 && !skillNameSet.has(skillName.toLowerCase())) continue;\n const full = skillMatch[0] ?? '';\n tokens.push({ kind: 'skill', label: skillName, start: skillMatch.index, end: skillMatch.index + full.length });\n }\n\n const quickByIndex = new Map<number, QueueInlineToken>();\n for (const action of QUICK_ACTIONS_SORTED) {\n const label = action.label;\n if (!label) continue;\n let from = 0;\n while (from < content.length) {\n const at = content.indexOf(label, from);\n if (at < 0) break;\n from = at + 1;\n if (!isWhitespaceBoundary(content, at, label.length)) continue;\n if (!quickByIndex.has(at)) {\n quickByIndex.set(at, { kind: 'quick', label, icon: action.icon, start: at, end: at + label.length });\n }\n }\n }\n tokens.push(...quickByIndex.values());\n\n // 匹配显式的 [[quick_action:xxx]] token,以支持排队队列中非内置 label(如 PPT 内容核查)的芯片样式渲染\n let quickTokenFrom = 0;\n while (quickTokenFrom < content.length) {\n const at = content.indexOf(QUICK_ACTION_TOKEN_PREFIX, quickTokenFrom);\n if (at < 0) break;\n const end = content.indexOf(QUICK_ACTION_TOKEN_SUFFIX, at + QUICK_ACTION_TOKEN_PREFIX.length);\n if (end > at) {\n const label = content.slice(at + QUICK_ACTION_TOKEN_PREFIX.length, end);\n const matchedAction = QUICK_ACTIONS_SORTED.find(action => action.label === label);\n tokens.push({\n kind: 'quick',\n label,\n icon: matchedAction?.icon,\n start: at,\n end: end + QUICK_ACTION_TOKEN_SUFFIX.length,\n });\n quickTokenFrom = end + QUICK_ACTION_TOKEN_SUFFIX.length;\n } else {\n quickTokenFrom = at + 1;\n }\n }\n\n // 匹配显式的 [[skill:xxx]] token,以支持排队队列中显式技能的芯片样式渲染\n let skillTokenFrom = 0;\n while (skillTokenFrom < content.length) {\n const at = content.indexOf(SKILL_TOKEN_PREFIX, skillTokenFrom);\n if (at < 0) break;\n const end = content.indexOf(SKILL_TOKEN_SUFFIX, at + SKILL_TOKEN_PREFIX.length);\n if (end > at) {\n const label = content.slice(at + SKILL_TOKEN_PREFIX.length, end).trim();\n tokens.push({\n kind: 'skill',\n label,\n start: at,\n end: end + SKILL_TOKEN_SUFFIX.length,\n });\n skillTokenFrom = end + SKILL_TOKEN_SUFFIX.length;\n } else {\n skillTokenFrom = at + 1;\n }\n }\n\n return tokens.sort((a, b) => a.start - b.start);\n}\n\nexport function buildQueueInlineSegments(content: string): QueueInlineSegment[] {\n const tokens = extractQueueInlineTokens(content);\n if (tokens.length === 0) return [{ kind: 'text', text: content }];\n\n const segments: QueueInlineSegment[] = [];\n let cursor = 0;\n for (const token of tokens) {\n if (token.start < cursor) continue;\n if (token.start > cursor) {\n segments.push({ kind: 'text', text: content.slice(cursor, token.start) });\n }\n segments.push(token);\n cursor = token.end;\n }\n if (cursor < content.length) {\n segments.push({ kind: 'text', text: content.slice(cursor) });\n }\n return segments;\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { fetchProtectedResourceBlob } from '@/utils/protected-resource';\n\nasync function copyImageToClipboard(url: string) {\n const blob = await fetchProtectedResourceBlob(url);\n if (!blob.type.startsWith('image/')) throw new Error(`not an image: ${blob.type}`);\n await navigator.clipboard.write([new ClipboardItem({ [blob.type]: blob })]);\n}\n\nexport function CopyButton({ url }: { url: string }) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(\n async (e: React.MouseEvent) => {\n e.stopPropagation();\n try {\n await copyImageToClipboard(url);\n } catch {\n try {\n await navigator.clipboard.writeText(url);\n } catch {\n return;\n }\n }\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n },\n [url],\n );\n\n return (\n <button\n type=\"button\"\n onClick={handleCopy}\n className=\"absolute top-2 right-2 bg-black/60 hover:bg-black/80 text-white rounded-md px-2 py-1 text-xs opacity-0 group-hover:opacity-100 transition-opacity\"\n title={copied ? 'Copied!' : 'Copy image'}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n );\n}\n\nexport function Lightbox({\n url,\n alt,\n caption,\n onClose,\n}: {\n url: string;\n alt: string;\n caption?: string;\n onClose: () => void;\n}) {\n useEffect(() => {\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', handleKey);\n return () => document.removeEventListener('keydown', handleKey);\n }, [onClose]);\n\n if (typeof document === 'undefined') {\n return null;\n }\n\n return createPortal(\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={alt || 'Image preview'}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm\"\n onClick={onClose}\n >\n <div\n className=\"relative group max-w-[90vw] max-h-[90vh] flex flex-col items-center\"\n onClick={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n onClick={onClose}\n className=\"absolute -top-3 -right-3 bg-black/70 hover:bg-black/90 text-white rounded-full w-8 h-8 flex items-center justify-center text-lg z-10\"\n title=\"Close\"\n >\n &times;\n </button>\n {/* biome-ignore lint/performance/noImgElement: data URIs from MCP cannot use next/image */}\n <img src={url} alt={alt} className=\"max-w-full max-h-[85vh] object-contain rounded-lg\" />\n {caption && <p className=\"mt-2 text-sm text-white/80\">{caption}</p>}\n <CopyButton url={url} />\n </div>\n </div>,\n document.body,\n );\n}\n","/*\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 { Lightbox } from '../../Lightbox';\n\ninterface ImagePreviewProps {\n files: File[];\n onRemove: (index: number) => void;\n}\n\nexport function resolveAttachmentIconByFileName(fileName: string): string {\n const ext = fileName.split('.').pop()?.toLowerCase() ?? '';\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') return '/icons/files-txt.svg';\n return '/icons/files-txt.svg';\n}\n\nexport function ImagePreview({ files, onRemove }: ImagePreviewProps) {\n const [lightboxIdx, setLightboxIdx] = useState<number | null>(null);\n\n const formatFileSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n const kb = bytes / 1024;\n if (kb < 1024) return `${kb.toFixed(1)} KB`;\n const mb = kb / 1024;\n if (mb < 1024) return `${mb.toFixed(1)} MB`;\n const gb = mb / 1024;\n return `${gb.toFixed(1)} GB`;\n };\n\n const getFileExt = (name: string) => {\n const parts = name.split('.');\n if (parts.length <= 1) return 'UNKNOWN';\n return parts[parts.length - 1].toUpperCase();\n };\n\n const getFileBaseName = (name: string) => {\n const lastDot = name.lastIndexOf('.');\n if (lastDot <= 0) return name;\n return name.slice(0, lastDot);\n };\n\n const urls = useMemo(() => files.map((f) => URL.createObjectURL(f)), [files]);\n\n useEffect(() => {\n return () => {\n for (const url of urls) URL.revokeObjectURL(url);\n };\n }, [urls]);\n\n if (files.length === 0) return null;\n\n return (\n <>\n <div className=\"mx-3 mb-0 border-b border-gray-100 pb-3 pt-2\">\n <div className=\"w-full max-h-[160px] overflow-y-auto overflow-x-hidden px-2 pt-3\">\n <div className=\"grid w-full min-w-0 grid-cols-3 gap-2 md:grid-cols-3 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5\">\n {files.map((file, i) => (\n <div\n key={`${getFileBaseName(file.name)}-${i}`}\n className=\"group relative inline-flex h-[56px] gap-[10px] rounded-lg border border-gray-200 pl-2 py-2 hover:border-[rgb(240,240,240)] hover:shadow-[0_4px_16px_0_rgba(0,0,0,0.08)]\"\n style={{ paddingRight: 12 }}\n title={getFileBaseName(file.name)}\n >\n {file.type.startsWith('image/') ? (\n <img\n src={urls[i]}\n alt={getFileBaseName(file.name)}\n className=\"h-10 w-10 cursor-pointer rounded-lg object-cover transition-opacity hover:opacity-90\"\n onClick={() => setLightboxIdx(i)}\n />\n ) : (\n <img src={resolveAttachmentIconByFileName(file.name)} alt=\"\" aria-hidden=\"true\" className=\"h-10 w-10 rounded-lg\" />\n )}\n <div\n className={`min-w-0 flex-1 ${file.type.startsWith('image/') ? 'cursor-pointer' : ''}`}\n onClick={() => {\n if (file.type.startsWith('image/')) setLightboxIdx(i);\n }}\n >\n <div\n className=\"truncate overflow-hidden text-ellipsis\"\n style={{ color: '#191919', fontSize: 12, fontWeight: 400, lineHeight: '18px' }}\n >\n {getFileBaseName(file.name)}\n </div>\n <div className=\"mt-1 text-[12px]\" style={{ color: '#808080', fontWeight: 400, lineHeight: '18px' }}>\n <span>{getFileExt(file.name)}</span>\n <span className=\"ml-3\">{formatFileSize(file.size)}</span>\n </div>\n </div>\n <button\n onClick={() => onRemove(i)}\n className=\"absolute -right-2 -top-2 z-10 hidden h-4 w-4 items-center justify-center rounded-full bg-[#c2c2c2] pb-1 text-xs text-white group-hover:flex\"\n style={{ boxShadow: '0 0 0 1px rgba(255,255,255,0.8)' }}\n title={`移除 ${getFileBaseName(file.name)}`}\n aria-label={`Remove ${getFileBaseName(file.name)}`}\n >\n x\n </button>\n </div>\n ))}\n </div>\n </div>\n </div>\n {lightboxIdx !== null && urls[lightboxIdx] && files[lightboxIdx]?.type.startsWith('image/') && (\n <Lightbox\n url={urls[lightboxIdx]}\n alt={files[lightboxIdx]?.name ?? 'preview'}\n onClose={() => setLightboxIdx(null)}\n />\n )}\n </>\n );\n}\n","import type { SVGProps } from 'react';\n\nexport function QueueEditIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"currentColor\" aria-hidden=\"true\" {...props}>\n <rect fill=\"none\" />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n fill=\"currentColor\"\n d=\"M5.48 14.29c.19-.08.35-.19.49-.33l7.69-7.69c.13-.13.25-.27.34-.42.08-.13.15-.27.21-.41s.1-.29.13-.44a2.074 2.074 0 0 0 0-1c-.03-.15-.07-.3-.13-.44s-.13-.28-.21-.41c-.09-.15-.21-.29-.34-.42-.13-.13-.27-.24-.42-.34-.13-.08-.26-.15-.4-.21-.15-.05-.29-.1-.44-.13-.17-.03-.33-.05-.5-.05-.18 0-.34.02-.51.05-.15.03-.29.08-.44.13-.14.06-.27.13-.4.21-.15.1-.29.21-.42.34l-7.69 7.69c-.15.15-.25.31-.33.49-.08.18-.11.38-.11.58v2.21c0 .1.01.19.05.27.03.08.08.16.15.22.07.07.14.12.23.16.08.03.17.05.27.05h2.21c.2 0 .39-.04.57-.11zm7.48-8.73-1.13 1.13-2.12-2.13 1.12-1.12c.09-.08.18-.15.27-.21.07-.05.15-.09.23-.12.08-.03.17-.06.25-.08a1.733 1.733 0 0 1 .63 0c.08.02.17.05.25.08.08.03.16.07.23.12.09.06.18.13.27.21.08.08.15.17.21.27.04.07.08.15.12.23.03.08.05.16.07.25.02.1.04.2.04.31s-.02.21-.04.31c-.02.09-.04.17-.07.25-.08.19-.19.36-.33.5zm-7.7 7.69 5.86-5.86L9 5.27l-5.86 5.86c-.1.1-.14.22-.14.36v1.91h1.91c.14 0 .26-.05.35-.15zm2.75.63c0-.28.22-.5.5-.5h5c.28 0 .5.22.5.5s-.22.5-.5.5h-5c-.28 0-.5-.22-.5-.5z\"\n />\n </svg>\n );\n}\n","import type { SVGProps } from 'react';\n\nexport function QueueTopIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\" {...props}>\n <path\n d=\"M16.77 5.15c.28 0 .5.23.5.5 0 .28-.22.5-.5.5H7.23a.5.5 0 0 1 0-1h9.54ZM10.86 7.93l-4.8 5.17a.69.69 0 0 0-.19.48l.01.08a.7.7 0 0 0 .7.63h2.27v3.02a1.56 1.56 0 0 0 1.56 1.56h3.18a1.56 1.56 0 0 0 1.56-1.56l-.01-3.02 2.28.01a.7.7 0 0 0 .48-.19.7.7 0 0 0 .04-.99l-4.8-5.17a1.4 1.4 0 0 0-1.99 0Zm1.52.65 4.38 4.71h-2.11a.5.5 0 0 0-.5.5v3.52a.56.56 0 0 1-.56.56h-3.18a.56.56 0 0 1-.56-.56v-3.52a.5.5 0 0 0-.5-.5h-2.11l4.35-4.68a.4.4 0 0 1 .59-.03ZM8.01 13.87a.5.5 0 0 1 .5-.5h5a.5.5 0 1 1 0 1h-5a.5.5 0 0 1-.5-.5Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\n","import type { SVGProps } from 'react';\n\nexport function QueueDeleteIcon(props: SVGProps<SVGSVGElement>) {\n return (\n <svg viewBox=\"0 0 16 16\" fill=\"none\" aria-hidden=\"true\" {...props}>\n <path\n d=\"M12.55 5.29c.25 0 .5.25.5.5v7.34a1.84 1.84 0 0 1-1.84 1.84H4.46a1.84 1.84 0 0 1-1.84-1.84V5.79c0-.25.25-.5.5-.5.25 0 .5.25.5.5v7.34c0 .42.33.84.83.84h6.76c.42 0 .84-.33.84-.84V5.79c0-.25.25-.5.5-.5ZM6.29 6.79c.25 0 .5.25.5.5v4.59c0 .17-.08.25-.17.33-.08.09-.25.17-.33.17-.34 0-.5-.25-.5-.5V7.29c0-.25.25-.5.5-.5Zm3.09 0c.25 0 .5.25.5.5v4.59c0 .25-.25.5-.5.5s-.5-.25-.5-.5V7.29c0-.25.25-.5.5-.5Zm0-5.75c.59 0 1.09.33 1.25.83l.5 1.75h3c.25 0 .5.25.5.5 0 .25-.25.5-.5.5H1.87c-.25 0-.5-.25-.5-.5 0-.25.25-.5.5-.5h2.92l.67-1.75c.17-.5.67-.83 1.17-.83h2.75Zm0 .92H6.71c-.17 0-.33.08-.33.17l-.5 1.42h4.25l-.42-1.42c-.08-.08-.17-.17-.33-.17Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n\n","'use client';\n\nimport { createPortal } from 'react-dom';\nimport { useEffect, useLayoutEffect, useRef, useState, type ReactNode, type RefObject } from 'react';\nimport type { QueueEntry } from '@/stores/chat-types';\nimport { buildQueueInlineSegments, type QueueInlineSegment } from '@/utils/queue-inline-segments';\nimport { resolveAttachmentIconByFileName } from './ImagePreview';\nimport { Button } from '../../shared/Button';\nimport { IconButton } from '../../shared/IconButton';\nimport { OverflowTooltip } from '../../shared/OverflowTooltip';\nimport { QueueEditIcon } from './icons/QueueEditIcon';\nimport { QueueTopIcon } from './icons/QueueTopIcon';\nimport { QueueDeleteIcon } from './icons/QueueDeleteIcon';\n\nconst CLEAR_CONFIRM_WIDTH = 248;\nconst CLEAR_CONFIRM_GAP = 10;\nconst VIEWPORT_PADDING = 8;\n\nfunction renderQueueSegment(segment: QueueInlineSegment, key: string): ReactNode {\n if (segment.kind === 'text') {\n return (\n <span key={key} className=\"text-[12px] leading-[16px] font-normal text-[var(--text-primary)]\">\n {segment.text}\n </span>\n );\n }\n if (segment.kind === 'mention') {\n return (\n <span key={key} className=\"text-[12px] leading-[16px] font-medium text-[rgb(20,118,255)]\">\n {segment.label}\n </span>\n );\n }\n if (segment.kind === 'skill') {\n return (\n <span key={key} className=\"inline-flex items-center gap-1 align-middle text-[var(--text-accent)]\">\n <span\n aria-hidden=\"true\"\n className=\"inline-block h-[14px] w-[14px] shrink-0\"\n style={{\n backgroundColor: 'currentColor',\n maskImage: \"url('/icons/menu/skills.svg')\",\n maskRepeat: 'no-repeat',\n maskPosition: 'center',\n maskSize: 'contain',\n WebkitMaskImage: \"url('/icons/menu/skills.svg')\",\n WebkitMaskRepeat: 'no-repeat',\n WebkitMaskPosition: 'center',\n WebkitMaskSize: 'contain',\n }}\n />\n <span className=\"text-[12px] leading-[16px]\">{segment.label}</span>\n </span>\n );\n }\n return (\n <span\n key={key}\n className=\"inline-flex items-center h-6 gap-1 rounded-full border border-[rgba(20,118,255,0.7)] bg-[var(--accent-soft)] px-2 py-1 align-middle text-[12px] leading-none text-[var(--text-primary)]\"\n >\n {segment.icon ? (\n <img src={segment.icon} alt=\"\" aria-hidden=\"true\" className=\"h-4 w-4 shrink-0\" />\n ) : (\n <span className=\"h-1.5 w-1.5 shrink-0 rounded-full bg-[var(--text-accent)]\" aria-hidden=\"true\" />\n )}\n <span className=\"max-w-[120px] truncate\">{segment.label}</span>\n </span>\n );\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.max(min, Math.min(value, max));\n}\n\ninterface ChatInputQueuePanelProps {\n queuedEntries: QueueEntry[];\n attachmentNamesByEntryId: Record<string, string[]>;\n queueCount: number;\n queueExpanded: boolean;\n queueBusy: boolean;\n queueHighlightedEntryId: string | null;\n listRef: RefObject<HTMLDivElement>;\n onToggleExpanded: () => void;\n onClear: () => void;\n onPinToTop: (entryId: string) => void;\n onEdit: (entryId: string) => void;\n onDelete: (entryId: string) => void;\n}\n\ninterface ConfirmPosition {\n top: number;\n left: number;\n arrowLeft: number;\n}\n\nexport function ChatInputQueuePanel({\n queuedEntries,\n attachmentNamesByEntryId,\n queueCount,\n queueExpanded,\n queueBusy,\n queueHighlightedEntryId,\n listRef,\n onToggleExpanded,\n onClear,\n onPinToTop,\n onEdit,\n onDelete,\n}: ChatInputQueuePanelProps) {\n const [showClearConfirm, setShowClearConfirm] = useState(false);\n const [confirmPosition, setConfirmPosition] = useState<ConfirmPosition | null>(null);\n const clearConfirmAnchorRef = useRef<HTMLDivElement>(null);\n const clearConfirmRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!showClearConfirm) return;\n\n const updatePosition = () => {\n const anchor = clearConfirmAnchorRef.current;\n const panel = clearConfirmRef.current;\n if (!anchor) return;\n const anchorRect = anchor.getBoundingClientRect();\n const panelHeight = panel?.getBoundingClientRect().height ?? 124;\n const maxLeft = window.innerWidth - CLEAR_CONFIRM_WIDTH - VIEWPORT_PADDING;\n const preferredLeft = anchorRect.right - CLEAR_CONFIRM_WIDTH;\n const left = clamp(preferredLeft, VIEWPORT_PADDING, maxLeft);\n const preferredTop = anchorRect.top - panelHeight - CLEAR_CONFIRM_GAP;\n const top = Math.max(VIEWPORT_PADDING, preferredTop);\n const anchorCenterX = anchorRect.left + anchorRect.width / 2;\n const arrowLeft = clamp(anchorCenterX - left, 14, CLEAR_CONFIRM_WIDTH - 14);\n setConfirmPosition({ top, left, arrowLeft });\n };\n\n updatePosition();\n window.addEventListener('resize', updatePosition);\n window.addEventListener('scroll', updatePosition, true);\n return () => {\n window.removeEventListener('resize', updatePosition);\n window.removeEventListener('scroll', updatePosition, true);\n };\n }, [showClearConfirm]);\n\n useEffect(() => {\n if (!showClearConfirm) return;\n\n const handlePointerDown = (event: MouseEvent) => {\n const target = event.target;\n if (!(target instanceof Node)) return;\n if (clearConfirmAnchorRef.current?.contains(target)) return;\n if (clearConfirmRef.current?.contains(target)) return;\n setShowClearConfirm(false);\n };\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') setShowClearConfirm(false);\n };\n\n window.addEventListener('mousedown', handlePointerDown);\n window.addEventListener('keydown', handleKeyDown);\n return () => {\n window.removeEventListener('mousedown', handlePointerDown);\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [showClearConfirm]);\n\n if (queueCount === 0) return null;\n\n return (\n <div\n className={`w-full min-w-0 max-w-full overflow-hidden rounded-t-[24px] rounded-b-none border chat-input-shell bg-[var(--surface-panel)] transition-[padding,border-color] duration-200 ${queueExpanded ? 'pb-5' : 'pb-4'}`}\n >\n <div className=\"flex min-h-[44px] items-center justify-between px-[18px] py-[13px]\">\n <button\n type=\"button\"\n onClick={onToggleExpanded}\n className=\"inline-flex min-w-0 items-center gap-1 rounded-[10px] text-[14px] leading-[22px] font-normal text-[var(--text-primary)] transition-colors\"\n aria-expanded={queueExpanded}\n aria-label=\"展开或收起待执行任务\"\n >\n <span>待执行任务({queueCount})</span>\n <svg\n className={`h-4 w-4 shrink-0 text-[var(--text-label-secondary)] transition-transform duration-200 ${queueExpanded ? 'rotate-180' : ''}`}\n viewBox=\"0 0 20 20\"\n fill=\"currentColor\"\n >\n <path\n fillRule=\"evenodd\"\n d=\"M5.23 7.21a.75.75 0 011.06.02L10 11.167l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.51a.75.75 0 01-1.08 0l-4.25-4.51a.75.75 0 01.02-1.06z\"\n clipRule=\"evenodd\"\n />\n </svg>\n </button>\n\n <div ref={clearConfirmAnchorRef}>\n {showClearConfirm ? (\n <IconButton\n label=\"一键清空队列\"\n size=\"sm\"\n disabled={queueBusy || queueCount === 0}\n onClick={() => setShowClearConfirm(false)}\n icon={<img src=\"/icons/icon-clear-all.svg\" alt=\"一键清空\" />}\n />\n ) : (\n <OverflowTooltip content=\"一键清空\" forceShow className=\"inline-flex\">\n <IconButton\n label=\"一键清空队列\"\n size=\"sm\"\n disabled={queueBusy || queueCount === 0}\n onClick={() => setShowClearConfirm(true)}\n icon={<img src=\"/icons/icon-clear-all.svg\" alt=\"一键清空\" />}\n />\n </OverflowTooltip>\n )}\n </div>\n </div>\n\n {showClearConfirm &&\n createPortal(\n <div\n ref={clearConfirmRef}\n className=\"fixed z-[320] w-[248px]\"\n style={\n confirmPosition\n ? { top: `${confirmPosition.top}px`, left: `${confirmPosition.left}px` }\n : { top: '-9999px', left: '-9999px' }\n }\n >\n <div className=\"relative overflow-tooltip rounded-lg bg-[var(--tooltip-surface)] p-4 text-[var(--tooltip-text)] shadow-[var(--tooltip-shadow)]\">\n <div className=\"flex items-start gap-3\">\n <img src=\"/icons/message-warn.svg\" alt=\"\" aria-hidden=\"true\" className=\"mt-0.5 h-4 w-4 flex-shrink-0\" />\n <p className=\"text-[12px] leading-5\">确认要一键清空所有执行任务吗?</p>\n </div>\n <div className=\"mt-4 flex items-center justify-end gap-2\">\n <Button variant=\"default\" className=\"!py-[3px] !px-[20px] !min-w-[62px] !h-[24px]\" onClick={() => setShowClearConfirm(false)}>\n 取消\n </Button>\n <Button\n className=\"!py-[3px] !px-[20px] !min-w-[62px] !h-[24px]\"\n disabled={queueBusy}\n onClick={() => {\n setShowClearConfirm(false);\n onClear();\n }}\n >\n 确定\n </Button>\n </div>\n <span\n aria-hidden=\"true\"\n className=\"absolute top-full h-0 w-0 -translate-x-1/2 border-x-[6px] border-t-[6px] border-x-transparent border-t-[var(--tooltip-surface)]\"\n style={{ left: `${confirmPosition?.arrowLeft ?? CLEAR_CONFIRM_WIDTH - 20}px` }}\n />\n </div>\n </div>,\n document.body,\n )}\n\n {queueExpanded && (\n <div className=\"border-t border-[var(--border-default)]/70 pt-1 px-[10px] pb-[10px]\">\n <div ref={listRef} className=\"max-h-[188px] overflow-y-auto\">\n {queuedEntries.map((entry, index) => {\n const inlineSegments = buildQueueInlineSegments(entry.content);\n const attachmentNames = attachmentNamesByEntryId[entry.id] ?? entry.attachmentNames ?? [];\n const tooltipContent =\n attachmentNames.length > 0 ? `${entry.content} ${attachmentNames.join(' ')}` : entry.content;\n return (\n <div\n key={entry.id}\n className={`group/queue-row h-[34px] relative mt-1 first:mt-0 flex min-h-[34px] min-w-0 items-center rounded-[8px] p-2 transition-[background-color,box-shadow,transform,opacity] duration-200 ${queueHighlightedEntryId === entry.id ? 'bg-[rgba(20,118,255,0.08)] shadow-[0_0_0_1px_rgba(20,118,255,0.16)]' : 'hover:bg-[var(--chat-queue-row-hover-bg)]'}`}\n >\n <svg viewBox=\"0 0 24 24\" className=\"mr-2 h-4 w-4 text-[var(--text-label-secondary)]\" fill=\"none\">\n <rect id=\"time\" width=\"24.000000\" height=\"24.000000\" x=\"0.000000\" y=\"0.000000\" />\n <path\n id=\"path\"\n d=\"M12 1.5C6.15 1.5 1.5 6.15 1.5 12C1.5 17.85 6.15 22.5 12 22.5C17.85 22.5 22.5 17.85 22.5 12C22.5 6.15 17.85 1.5 12 1.5ZM12 21C7.05 21 3 16.95 3 12C3 7.05 7.05 3 12 3C16.95 3 21 7.05 21 12C21 16.95 16.95 21 12 21ZM15 12.6C15 13.2 14.7 13.5 14.25 13.5L11.55 13.5C10.95 13.5 10.5 13.05 10.5 12.45L10.5 8.25C10.5 7.8 10.8 7.5 11.25 7.5C11.7 7.5 12 7.8 12 8.25L12 12L14.25 12C14.55 12 14.85 12.3 15 12.6Z\"\n fill=\"currentColor\"\n fillRule=\"nonzero\"\n />\n </svg>\n <OverflowTooltip content={tooltipContent} className=\"mr-3 min-w-0 max-w-full flex-1 overflow-hidden\">\n <div className=\"block w-full min-w-0 overflow-hidden text-ellipsis whitespace-nowrap\">\n {inlineSegments.map((segment, segIndex) =>\n renderQueueSegment(segment, `${entry.id}-${segIndex}`),\n )}\n {attachmentNames.map((fileName, attachmentIndex) => (\n <span\n key={`${entry.id}-attachment-${attachmentIndex}`}\n className=\"ml-2 inline-flex items-center gap-1 align-middle text-[12px] leading-[16px] font-normal text-[var(--text-primary)]\"\n >\n <img\n src={resolveAttachmentIconByFileName(fileName)}\n alt=\"\"\n aria-hidden=\"true\"\n className=\"h-4 w-4 shrink-0\"\n />\n <span>{fileName}</span>\n </span>\n ))}\n </div>\n </OverflowTooltip>\n <div className=\"flex w-[102px] shrink-0 items-center justify-end gap-1\">\n {index > 0 ? (\n <OverflowTooltip content=\"置顶\" forceShow className=\"inline-flex\">\n <IconButton\n label=\"置顶\"\n size=\"sm\"\n disabled={queueBusy}\n onClick={() => onPinToTop(entry.id)}\n className={`opacity-0 pointer-events-none group-hover/queue-row:pointer-events-auto group-hover/queue-row:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 hover:bg-[var(--chat-queue-action-hover-bg)] focus-visible:bg-[var(--chat-queue-action-hover-bg)] ${queueHighlightedEntryId === entry.id ? 'text-[var(--text-accent)]' : ''}`}\n icon={<QueueTopIcon className=\"h-4 w-4\" />}\n />\n </OverflowTooltip>\n ) : (\n <span className=\"inline-flex h-6 w-6 shrink-0\" aria-hidden=\"true\" />\n )}\n <OverflowTooltip content=\"编辑\" forceShow className=\"inline-flex\">\n <IconButton\n label=\"编辑\"\n size=\"sm\"\n disabled={queueBusy}\n onClick={() => onEdit(entry.id)}\n className=\"opacity-0 pointer-events-none group-hover/queue-row:pointer-events-auto group-hover/queue-row:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 hover:bg-[var(--chat-queue-action-hover-bg)] focus-visible:bg-[var(--chat-queue-action-hover-bg)]\"\n icon={<QueueEditIcon className=\"h-4 w-4\" />}\n />\n </OverflowTooltip>\n <OverflowTooltip content=\"删除\" forceShow className=\"inline-flex\">\n <IconButton\n label=\"删除\"\n size=\"sm\"\n disabled={queueBusy}\n onClick={() => onDelete(entry.id)}\n className=\"opacity-0 pointer-events-none group-hover/queue-row:pointer-events-auto group-hover/queue-row:opacity-100 focus-visible:pointer-events-auto focus-visible:opacity-100 hover:bg-[var(--chat-queue-action-hover-bg)] focus-visible:bg-[var(--chat-queue-action-hover-bg)]\"\n icon={<QueueDeleteIcon className=\"h-4 w-4\" />}\n />\n </OverflowTooltip>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n )}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { KeyboardEvent, useCallback, useEffect, useRef, useState } from 'react';\nimport { useInputHistoryStore } from '@/stores/inputHistoryStore';\n\ninterface HistorySearchModalProps {\n onSelect: (text: string) => void;\n onClose: () => void;\n}\n\nexport function HistorySearchModal({ onSelect, onClose }: HistorySearchModalProps) {\n const [query, setQuery] = useState('');\n const [selectedIdx, setSelectedIdx] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n const search = useInputHistoryStore((s) => s.search);\n\n const results = query ? search(query) : useInputHistoryStore.getState().entries.slice(0, 20);\n\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n useEffect(() => {\n setSelectedIdx(0);\n }, []);\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n onClose();\n return;\n }\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedIdx((i) => Math.min(i + 1, results.length - 1));\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedIdx((i) => Math.max(i - 1, 0));\n return;\n }\n if (e.key === 'Enter' && results.length > 0 && !e.nativeEvent.isComposing) {\n e.preventDefault();\n onSelect(results[selectedIdx]);\n }\n },\n [results, selectedIdx, onSelect, onClose],\n );\n\n return (\n <div\n data-testid=\"history-search\"\n className=\"absolute bottom-full left-0 right-0 z-20 mb-1 mx-4 overflow-hidden rounded-xl border border-[var(--modal-border)] bg-[var(--modal-surface)] shadow-[var(--modal-shadow)]\"\n >\n <div className=\"flex items-center gap-2 border-b border-[var(--modal-divider)] px-3 py-2\">\n <span className=\"text-xs font-mono text-[var(--modal-text-subtle)]\">Ctrl+R</span>\n <input\n ref={inputRef}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Search history...\"\n className=\"ui-input ui-input-plain flex-1 text-sm\"\n />\n <button onClick={onClose} className=\"text-xs text-[var(--modal-text-subtle)] transition-colors hover:text-[var(--modal-text)]\">\n Esc\n </button>\n </div>\n <div className=\"max-h-48 overflow-y-auto\">\n {results.length === 0 && <div className=\"px-3 py-2 text-xs text-[var(--modal-empty-text)]\">No matches</div>}\n {results.map((entry, i) => (\n <button\n key={`${i}-${entry}`}\n className={`w-full text-left px-3 py-1.5 text-sm truncate transition-colors ${\n i === selectedIdx\n ? 'bg-[var(--modal-muted-surface)] text-[var(--modal-text)]'\n : 'text-[var(--modal-text-muted)] hover:bg-[var(--modal-muted-surface)]'\n }`}\n onMouseEnter={() => setSelectedIdx(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n onSelect(entry);\n }}\n >\n {entry}\n </button>\n ))}\n </div>\n <div className=\"border-t border-[var(--modal-divider)] px-3 py-1 text-[10px] text-[var(--modal-text-subtle)]\">\n {'\\u2191\\u2193 \\u9009\\u62E9 \\u00B7 Enter \\u786E\\u8BA4 \\u00B7 Esc \\u5173\\u95ED'}\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n/**\n * F080-P2: Path completion dropdown menu.\n * Displays file/directory candidates from the API.\n */\n\n'use client';\n\nimport type { PathEntry } from '@/hooks/usePathCompletion';\n\ninterface PathCompletionMenuProps {\n entries: PathEntry[];\n selectedIdx: number;\n onSelectIdx: (i: number) => void;\n onSelect: (entry: PathEntry) => void;\n}\n\nexport function PathCompletionMenu({ entries, selectedIdx, onSelectIdx, onSelect }: PathCompletionMenuProps) {\n if (entries.length === 0) return null;\n\n return (\n <div\n data-testid=\"path-completion-menu\"\n className=\"absolute bottom-full left-4 mb-2 bg-white rounded-xl shadow-lg border border-gray-200 overflow-hidden w-80 z-10 max-h-64 flex flex-col\"\n >\n <div className=\"overflow-y-auto flex-1\">\n {entries.map((entry, i) => (\n <button\n key={entry.path}\n className={`w-full text-left px-3 py-2 flex items-center gap-2 transition-colors text-sm ${\n i === selectedIdx ? 'bg-gray-50' : 'hover:bg-gray-50'\n }`}\n onMouseEnter={() => onSelectIdx(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n onSelect(entry);\n }}\n >\n <span className=\"text-base w-5 text-center shrink-0\">\n {entry.isDirectory ? '\\uD83D\\uDCC1' : '\\uD83D\\uDCC4'}\n </span>\n <span className=\"truncate font-mono text-xs text-gray-700\">{entry.name}</span>\n </button>\n ))}\n </div>\n <div className=\"px-3 py-1 text-[10px] text-gray-400 border-t border-gray-100 shrink-0\">\n Tab/Enter 选择 · Esc 关闭\n </div>\n </div>\n );\n}\n","'use client';\n\nimport type { QuickActionConfig } from '@/config/quick-actions';\nimport type { RefObject } from 'react';\nimport { MaskIcon } from '@/components/shared/MaskIcon';\nimport {\n EXPERT_CARD_BUTTON_CLASS,\n QUICK_ACTION_BUTTON_CLASS,\n QUICK_ACTION_EXPAND_BUTTON_CLASS,\n QUICK_PROMPT_BUTTON_CLASS,\n} from '../utils/constants';\n\nfunction QuickActionExpandIcon({ expanded }: { expanded: boolean }) {\n return (\n <svg\n aria-hidden=\"true\"\n className=\"h-3 w-3\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n {expanded ? <path d=\"M6 9l6 6 6-6\" /> : <path d=\"M18 15l-6-6-6 6\" />}\n </svg>\n );\n}\n\nfunction renderExpertCardPreview(card: NonNullable<QuickActionConfig['expertCards']>[number]) {\n const mentionMatch = card.content.match(/^((?:@[^@\\s,,]+)+)([,,]?)(.*)$/);\n if (!mentionMatch) {\n return (\n <>\n <span className=\"font-medium text-[var(--text-accent)]\">@{card.agentName}</span>,{card.content}\n </>\n );\n }\n\n const mentions = mentionMatch[1].match(/@[^@\\s,,]+/g) ?? [];\n const separator = mentionMatch[2] || ',';\n const rest = mentionMatch[3];\n\n return (\n <>\n {mentions.map((mention, index) => (\n <span key={`${card.agentId}-${mention}-${index}`}>\n {index > 0 ? ' ' : ''}\n <span className=\"font-medium text-[var(--text-accent)]\">{mention}</span>\n </span>\n ))}\n {rest ? `${separator}${rest}` : null}\n </>\n );\n}\n\ninterface QuickActionsPanelProps {\n showQuickPrompts: boolean;\n quickActionsExpanded: boolean;\n quickActionsOverflowing: boolean;\n visibleQuickActions: QuickActionConfig[];\n selectedQuickAction: QuickActionConfig | null;\n queueAwareDisabled: boolean;\n quickActionsContainerRef: RefObject<HTMLDivElement | null>;\n quickActionsRowRef: RefObject<HTMLDivElement | null>;\n onQuickAction: (action: QuickActionConfig) => void;\n onQuickPrompt: (prompt: string) => void;\n onExpertCardClick: (card: NonNullable<QuickActionConfig['expertCards']>[number]) => void;\n onToggleExpanded: () => void;\n}\n\nexport function QuickActionsPanel({\n showQuickPrompts,\n quickActionsExpanded,\n quickActionsOverflowing,\n visibleQuickActions,\n selectedQuickAction,\n queueAwareDisabled,\n quickActionsContainerRef,\n quickActionsRowRef,\n onQuickAction,\n onQuickPrompt,\n onExpertCardClick,\n onToggleExpanded,\n}: QuickActionsPanelProps) {\n return (\n <>\n {!showQuickPrompts && (\n <div\n ref={quickActionsContainerRef}\n className={`relative mb-2 flex gap-2 ${quickActionsExpanded ? 'items-end' : 'items-start'}`}\n >\n <div\n ref={quickActionsRowRef}\n className={`flex min-w-0 flex-1 items-center gap-2 ${\n quickActionsExpanded ? 'flex-wrap overflow-visible' : 'flex-nowrap overflow-hidden'\n } ${\n quickActionsOverflowing && !quickActionsExpanded ? 'chat-input-quick-actions-fade' : ''\n }`}\n data-testid=\"chat-input-quick-actions-row\"\n >\n {visibleQuickActions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n data-quick-action-button=\"true\"\n onClick={() => onQuickAction(action)}\n disabled={queueAwareDisabled}\n className={QUICK_ACTION_BUTTON_CLASS}\n >\n <MaskIcon src={action.icon} className=\"h-4 w-4 text-[var(--mask-icon)]\" />\n <span>{action.label}</span>\n </button>\n ))}\n </div>\n {quickActionsOverflowing && (\n <button\n type=\"button\"\n aria-label={quickActionsExpanded ? '收起快捷操作' : '展开快捷操作'}\n className={`${QUICK_ACTION_EXPAND_BUTTON_CLASS} ${quickActionsExpanded ? 'self-end' : 'mt-[7px] self-start'}`}\n onClick={onToggleExpanded}\n >\n <QuickActionExpandIcon expanded={quickActionsExpanded} />\n </button>\n )}\n </div>\n )}\n {showQuickPrompts && selectedQuickAction && (\n <div\n className=\"mb-2 grid gap-2\"\n style={{\n gridTemplateColumns: selectedQuickAction.expertCards\n ? 'repeat(3, minmax(0, 1fr))'\n : `repeat(${selectedQuickAction.prompts.length}, minmax(0, 1fr))`,\n }}\n >\n {selectedQuickAction.expertCards\n ? selectedQuickAction.expertCards.map((card) => (\n <button\n key={card.agentId}\n type=\"button\"\n onClick={() => onExpertCardClick(card)}\n className={EXPERT_CARD_BUTTON_CLASS}\n >\n <p className=\"line-clamp-4 text-[13px] leading-[20px] text-[var(--text-secondary)]\">\n {renderExpertCardPreview(card)}\n </p>\n </button>\n ))\n : selectedQuickAction.prompts.map((prompt) => (\n <button key={prompt} type=\"button\" onClick={() => onQuickPrompt(prompt)} className={QUICK_PROMPT_BUTTON_CLASS}>\n {prompt}\n </button>\n ))}\n </div>\n )}\n </>\n );\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { useEffect, type RefObject } from 'react';\nimport type { ParsedPrompt } from '@/utils/promptParser';\n\ninterface UsePromptBlockKeyboardNavigationParams {\n containerRef: RefObject<HTMLElement>;\n parsed: ParsedPrompt;\n onFocus: (id: string) => void;\n onBlur: () => void;\n onDelete?: (id: string) => void;\n}\n\ntype CaretEdge = 'start' | 'end';\ntype ArrowDirection = 'left' | 'right';\n\nfunction isEditableTextPlaceholder(element: HTMLElement): boolean {\n return element.getAttribute('contenteditable') === 'true';\n}\n\nfunction findPlaceholderControl(container: HTMLElement, placeholderId: string): HTMLElement | null {\n return (\n Array.from(container.querySelectorAll<HTMLElement>('[data-placeholder-control=\"true\"]')).find(\n (element) => element.dataset.placeholderId === placeholderId,\n ) ?? null\n );\n}\n\nfunction findFixedBlock(container: HTMLElement, blockIndex: number): HTMLElement | null {\n return (\n Array.from(container.querySelectorAll<HTMLElement>('[data-block-index]')).find(\n (element) => Number(element.dataset.blockIndex) === blockIndex,\n ) ?? null\n );\n}\n\nfunction placeCaretInFixedBlock(\n container: HTMLElement,\n blockIndex: number,\n edge: CaretEdge,\n onBlur: () => void,\n): boolean {\n const fixedBlock = findFixedBlock(container, blockIndex);\n const selection = window.getSelection();\n if (!fixedBlock || !selection) return false;\n\n fixedBlock.focus();\n onBlur();\n\n const range = document.createRange();\n range.selectNodeContents(fixedBlock);\n range.collapse(edge === 'start');\n selection.removeAllRanges();\n selection.addRange(range);\n return true;\n}\n\nfunction focusPlaceholder(\n container: HTMLElement,\n placeholderId: string,\n edge: CaretEdge,\n onFocus: (id: string) => void,\n): boolean {\n const control = findPlaceholderControl(container, placeholderId);\n if (!control) return false;\n\n control.focus();\n if (control instanceof HTMLInputElement) {\n const caret = edge === 'start' ? 0 : control.value.length;\n control.setSelectionRange(caret, caret);\n } else if (isEditableTextPlaceholder(control)) {\n placeCaretInEditableElement(control, edge);\n }\n onFocus(placeholderId);\n return true;\n}\n\nfunction placeCaretAtContainerEdge(container: HTMLElement, edge: CaretEdge, onBlur: () => void): boolean {\n const selection = window.getSelection();\n if (!selection) return false;\n\n container.focus();\n onBlur();\n\n const range = document.createRange();\n range.selectNodeContents(container);\n range.collapse(edge === 'start');\n selection.removeAllRanges();\n selection.addRange(range);\n return true;\n}\n\nfunction moveToBlockBoundary(\n container: HTMLElement,\n parsed: ParsedPrompt,\n blockIndex: number,\n edge: CaretEdge,\n onFocus: (id: string) => void,\n onBlur: () => void,\n): boolean {\n const block = parsed.blocks[blockIndex];\n if (!block) return placeCaretAtContainerEdge(container, edge, onBlur);\n\n if (block.type === 'fixed') {\n return placeCaretInFixedBlock(container, blockIndex, edge, onBlur);\n }\n\n return focusPlaceholder(container, block.placeholder.id, edge, onFocus);\n}\n\nfunction moveFromBlock(\n container: HTMLElement,\n parsed: ParsedPrompt,\n blockIndex: number,\n direction: ArrowDirection,\n onFocus: (id: string) => void,\n onBlur: () => void,\n): boolean {\n const targetIndex = direction === 'left' ? blockIndex - 1 : blockIndex + 1;\n const targetEdge = direction === 'left' ? 'end' : 'start';\n return moveToBlockBoundary(container, parsed, targetIndex, targetEdge, onFocus, onBlur);\n}\n\nfunction getPlaceholderBlockIndex(parsed: ParsedPrompt, placeholderId: string): number {\n return parsed.blocks.findIndex(\n (block) => block.type === 'placeholder' && block.placeholder.id === placeholderId,\n );\n}\n\nfunction hasTrailingCaretTarget(parsed: ParsedPrompt, blockIndex: number): boolean {\n const nextBlock = parsed.blocks[blockIndex + 1];\n return blockIndex === parsed.blocks.length - 2 && nextBlock?.type === 'fixed' && nextBlock.content.length === 0;\n}\n\nfunction getFixedBlockIndexFromRange(container: HTMLElement, range: Range): number | null {\n const startNode = range.startContainer;\n const startElement = startNode instanceof Element ? startNode : startNode.parentElement;\n const fixedBlock = startElement?.closest<HTMLElement>('[data-block-index]');\n if (!fixedBlock || !container.contains(fixedBlock)) return null;\n\n const blockIndex = Number(fixedBlock.dataset.blockIndex);\n return Number.isFinite(blockIndex) ? blockIndex : null;\n}\n\nfunction getCaretTextOffset(range: Range, container: HTMLElement): number | null {\n if (!container.contains(range.startContainer)) return null;\n\n const beforeCaret = document.createRange();\n beforeCaret.selectNodeContents(container);\n beforeCaret.setEnd(range.startContainer, range.startOffset);\n return beforeCaret.toString().length;\n}\n\nfunction isCaretAtBoundary(range: Range, container: HTMLElement, edge: CaretEdge): boolean {\n const caretOffset = getCaretTextOffset(range, container);\n if (caretOffset === null) return false;\n\n return edge === 'start' ? caretOffset === 0 : caretOffset === container.textContent?.length;\n}\n\nfunction isFixedCaretAtBoundary(range: Range, fixedBlock: HTMLElement, edge: CaretEdge): boolean {\n return isCaretAtBoundary(range, fixedBlock, edge);\n}\n\nfunction getActivePlaceholderControl(container: HTMLElement): HTMLElement | null {\n const activeElement = document.activeElement;\n if (!(activeElement instanceof HTMLElement)) return null;\n if (!container.contains(activeElement)) return null;\n return activeElement.dataset.placeholderControl === 'true' ? activeElement : null;\n}\n\nfunction shouldMoveFromTextInput(input: HTMLInputElement, direction: ArrowDirection): boolean {\n const selectionStart = input.selectionStart ?? 0;\n const selectionEnd = input.selectionEnd ?? selectionStart;\n if (selectionStart !== selectionEnd) return false;\n\n return direction === 'left' ? selectionStart === 0 : selectionEnd === input.value.length;\n}\n\nfunction getEditableTextNode(element: HTMLElement, edge: CaretEdge): Text | null {\n const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);\n let current = walker.nextNode() as Text | null;\n let candidate: Text | null = null;\n\n while (current) {\n if (current.data.length > 0) {\n candidate = current;\n if (edge === 'start') return candidate;\n }\n current = walker.nextNode() as Text | null;\n }\n\n return candidate;\n}\n\nfunction placeCaretInEditableElement(element: HTMLElement, edge: CaretEdge): boolean {\n const selection = window.getSelection();\n if (!selection) return false;\n\n const range = document.createRange();\n const textNode = getEditableTextNode(element, edge);\n if (textNode) {\n range.setStart(textNode, edge === 'start' ? 0 : textNode.data.length);\n } else {\n range.selectNodeContents(element);\n range.collapse(edge === 'start');\n }\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n return true;\n}\n\nfunction shouldMoveFromEditableText(element: HTMLElement, direction: ArrowDirection): boolean {\n const selection = window.getSelection();\n if (!selection || selection.rangeCount === 0) return false;\n\n const range = selection.getRangeAt(0);\n if (!range.collapsed) return false;\n\n const edge = direction === 'left' ? 'start' : 'end';\n return isCaretAtBoundary(range, element, edge);\n}\n\nfunction shouldMoveFromPlaceholderControl(control: HTMLElement, direction: ArrowDirection): boolean {\n if (control instanceof HTMLInputElement) {\n return shouldMoveFromTextInput(control, direction);\n }\n if (isEditableTextPlaceholder(control)) {\n return shouldMoveFromEditableText(control, direction);\n }\n return true;\n}\n\nexport function usePromptBlockKeyboardNavigation({\n containerRef,\n parsed,\n onFocus,\n onBlur,\n onDelete,\n}: UsePromptBlockKeyboardNavigationParams & { onDelete?: (id: string) => void }) {\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n const activePlaceholderControl = getActivePlaceholderControl(container);\n const selection = window.getSelection();\n const range = selection?.rangeCount ? selection.getRangeAt(0) : null;\n\n // Handle Backspace\n if (event.key === 'Backspace' && range && range.collapsed) {\n const fixedBlockIndex = getFixedBlockIndexFromRange(container, range);\n const fixedBlock = fixedBlockIndex !== null ? findFixedBlock(container, fixedBlockIndex) : null;\n\n // Backspace at start of fixed block - try to delete preceding placeholder\n if (fixedBlock && isFixedCaretAtBoundary(range, fixedBlock, 'start') && fixedBlockIndex !== null) {\n const placeholderIndex = fixedBlockIndex - 1;\n if (placeholderIndex >= 0) {\n const block = parsed.blocks[placeholderIndex];\n if (block?.type === 'placeholder') {\n event.preventDefault();\n onDelete?.(block.placeholder.id);\n // Position cursor at end of block before deleted placeholder\n const targetIndex = placeholderIndex - 1;\n const targetBlock = parsed.blocks[targetIndex];\n if (targetBlock?.type === 'fixed') {\n moveToBlockBoundary(container, parsed, targetIndex, 'end', onFocus, onBlur);\n } else if (targetBlock?.type === 'placeholder') {\n focusPlaceholder(container, targetBlock.placeholder.id, 'end', onFocus);\n } else {\n placeCaretAtContainerEdge(container, 'end', onBlur);\n }\n return;\n }\n }\n }\n\n // Backspace in fixed block (not at boundary) - let browser handle normally\n if (fixedBlockIndex !== null) return;\n\n // Backspace at start of placeholder content - delete placeholder\n if (activePlaceholderControl) {\n const placeholderId = activePlaceholderControl.dataset.placeholderId;\n if (!placeholderId) return;\n\n const blockIndex = getPlaceholderBlockIndex(parsed, placeholderId);\n if (blockIndex < 0) return;\n\n const block = parsed.blocks[blockIndex];\n if (block?.type !== 'placeholder') return;\n\n // Check if caret is at start of placeholder content\n const caretOffset = getCaretTextOffset(range, activePlaceholderControl);\n if (caretOffset === 0) {\n event.preventDefault();\n onDelete?.(placeholderId);\n // Position cursor at block before deleted placeholder\n const targetIndex = blockIndex - 1;\n if (targetIndex >= 0) {\n const targetBlock = parsed.blocks[targetIndex];\n if (targetBlock?.type === 'fixed') {\n moveToBlockBoundary(container, parsed, targetIndex, 'end', onFocus, onBlur);\n } else if (targetBlock?.type === 'placeholder') {\n focusPlaceholder(container, targetBlock.placeholder.id, 'end', onFocus);\n } else {\n placeCaretAtContainerEdge(container, 'end', onBlur);\n }\n } else {\n placeCaretAtContainerEdge(container, 'start', onBlur);\n }\n return;\n }\n }\n return;\n }\n\n // Handle End from the final placeholder. Browser-native End stays inside\n // the nested contenteditable placeholder; move to the trailing edit point.\n if (event.key === 'End') {\n if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;\n if (!activePlaceholderControl) return;\n if (!shouldMoveFromPlaceholderControl(activePlaceholderControl, 'right')) return;\n\n const placeholderId = activePlaceholderControl.dataset.placeholderId;\n if (!placeholderId) return;\n\n const blockIndex = getPlaceholderBlockIndex(parsed, placeholderId);\n if (blockIndex < 0 || !hasTrailingCaretTarget(parsed, blockIndex)) return;\n\n event.preventDefault();\n moveFromBlock(container, parsed, blockIndex, 'right', onFocus, onBlur);\n return;\n }\n\n // Handle ArrowLeft/ArrowRight\n if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return;\n if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return;\n\n const direction: ArrowDirection = event.key === 'ArrowLeft' ? 'left' : 'right';\n\n if (activePlaceholderControl) {\n const placeholderId = activePlaceholderControl.dataset.placeholderId;\n if (!placeholderId) return;\n if (!shouldMoveFromPlaceholderControl(activePlaceholderControl, direction)) {\n return;\n }\n\n const blockIndex = getPlaceholderBlockIndex(parsed, placeholderId);\n if (blockIndex < 0) return;\n\n event.preventDefault();\n moveFromBlock(container, parsed, blockIndex, direction, onFocus, onBlur);\n return;\n }\n\n if (!range || !range.collapsed) return;\n\n const fixedBlockIndex = getFixedBlockIndexFromRange(container, range);\n if (fixedBlockIndex === null) return;\n\n const fixedBlock = findFixedBlock(container, fixedBlockIndex);\n if (!fixedBlock) return;\n\n const edge = direction === 'left' ? 'start' : 'end';\n if (!isFixedCaretAtBoundary(range, fixedBlock, edge)) return;\n\n event.preventDefault();\n moveFromBlock(container, parsed, fixedBlockIndex, direction, onFocus, onBlur);\n };\n\n container.addEventListener('keydown', handleKeyDown);\n return () => container.removeEventListener('keydown', handleKeyDown);\n }, [containerRef, onBlur, onFocus, onDelete, parsed]);\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { useCallback } from 'react';\nimport { apiFetch } from '@/utils/api-client';\nimport {\n buildDefaultInspirationWorkspacePath,\n buildInspirationUploadPath,\n} from '@/utils/inspiration-workspace-path';\nimport { usePlaceholderStore } from '../stores/placeholderStore';\n\nasync function resolveDefaultWorkspacePath(): Promise<string | null> {\n try {\n const response = await apiFetch('/api/projects/cwd');\n if (!response.ok) return null;\n const data = await response.json().catch(() => null);\n const workspaceRoot = typeof data?.workspacePath === 'string' ? data.workspacePath.trim() : '';\n return buildDefaultInspirationWorkspacePath(workspaceRoot) || null;\n } catch {\n return null;\n }\n}\n\n/**\n * 复用现有附件上传机制\n * 存储路径格式: {workspacePath}/upload/{filename}\n */\nexport function usePlaceholderFileUpload() {\n const setFileValue = usePlaceholderStore((s) => s.setFileValue);\n const removeFileValue = usePlaceholderStore((s) => s.removeFileValue);\n const setWorkspacePath = usePlaceholderStore((s) => s.setWorkspacePath);\n const workspacePath = usePlaceholderStore((s) => s.workspacePath);\n\n const uploadFile = useCallback(\n async (placeholderId: string, file: File): Promise<{ path: string; name: string }> => {\n const resolvedWorkspacePath = workspacePath?.trim() || (await resolveDefaultWorkspacePath());\n if (resolvedWorkspacePath) {\n setWorkspacePath(resolvedWorkspacePath);\n }\n const storedPath = buildInspirationUploadPath(resolvedWorkspacePath ?? '', file.name);\n\n setFileValue(placeholderId, {\n path: storedPath,\n name: file.name,\n file, // Store the actual File object for sending\n });\n\n return { path: storedPath, name: file.name };\n },\n [setFileValue, setWorkspacePath, workspacePath],\n );\n\n const deleteFile = useCallback(\n (placeholderId: string) => {\n removeFileValue(placeholderId);\n },\n [removeFileValue],\n );\n\n return {\n uploadFile,\n deleteFile,\n };\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { useCallback, useState } from 'react';\nimport { usePlaceholderStore } from '@/stores/placeholderStore';\nimport { usePlaceholderFileUpload } from '@/hooks/usePlaceholderFileUpload';\nimport type { FilePlaceholder } from '@/utils/promptParser';\nimport { getFileTypeIcon } from '@/hooks/usePromptBlocks';\n\ninterface FilePlaceholderBlockProps {\n placeholder: FilePlaceholder;\n isActive: boolean;\n onFocus: () => void;\n onBlur: () => void;\n onDelete: () => void;\n onTabNext: () => void;\n}\n\nexport function FilePlaceholderBlock({\n placeholder,\n isActive,\n onFocus,\n onBlur,\n onDelete,\n onTabNext,\n}: FilePlaceholderBlockProps) {\n const fileValue = usePlaceholderStore((s) => s.fileValues[placeholder.id] ?? null);\n const { uploadFile, deleteFile } = usePlaceholderFileUpload();\n const [isHovered, setIsHovered] = useState(false);\n\n const hasFile = fileValue !== null;\n\n const handleIconClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation();\n if (hasFile) {\n deleteFile(placeholder.id);\n }\n },\n [hasFile, placeholder.id, deleteFile]\n );\n\n const handleClick = useCallback(() => {\n if (hasFile) return;\n\n const input = document.createElement('input');\n input.type = 'file';\n input.accept = placeholder.formats.length > 0 ? `.${placeholder.formats.join(',.')}` : '*/*';\n\n input.onchange = async (e) => {\n const file = (e.target as HTMLInputElement).files?.[0];\n if (!file) return;\n await uploadFile(placeholder.id, file);\n };\n\n input.click();\n }, [hasFile, placeholder.id, placeholder.formats, uploadFile]);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Tab') {\n e.preventDefault();\n onTabNext();\n return;\n }\n },\n [onTabNext]\n );\n\n const handleFocus = useCallback(() => {\n onFocus();\n }, [onFocus]);\n\n const handleBlur = useCallback(() => {\n onBlur();\n }, [onBlur]);\n\n return (\n <span\n className=\"inline-flex items-center gap-[2px] rounded-[6px] px-[4px] py-[1px] cursor-pointer whitespace-pre-wrap break-words [overflow-wrap:anywhere]\"\n style={{\n backgroundColor: 'rgba(20, 118, 255, 0.08)',\n color: hasFile ? 'rgba(20, 118, 255, 1)' : 'rgba(20, 118, 255, 0.4)',\n }}\n onClick={handleClick}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n tabIndex={0}\n data-placeholder-id={placeholder.id}\n data-placeholder-control=\"true\"\n data-placeholder-type=\"file\"\n role=\"button\"\n aria-label={hasFile ? `已上传: ${fileValue.name}` : placeholder.defaultText}\n >\n <span\n aria-hidden=\"true\"\n className=\"inline-flex items-center justify-center w-[16px] h-[16px] flex-shrink-0\"\n onClick={handleIconClick}\n >\n {hasFile && isHovered ? (\n <img src=\"/icons/common-delete.svg\" alt=\"\" className=\"w-[16px] h-[16px]\" />\n ) : hasFile ? (\n <img src={getFileTypeIcon(fileValue.name)} alt=\"\" className=\"w-[16px] h-[16px]\" />\n ) : (\n <img src=\"/icons/icon-upload.svg\" alt=\"\" className=\"w-[16px] h-[16px]\" />\n )}\n </span>\n <span\n className=\"inline-block\"\n style={{\n wordBreak: 'break-word',\n }}\n >\n {hasFile ? fileValue.name : placeholder.defaultText}\n </span>\n </span>\n );\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport { useCallback, useLayoutEffect, useMemo, useRef } from 'react';\nimport { usePlaceholderStore } from '@/stores/placeholderStore';\nimport type { TextPlaceholder } from '@/utils/promptParser';\nimport {\n buildRichTextareaSegments,\n type RichQuickActionOption,\n type RichSkillOption,\n type RichTextareaSegment,\n renderRichTextareaSegments,\n serializeRichTextareaNode,\n serializeRichTextareaNodeSignature,\n} from './rich-textarea-token-rendering';\n\ninterface TextPlaceholderBlockProps {\n placeholder: TextPlaceholder;\n isActive: boolean;\n skillOptions: RichSkillOption[];\n quickActionOptions: RichQuickActionOption[];\n onFocus: () => void;\n onBlur: () => void;\n onDelete: () => void;\n onTabNext: () => void;\n}\n\nexport function TextPlaceholderBlock({\n placeholder,\n isActive,\n skillOptions,\n quickActionOptions,\n onFocus,\n onBlur,\n onDelete,\n onTabNext,\n}: TextPlaceholderBlockProps) {\n const textRef = useRef<HTMLSpanElement>(null);\n const isComposingRef = useRef(false);\n const userInput = usePlaceholderStore((s) => s.textValues[placeholder.id] ?? '');\n const setTextValue = usePlaceholderStore((s) => s.setTextValue);\n const segments = useMemo(\n () =>\n buildRichTextareaSegments(userInput, skillOptions, quickActionOptions, {\n allowTerminalMention: true,\n }),\n [quickActionOptions, skillOptions, userInput],\n );\n const hasRichTokens = useMemo(() => segments.some((segment) => segment.type !== 'text'), [segments]);\n const segmentSignature = useMemo(\n () =>\n segments\n .map((segment) => {\n if (segment.type === 'text') return `t:${segment.text}`;\n if (segment.type === 'mention') return `m:${segment.text}`;\n if (segment.type === 'skill') return `s:${segment.token}`;\n return `q:${segment.token}`;\n })\n .join(''),\n [segments],\n );\n\n useLayoutEffect(() => {\n const el = textRef.current;\n if (!el) return;\n if (isComposingRef.current) return;\n\n const currentText = Array.from(el.childNodes)\n .map((node) => serializeRichTextareaNode(node))\n .join('');\n const currentSignature = Array.from(el.childNodes)\n .map((node) => serializeRichTextareaNodeSignature(node))\n .join('');\n if (currentText === userInput && currentSignature === segmentSignature) return;\n\n const selection = window.getSelection();\n const isFocused = document.activeElement === el && selection && selection.rangeCount > 0;\n const activeSelection = isFocused ? getSelectionOffsetsWithinElement(el, selection.getRangeAt(0)) : null;\n const nextSegments: RichTextareaSegment[] = hasRichTokens ? segments : [{ type: 'text', text: userInput }];\n\n renderRichTextareaSegments(el, nextSegments);\n\n if (activeSelection) {\n setSelectionOffsetsWithinElement(el, activeSelection.start, activeSelection.end);\n }\n }, [hasRichTokens, segments, segmentSignature, userInput]);\n\n useLayoutEffect(() => {\n const el = textRef.current;\n if (isActive && el && document.activeElement !== el) {\n el.focus();\n const selection = window.getSelection();\n if (!selection) return;\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n }\n }, [isActive]);\n\n const handleInput = useCallback(\n (e: React.FormEvent<HTMLSpanElement>) => {\n if (isComposingRef.current) return;\n const value = Array.from(e.currentTarget.childNodes)\n .map((node) => serializeRichTextareaNode(node))\n .join('');\n setTextValue(placeholder.id, value);\n },\n [placeholder.id, setTextValue],\n );\n\n const handleCompositionStart = useCallback(() => {\n isComposingRef.current = true;\n }, []);\n\n const handleCompositionEnd = useCallback(\n (e: React.CompositionEvent<HTMLSpanElement>) => {\n isComposingRef.current = false;\n const value = Array.from(e.currentTarget.childNodes)\n .map((node) => serializeRichTextareaNode(node))\n .join('');\n setTextValue(placeholder.id, value);\n },\n [placeholder.id, setTextValue],\n );\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent<HTMLSpanElement>) => {\n if (e.key === 'Tab') {\n e.preventDefault();\n onTabNext();\n return;\n }\n\n // Don't prevent arrow keys - let them bubble to container for navigation\n if (e.key === 'Backspace') {\n if (userInput.length === 0) {\n e.preventDefault();\n onDelete();\n return;\n }\n }\n },\n [userInput.length, onDelete, onTabNext],\n );\n\n const handleFocus = useCallback(() => {\n onFocus();\n }, [onFocus]);\n\n const handleBlur = useCallback(() => {\n onBlur();\n }, [onBlur]);\n\n const isEmpty = userInput.length === 0;\n\n return (\n <span\n ref={textRef}\n contentEditable\n suppressContentEditableWarning\n className=\"prompt-placeholder-text inline rounded-[6px] px-[4px] py-[1px] align-baseline outline-none whitespace-pre-wrap break-words [overflow-wrap:anywhere]\"\n style={{\n backgroundColor: 'rgba(20, 118, 255, 0.08)',\n color: isEmpty ? 'rgba(20, 118, 255, 0.4)' : 'rgba(20, 118, 255, 1)',\n }}\n onInput={handleInput}\n onCompositionStart={handleCompositionStart}\n onCompositionEnd={handleCompositionEnd}\n onKeyDown={handleKeyDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-placeholder={placeholder.defaultText}\n data-placeholder-empty={isEmpty ? 'true' : 'false'}\n data-placeholder-id={placeholder.id}\n data-placeholder-control=\"true\"\n data-placeholder-type=\"text\"\n />\n );\n}\n\nfunction getSelectionOffsetsWithinElement(\n element: HTMLSpanElement,\n range: Range,\n): { start: number; end: number } | null {\n if (!element.contains(range.startContainer) || !element.contains(range.endContainer)) return null;\n\n const startRange = document.createRange();\n startRange.selectNodeContents(element);\n startRange.setEnd(range.startContainer, range.startOffset);\n\n const endRange = document.createRange();\n endRange.selectNodeContents(element);\n endRange.setEnd(range.endContainer, range.endOffset);\n\n return {\n start: serializeSelectionRange(startRange),\n end: serializeSelectionRange(endRange),\n };\n}\n\nfunction serializeSelectionRange(range: Range): number {\n const fragment = range.cloneContents();\n let serialized = '';\n for (const child of Array.from(fragment.childNodes)) {\n serialized += serializeRichTextareaNode(child);\n }\n return serialized.length;\n}\n\nfunction setSelectionOffsetsWithinElement(element: HTMLSpanElement, start: number, end: number): void {\n const nodes: Array<{ node: Node; start: number; end: number }> = [];\n let offset = 0;\n const walk = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent ?? '';\n nodes.push({ node, start: offset, end: offset + text.length });\n offset += text.length;\n return;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const el = node as HTMLElement;\n if (el.dataset.tokenType === 'skill' || el.dataset.tokenType === 'quick-action') {\n const token = el.dataset.tokenValue ?? '';\n nodes.push({ node, start: offset, end: offset + token.length });\n offset += token.length;\n return;\n }\n for (const child of Array.from(node.childNodes)) walk(child);\n };\n walk(element);\n\n const pick = (target: number): { node: Node; offset: number } => {\n for (const item of nodes) {\n if (target <= item.end) {\n if (item.node.nodeType === Node.TEXT_NODE) {\n return {\n node: item.node,\n offset: Math.max(0, Math.min((item.node.textContent ?? '').length, target - item.start)),\n };\n }\n const parent = item.node.parentNode;\n if (parent) {\n const idx = Array.prototype.indexOf.call(parent.childNodes, item.node);\n if (target - item.start <= 0) return { node: parent, offset: idx };\n return { node: parent, offset: idx + 1 };\n }\n }\n }\n return { node: element, offset: element.childNodes.length };\n };\n\n const selection = window.getSelection();\n if (!selection) return;\n const range = document.createRange();\n const s = pick(start);\n const e = pick(end);\n range.setStart(s.node, s.offset);\n range.setEnd(e.node, e.offset);\n selection.removeAllRanges();\n selection.addRange(range);\n}\n","/*\n * *\n * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n */\n\nimport {\n type ClipboardEvent,\n type CSSProperties,\n type FormEvent,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type UIEvent,\n useCallback,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\nimport type { FilePlaceholder, ParsedPrompt, TextPlaceholder } from '@/utils/promptParser';\nimport { usePromptBlockKeyboardNavigation } from '../hooks/usePromptBlockKeyboardNavigation';\nimport { FilePlaceholderBlock } from './FilePlaceholderBlock';\nimport {\n buildRichTextareaSegments,\n renderRichTextareaSegments,\n type RichQuickActionOption,\n type RichSkillOption,\n serializeRichTextareaNode,\n serializeRichTextareaNodeSignature,\n} from './rich-textarea-token-rendering';\nimport { TextPlaceholderBlock } from './TextPlaceholderBlock';\n\nexport interface RichTextareaPromptBlocksProps {\n parsed: ParsedPrompt;\n activePlaceholderId: string | null;\n onFocus: (id: string) => void;\n onBlur: () => void;\n onDelete: (id: string) => void;\n onTabNext: (currentId: string) => void;\n onInput?: (e: FormEvent<HTMLDivElement>) => void;\n onKeyDown?: (e: KeyboardEvent<HTMLDivElement>) => void;\n onPaste?: (e: ClipboardEvent<HTMLDivElement>) => void;\n onScroll?: (e: UIEvent<HTMLDivElement>) => void;\n skillOptions?: RichSkillOption[];\n quickActionOptions?: RichQuickActionOption[];\n className?: string;\n style?: CSSProperties;\n}\n\nfunction placeCaretFromClick(e: MouseEvent<HTMLSpanElement>): void {\n e.stopPropagation();\n const selection = window.getSelection();\n if (!selection) return;\n\n let range: Range | null = null;\n if (typeof document.caretRangeFromPoint === 'function') {\n range = document.caretRangeFromPoint(e.clientX, e.clientY);\n } else if (document.caretPositionFromPoint) {\n const pos = document.caretPositionFromPoint(e.clientX, e.clientY);\n if (pos) {\n range = document.createRange();\n range.setStart(pos.offsetNode, pos.offset);\n }\n }\n\n if (!range) {\n range = document.createRange();\n range.selectNodeContents(e.currentTarget);\n range.collapse((e.currentTarget.textContent ?? '').length === 0);\n }\n selection.removeAllRanges();\n selection.addRange(range);\n}\n\ninterface RichPromptFixedBlockProps {\n blockIndex: number;\n content: string;\n skillOptions: RichSkillOption[];\n quickActionOptions: RichQuickActionOption[];\n isTerminalCaretTarget?: boolean;\n}\n\nfunction RichPromptFixedBlock({\n blockIndex,\n content,\n skillOptions,\n quickActionOptions,\n isTerminalCaretTarget = false,\n}: RichPromptFixedBlockProps) {\n const blockRef = useRef<HTMLSpanElement>(null);\n const segments = useMemo(\n () => buildRichTextareaSegments(content, skillOptions, quickActionOptions, { allowTerminalMention: true }),\n [content, quickActionOptions, skillOptions],\n );\n const segmentSignature = useMemo(\n () =>\n segments\n .map((segment) => {\n if (segment.type === 'text') return `t:${segment.text}`;\n if (segment.type === 'mention') return `m:${segment.text}`;\n if (segment.type === 'skill') return `s:${segment.token}`;\n return `q:${segment.token}`;\n })\n .join(''),\n [segments],\n );\n\n useLayoutEffect(() => {\n const el = blockRef.current;\n if (!el) return;\n\n const currentText = Array.from(el.childNodes)\n .map((node) => serializeRichTextareaNode(node))\n .join('');\n const currentSignature = Array.from(el.childNodes)\n .map((node) => serializeRichTextareaNodeSignature(node))\n .join('');\n if (currentText === content && currentSignature === segmentSignature) return;\n\n renderRichTextareaSegments(el, segments);\n }, [content, segments, segmentSignature]);\n\n return (\n <span\n ref={blockRef}\n contentEditable\n suppressContentEditableWarning\n className={\n isTerminalCaretTarget\n ? 'inline-block min-w-[1px] align-baseline outline-none focus:outline-none'\n : 'outline-none focus:outline-none'\n }\n data-block-index={blockIndex}\n onClick={placeCaretFromClick}\n />\n );\n}\n\nexport const RichTextareaPromptBlocks = forwardRef<HTMLDivElement, RichTextareaPromptBlocksProps>(\n function RichTextareaPromptBlocks(\n {\n parsed,\n activePlaceholderId,\n onFocus,\n onBlur,\n onDelete,\n onTabNext,\n onInput,\n onKeyDown,\n onPaste,\n onScroll,\n skillOptions = [],\n quickActionOptions = [],\n className,\n style,\n },\n ref,\n ) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n useImperativeHandle(ref, () => containerRef.current as HTMLDivElement);\n\n const handleFocus = useCallback((id: string) => onFocus(id), [onFocus]);\n const handleBlur = useCallback(() => onBlur(), [onBlur]);\n const handleDelete = useCallback((id: string) => onDelete(id), [onDelete]);\n const handleTabNext = useCallback((currentId: string) => onTabNext(currentId), [onTabNext]);\n\n usePromptBlockKeyboardNavigation({ containerRef, parsed, onFocus, onBlur, onDelete: handleDelete });\n\n return (\n <div\n ref={containerRef}\n className={className ? `${className} outline-none` : 'outline-none'}\n style={style}\n tabIndex={0}\n role=\"textbox\"\n aria-multiline=\"true\"\n onInput={onInput}\n onKeyDown={(e) => {\n if (e.defaultPrevented) return;\n onKeyDown?.(e);\n }}\n onPaste={onPaste}\n onScroll={onScroll}\n >\n {parsed.blocks.map((block, index) => {\n if (block.type === 'fixed') {\n return (\n <RichPromptFixedBlock\n key={`fixed-${index}`}\n blockIndex={index}\n content={block.content}\n skillOptions={skillOptions}\n quickActionOptions={quickActionOptions}\n isTerminalCaretTarget={index === parsed.blocks.length - 1 && block.content.length === 0}\n />\n );\n }\n\n if (block.type === 'placeholder') {\n const placeholder = block.placeholder;\n const isActive = placeholder.id === activePlaceholderId;\n\n if (placeholder.type === 'text') {\n return (\n <TextPlaceholderBlock\n key={placeholder.id}\n placeholder={placeholder as TextPlaceholder}\n isActive={isActive}\n skillOptions={skillOptions}\n quickActionOptions={quickActionOptions}\n onFocus={() => handleFocus(placeholder.id)}\n onBlur={handleBlur}\n onDelete={() => handleDelete(placeholder.id)}\n onTabNext={() => handleTabNext(placeholder.id)}\n />\n );\n }\n\n if (placeholder.type === 'file') {\n return (\n <FilePlaceholderBlock\n key={placeholder.id}\n placeholder={placeholder as FilePlaceholder}\n isActive={isActive}\n onFocus={() => handleFocus(placeholder.id)}\n onBlur={handleBlur}\n onDelete={() => handleDelete(placeholder.id)}\n onTabNext={() => handleTabNext(placeholder.id)}\n />\n );\n }\n }\n\n return null;\n })}\n </div>\n );\n },\n);\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport {\n type ClipboardEvent,\n type CSSProperties,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type MutableRefObject,\n type UIEvent,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { RichTextareaPromptBlocksProps } from './RichTextareaPromptBlocks';\nimport { RichTextareaPromptBlocks } from './RichTextareaPromptBlocks';\nimport {\n buildRichTextareaSegments,\n isVisuallyEmptyRichTextareaValue,\n type RichQuickActionOption,\n type RichSkillOption,\n renderRichTextareaSegments,\n serializeRichTextareaNode,\n serializeRichTextareaNodeSignature,\n} from './rich-textarea-token-rendering';\n\ninterface RichTextareaProps {\n value: string;\n onValueChange: (value: string, selectionStart: number, selectionEnd: number) => void;\n mentionDataVersion?: number;\n onCompositionStateChange?: (isComposing: boolean) => void;\n onInput?: () => void;\n onKeyDown?: (e: KeyboardEvent<HTMLDivElement>) => void;\n onPaste?: (e: ClipboardEvent<HTMLDivElement>) => void;\n onScroll?: (e: UIEvent<HTMLDivElement>) => void;\n placeholder?: string;\n className?: string;\n style?: CSSProperties;\n disabled?: boolean;\n maxLength?: number;\n skillOptions?: RichSkillOption[];\n quickActionOptions?: RichQuickActionOption[];\n promptBlocks?: RichTextareaPromptBlocksProps | null;\n}\n\nexport interface RichTextareaHandle {\n focus: () => void;\n getSelectionStart: () => number;\n getSelectionEnd: () => number;\n setSelectionRange: (start: number, end: number) => void;\n getElement: () => HTMLDivElement | null;\n getClientRectAtOffset: (offset: number) => DOMRect | null;\n applyProgrammaticChange: (value: string, selectionStart: number, selectionEnd: number) => void;\n}\n\ntype HistorySnapshot = { value: string; start: number; end: number };\ntype GroupedHistoryAction = 'insertText' | 'deleteContentBackward' | 'deleteContentForward' | null;\n\nconst HISTORY_STACK_LIMIT = 100;\nconst HISTORY_GROUP_WINDOW_MS = 1000;\n\nfunction serializeChildren(root: HTMLElement): string {\n return Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n}\n\ntype PromptEditableSegment = {\n element: HTMLElement;\n start: number;\n end: number;\n editable: boolean;\n};\n\nfunction collectPromptEditableSegments(root: HTMLElement): PromptEditableSegment[] {\n const segments: PromptEditableSegment[] = [];\n let offset = 0;\n for (const child of Array.from(root.childNodes)) {\n const text = serializeRichTextareaNode(child);\n if (child instanceof HTMLElement) {\n const isFixedBlock = child.dataset.blockIndex !== undefined;\n const isTextPlaceholder = child.dataset.placeholderControl === 'true' && child.dataset.placeholderType === 'text';\n segments.push({\n element: child,\n start: offset,\n end: offset + text.length,\n editable: isFixedBlock || isTextPlaceholder,\n });\n }\n offset += text.length;\n }\n return segments;\n}\n\nfunction getStringDiff(current: string, next: string): { start: number; end: number; inserted: string } {\n let start = 0;\n while (start < current.length && start < next.length && current[start] === next[start]) start += 1;\n\n let currentEnd = current.length;\n let nextEnd = next.length;\n while (currentEnd > start && nextEnd > start && current[currentEnd - 1] === next[nextEnd - 1]) {\n currentEnd -= 1;\n nextEnd -= 1;\n }\n\n return { start, end: currentEnd, inserted: next.slice(start, nextEnd) };\n}\n\nfunction findPromptEditableSegment(\n segments: PromptEditableSegment[],\n start: number,\n end: number,\n): PromptEditableSegment | null {\n const active = document.activeElement;\n const activeSegment =\n active instanceof HTMLElement\n ? segments.find((segment) => segment.element === active || segment.element.contains(active))\n : null;\n if (activeSegment?.editable && start >= activeSegment.start && end <= activeSegment.end) {\n return activeSegment;\n }\n\n if (start === end) {\n const boundaryPlaceholder = segments.find(\n (segment) =>\n segment.editable &&\n segment.element.dataset.placeholderControl === 'true' &&\n segment.element.dataset.placeholderType === 'text' &&\n start === segment.start,\n );\n if (boundaryPlaceholder) return boundaryPlaceholder;\n }\n\n return (\n segments.find((segment) => {\n if (!segment.editable) return false;\n if (start === end) return start >= segment.start && start <= segment.end;\n return start >= segment.start && end <= segment.end;\n }) ?? null\n );\n}\n\nfunction findFallbackPromptTextSegment(segments: PromptEditableSegment[]): PromptEditableSegment | null {\n const active = document.activeElement;\n if (active instanceof HTMLElement) {\n const activeSegment = segments.find((segment) => segment.element === active || segment.element.contains(active));\n if (\n activeSegment?.editable &&\n activeSegment.element.dataset.placeholderControl === 'true' &&\n activeSegment.element.dataset.placeholderType === 'text'\n ) {\n return activeSegment;\n }\n }\n\n return (\n segments.find(\n (segment) =>\n segment.editable &&\n segment.element.dataset.placeholderControl === 'true' &&\n segment.element.dataset.placeholderType === 'text',\n ) ?? null\n );\n}\n\nfunction dispatchProgrammaticInput(element: HTMLElement, inserted: string): void {\n const event =\n typeof InputEvent === 'function'\n ? new InputEvent('input', {\n bubbles: true,\n inputType: 'insertReplacementText',\n data: inserted,\n })\n : new Event('input', { bubbles: true });\n element.dispatchEvent(event);\n}\n\nfunction renderPromptSegmentContent(\n element: HTMLElement,\n value: string,\n skillOptions: RichSkillOption[],\n quickActionOptions: RichQuickActionOption[],\n): void {\n renderRichTextareaSegments(\n element,\n buildRichTextareaSegments(value, skillOptions, quickActionOptions, { allowTerminalMention: true }),\n );\n}\n\nfunction applyPromptBlockProgrammaticChange(\n root: HTMLElement,\n nextValue: string,\n selectionStart: number,\n selectionEnd: number,\n skillOptions: RichSkillOption[],\n quickActionOptions: RichQuickActionOption[],\n): boolean {\n const current = serializeChildren(root);\n if (current === nextValue) {\n setSelectionOffset(root, selectionStart, selectionEnd);\n return true;\n }\n\n const diff = getStringDiff(current, nextValue);\n const segments = collectPromptEditableSegments(root);\n const segment = findPromptEditableSegment(segments, diff.start, diff.end);\n if (!segment) {\n const fallback = findFallbackPromptTextSegment(segments);\n if (!fallback) return false;\n\n renderPromptSegmentContent(fallback.element, nextValue, skillOptions, quickActionOptions);\n const nextStart = Math.max(0, Math.min(nextValue.length, selectionStart));\n const nextEnd = Math.max(nextStart, Math.min(nextValue.length, selectionEnd));\n setSelectionOffset(root, fallback.start + nextStart, fallback.start + nextEnd);\n dispatchProgrammaticInput(fallback.element, nextValue);\n return true;\n }\n\n const currentText = serializeRichTextareaNode(segment.element);\n const localStart = Math.max(0, diff.start - segment.start);\n const localEnd = Math.max(localStart, diff.end - segment.start);\n const nextSegmentText = `${currentText.slice(0, localStart)}${diff.inserted}${currentText.slice(localEnd)}`;\n renderPromptSegmentContent(segment.element, nextSegmentText, skillOptions, quickActionOptions);\n setSelectionOffset(root, selectionStart, selectionEnd);\n dispatchProgrammaticInput(segment.element, diff.inserted);\n return true;\n}\n\nfunction collectTextNodes(root: HTMLElement): Array<{ node: Node; start: number; end: number }> {\n const out: Array<{ node: Node; start: number; end: number }> = [];\n let offset = 0;\n const walk = (node: Node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent ?? '';\n out.push({ node, start: offset, end: offset + text.length });\n offset += text.length;\n return;\n }\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const el = node as HTMLElement;\n if (el.dataset.tokenType === 'skill' || el.dataset.tokenType === 'quick-action') {\n const token = el.dataset.tokenValue ?? '';\n out.push({ node: el, start: offset, end: offset + token.length });\n offset += token.length;\n return;\n }\n for (const child of Array.from(node.childNodes)) walk(child);\n };\n walk(root);\n return out;\n}\n\nfunction getSelectionOffset(root: HTMLElement, atEnd: boolean): number {\n const sel = window.getSelection();\n if (!sel || sel.rangeCount === 0) return 0;\n const active = sel.getRangeAt(0);\n const range = document.createRange();\n range.selectNodeContents(root);\n range.setEnd(atEnd ? active.endContainer : active.startContainer, atEnd ? active.endOffset : active.startOffset);\n const fragment = range.cloneContents();\n let serialized = '';\n for (const child of Array.from(fragment.childNodes)) {\n serialized += serializeRichTextareaNode(child);\n }\n return serialized.length;\n}\n\nfunction setSelectionOffset(root: HTMLElement, start: number, end: number): void {\n const nodes = collectTextNodes(root);\n const pick = (offset: number): { node: Node; offset: number } => {\n for (const item of nodes) {\n if (offset <= item.end) {\n if (item.node.nodeType === Node.TEXT_NODE) {\n return {\n node: item.node,\n offset: Math.max(0, Math.min((item.node.textContent ?? '').length, offset - item.start)),\n };\n }\n const parent = item.node.parentNode;\n if (parent) {\n const idx = Array.prototype.indexOf.call(parent.childNodes, item.node);\n if (offset - item.start <= 0) return { node: parent, offset: idx };\n return { node: parent, offset: idx + 1 };\n }\n }\n }\n return { node: root, offset: root.childNodes.length };\n };\n\n const s = pick(start);\n const e = pick(end);\n const range = document.createRange();\n range.setStart(s.node, s.offset);\n range.setEnd(e.node, e.offset);\n const sel = window.getSelection();\n if (!sel) return;\n sel.removeAllRanges();\n sel.addRange(range);\n}\n\nfunction clampWithSelection(\n nextValue: string,\n selectionStart: number,\n selectionEnd: number,\n maxLength?: number,\n): { value: string; start: number; end: number } {\n if (isVisuallyEmptyRichTextareaValue(nextValue)) {\n return { value: '', start: 0, end: 0 };\n }\n if (!maxLength || maxLength <= 0 || nextValue.length <= maxLength) {\n return { value: nextValue, start: selectionStart, end: selectionEnd };\n }\n const clampedValue = nextValue.slice(0, maxLength);\n return {\n value: clampedValue,\n start: Math.min(selectionStart, clampedValue.length),\n end: Math.min(selectionEnd, clampedValue.length),\n };\n}\n\nfunction forceSyncPlainText(root: HTMLElement, value: string, start: number, end: number): void {\n if (value.length === 0) {\n root.replaceChildren();\n } else {\n root.replaceChildren(document.createTextNode(value));\n }\n setSelectionOffset(root, start, end);\n}\n\nfunction resolvePositionAtOffset(root: HTMLElement, offset: number): { node: Node; offset: number } {\n const nodes = collectTextNodes(root);\n for (const item of nodes) {\n if (offset <= item.end) {\n if (item.node.nodeType === Node.TEXT_NODE) {\n const textLength = (item.node.textContent ?? '').length;\n return { node: item.node, offset: Math.max(0, Math.min(textLength, offset - item.start)) };\n }\n const parent = item.node.parentNode;\n if (parent) {\n const idx = Array.prototype.indexOf.call(parent.childNodes, item.node);\n if (offset - item.start <= 0) return { node: parent, offset: idx };\n return { node: parent, offset: idx + 1 };\n }\n }\n }\n return { node: root, offset: root.childNodes.length };\n}\n\nfunction getClientRectAtOffset(root: HTMLElement, offset: number): DOMRect | null {\n try {\n const pos = resolvePositionAtOffset(root, offset);\n const range = document.createRange();\n range.setStart(pos.node, pos.offset);\n range.setEnd(pos.node, pos.offset);\n const rect = range.getBoundingClientRect();\n if (rect.width !== 0 || rect.height !== 0) return rect;\n const fallback = root.getBoundingClientRect();\n return fallback.width > 0 || fallback.height > 0 ? fallback : null;\n } catch {\n return null;\n }\n}\n\nfunction isTextInsertionKey(e: KeyboardEvent<HTMLDivElement>): boolean {\n if (e.key.length === 1) return true;\n return e.key === 'Enter';\n}\n\nfunction cloneSnapshot(snapshot: HistorySnapshot): HistorySnapshot {\n return { ...snapshot };\n}\n\nfunction isSameSnapshot(left: HistorySnapshot, right: HistorySnapshot): boolean {\n return left.value === right.value && left.start === right.start && left.end === right.end;\n}\n\nfunction normalizeGroupedHistoryAction(inputType: string): GroupedHistoryAction {\n if (inputType === 'insertText' || inputType === 'deleteContentBackward' || inputType === 'deleteContentForward') {\n return inputType;\n }\n return null;\n}\n\n\nexport const RichTextarea = forwardRef<RichTextareaHandle, RichTextareaProps>(function RichTextarea(\n {\n value,\n onValueChange,\n mentionDataVersion = 0,\n onCompositionStateChange,\n onInput,\n onKeyDown,\n onPaste,\n onScroll,\n placeholder,\n className,\n style,\n disabled,\n maxLength,\n skillOptions = [],\n quickActionOptions = [],\n promptBlocks = null,\n },\n ref,\n) {\n const rootRef = useRef<HTMLDivElement | null>(null);\n const isPromptBlockMode = promptBlocks !== null;\n const isComposingRef = useRef(false);\n const pendingSelectionRef = useRef<{ start: number; end: number } | null>(null);\n const shouldScrollToBottomRef = useRef(false);\n const currentSnapshotRef = useRef<HistorySnapshot>({ value, start: 0, end: 0 });\n const undoStackRef = useRef<HistorySnapshot[]>([]);\n const redoStackRef = useRef<HistorySnapshot[]>([]);\n const pendingInternalValueSyncRef = useRef(false);\n const historyInputGuardRef = useRef<'historyUndo' | 'historyRedo' | null>(null);\n const previousPromptBlockModeRef = useRef(isPromptBlockMode);\n const historyGroupRef = useRef<{ action: GroupedHistoryAction; timestamp: number }>({\n action: null,\n timestamp: 0,\n });\n const [showPlaceholder, setShowPlaceholder] = useState(() => isVisuallyEmptyRichTextareaValue(value));\n const segments = useMemo(\n () => buildRichTextareaSegments(value, skillOptions, quickActionOptions, { allowTerminalMention: true }),\n [value, skillOptions, quickActionOptions, mentionDataVersion],\n );\n const segmentSignature = useMemo(\n () =>\n `${mentionDataVersion}::` +\n segments\n .map((seg) => {\n if (seg.type === 'text') return `t:${seg.text}`;\n if (seg.type === 'mention') return `m:${seg.text}`;\n if (seg.type === 'skill') return `s:${seg.token}`;\n if (seg.type === 'quick_action') return `q:${seg.token}`;\n return '';\n })\n .join(''),\n [segments, mentionDataVersion],\n );\n\n useImperativeHandle(ref, () => ({\n focus: () => rootRef.current?.focus(),\n getSelectionStart: () => {\n const root = rootRef.current;\n if (!root) return 0;\n return getSelectionOffset(root, false);\n },\n getSelectionEnd: () => {\n const root = rootRef.current;\n if (!root) return 0;\n return getSelectionOffset(root, true);\n },\n setSelectionRange: (start: number, end: number) => {\n const root = rootRef.current;\n if (!root) return;\n setSelectionOffset(root, start, end);\n },\n getElement: () => rootRef.current,\n getClientRectAtOffset: (offset: number) => {\n const root = rootRef.current;\n if (!root) return null;\n return getClientRectAtOffset(root, offset);\n },\n applyProgrammaticChange: (nextValue: string, selectionStart: number, selectionEnd: number) => {\n if (isPromptBlockMode) {\n const root = rootRef.current;\n if (!root) return;\n const next = clampWithSelection(nextValue, selectionStart, selectionEnd, maxLength);\n applyPromptBlockProgrammaticChange(root, next.value, next.start, next.end, skillOptions, quickActionOptions);\n return;\n }\n const next = clampWithSelection(nextValue, selectionStart, selectionEnd, maxLength);\n commitChange(next, 'insertReplacementText');\n },\n }));\n\n const resetHistoryGroup = () => {\n historyGroupRef.current = { action: null, timestamp: 0 };\n };\n\n const pushHistorySnapshot = (stack: MutableRefObject<HistorySnapshot[]>, snapshot: HistorySnapshot) => {\n const copy = cloneSnapshot(snapshot);\n const last = stack.current[stack.current.length - 1];\n if (last && isSameSnapshot(last, copy)) return;\n stack.current.push(copy);\n if (stack.current.length > HISTORY_STACK_LIMIT) {\n stack.current.splice(0, stack.current.length - HISTORY_STACK_LIMIT);\n }\n };\n\n const applySnapshot = (snapshot: HistorySnapshot) => {\n const root = rootRef.current;\n const next = cloneSnapshot(snapshot);\n currentSnapshotRef.current = next;\n pendingSelectionRef.current = { start: next.start, end: next.end };\n pendingInternalValueSyncRef.current = true;\n setShowPlaceholder(isVisuallyEmptyRichTextareaValue(next.value));\n if (root) {\n forceSyncPlainText(root, next.value, next.start, next.end);\n }\n onValueChange(next.value, next.start, next.end);\n onInput?.();\n };\n\n const commitChange = (snapshot: HistorySnapshot, inputType = '') => {\n const next = cloneSnapshot(snapshot);\n const current = currentSnapshotRef.current;\n const valueChanged = current.value !== next.value;\n if (valueChanged) {\n const groupedAction = normalizeGroupedHistoryAction(inputType);\n const now = Date.now();\n const shouldGroup =\n groupedAction !== null &&\n historyGroupRef.current.action === groupedAction &&\n now - historyGroupRef.current.timestamp <= HISTORY_GROUP_WINDOW_MS;\n if (!shouldGroup) {\n pushHistorySnapshot(undoStackRef, current);\n }\n redoStackRef.current = [];\n historyGroupRef.current = { action: groupedAction, timestamp: now };\n } else {\n resetHistoryGroup();\n }\n\n currentSnapshotRef.current = next;\n pendingSelectionRef.current = { start: next.start, end: next.end };\n pendingInternalValueSyncRef.current = true;\n setShowPlaceholder(isVisuallyEmptyRichTextareaValue(next.value));\n onValueChange(next.value, next.start, next.end);\n onInput?.();\n };\n\n const applyUndo = () => {\n const previous = undoStackRef.current.pop();\n if (!previous) return;\n pushHistorySnapshot(redoStackRef, currentSnapshotRef.current);\n resetHistoryGroup();\n applySnapshot(previous);\n };\n\n const applyRedo = () => {\n const next = redoStackRef.current.pop();\n if (!next) return;\n pushHistorySnapshot(undoStackRef, currentSnapshotRef.current);\n resetHistoryGroup();\n applySnapshot(next);\n };\n\n const armHistoryInputGuard = (type: 'historyUndo' | 'historyRedo') => {\n historyInputGuardRef.current = type;\n requestAnimationFrame(() => {\n if (historyInputGuardRef.current === type) {\n historyInputGuardRef.current = null;\n }\n });\n };\n\n useLayoutEffect(() => {\n if (isPromptBlockMode) return;\n const root = rootRef.current;\n if (!root) return;\n // IME composition guard: rebuilding DOM during 拼音组合输入会打断候选词。\n if (isComposingRef.current) return;\n const current = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n const currentSignature = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNodeSignature(n))\n .join('');\n if (current === value && currentSignature === segmentSignature) return;\n\n const active = document.activeElement === root;\n const pendingSelection = active ? pendingSelectionRef.current : null;\n const start = active ? (pendingSelection?.start ?? getSelectionOffset(root, false)) : 0;\n const end = active ? (pendingSelection?.end ?? getSelectionOffset(root, true)) : 0;\n if (pendingSelection) pendingSelectionRef.current = null;\n const prevScrollTop = root.scrollTop;\n const prevClientHeight = root.clientHeight;\n const prevScrollHeight = root.scrollHeight;\n const wasNearBottom = prevScrollTop + prevClientHeight >= prevScrollHeight - 2;\n renderRichTextareaSegments(root, segments);\n if (active) {\n const nextStart = Math.min(start, value.length);\n const nextEnd = Math.min(end, value.length);\n setSelectionOffset(root, nextStart, nextEnd);\n if (shouldScrollToBottomRef.current) {\n shouldScrollToBottomRef.current = false;\n root.scrollTop = root.scrollHeight;\n } else if (wasNearBottom) {\n // Keep caret visible while typing at the bottom of long content.\n root.scrollTop = root.scrollHeight;\n } else {\n // Preserve manual scroll position when user is editing/viewing middle content.\n root.scrollTop = prevScrollTop;\n }\n }\n }, [isPromptBlockMode, segments, segmentSignature, value]);\n\n useLayoutEffect(() => {\n const wasPromptBlockMode = previousPromptBlockModeRef.current;\n previousPromptBlockModeRef.current = isPromptBlockMode;\n if (!wasPromptBlockMode || isPromptBlockMode) return;\n\n const root = rootRef.current;\n if (!root) return;\n root.focus();\n setSelectionOffset(root, value.length, value.length);\n }, [isPromptBlockMode, value]);\n\n useEffect(() => {\n if (isPromptBlockMode) {\n setShowPlaceholder(false);\n return;\n }\n if (isComposingRef.current) return;\n setShowPlaceholder(isVisuallyEmptyRichTextareaValue(value));\n }, [isPromptBlockMode, value]);\n\n useEffect(() => {\n if (isPromptBlockMode) return;\n if (pendingInternalValueSyncRef.current) {\n pendingInternalValueSyncRef.current = false;\n return;\n }\n const current = currentSnapshotRef.current;\n if (current.value === value) return;\n currentSnapshotRef.current = {\n value,\n start: Math.min(current.start, value.length),\n end: Math.min(current.end, value.length),\n };\n undoStackRef.current = [];\n redoStackRef.current = [];\n resetHistoryGroup();\n }, [isPromptBlockMode, value]);\n\n useLayoutEffect(() => {\n if (!isPromptBlockMode) return;\n const root = rootRef.current;\n if (!root) return;\n const rawNext = serializeChildren(root);\n const rawStart = getSelectionOffset(root, false);\n const rawEnd = getSelectionOffset(root, true);\n const nextState = clampWithSelection(rawNext, rawStart, rawEnd, maxLength);\n currentSnapshotRef.current = nextState;\n if (value === nextState.value) return;\n pendingSelectionRef.current = { start: nextState.start, end: nextState.end };\n onValueChange(nextState.value, nextState.start, nextState.end);\n }, [isPromptBlockMode, maxLength, onValueChange, value]);\n\n const resolveEventElement = (target: EventTarget | null): HTMLElement | null => {\n if (!target) return null;\n if (target instanceof HTMLElement) return target;\n if (target instanceof Text) return target.parentElement;\n return null;\n };\n\n const handlePromptInput = () => {\n const root = rootRef.current;\n if (!root) return;\n const rawNext = serializeChildren(root);\n const rawStart = getSelectionOffset(root, false);\n const rawEnd = getSelectionOffset(root, true);\n const nextState = clampWithSelection(rawNext, rawStart, rawEnd, maxLength);\n currentSnapshotRef.current = nextState;\n pendingSelectionRef.current = { start: nextState.start, end: nextState.end };\n onValueChange(nextState.value, nextState.start, nextState.end);\n onInput?.();\n };\n\n return (\n <div className=\"relative\">\n {!isPromptBlockMode && showPlaceholder && placeholder && (\n <div className=\"pointer-events-none absolute left-[18px] top-4 text-[16px] text-[var(--text-field-placeholder)]\">\n {placeholder}\n </div>\n )}\n {isPromptBlockMode && promptBlocks ? (\n <RichTextareaPromptBlocks\n ref={rootRef}\n {...promptBlocks}\n className={className}\n style={style}\n skillOptions={skillOptions}\n quickActionOptions={quickActionOptions}\n onInput={handlePromptInput}\n onKeyDown={onKeyDown}\n onPaste={onPaste}\n onScroll={onScroll}\n />\n ) : (\n <div\n ref={rootRef}\n contentEditable={!disabled}\n suppressContentEditableWarning\n className={className}\n style={style}\n role=\"textbox\"\n aria-multiline=\"true\"\n onMouseDown={(e: MouseEvent<HTMLDivElement>) => {\n const target = resolveEventElement(e.target);\n const removeButton = target?.closest('[data-remove-quick-action=\"1\"]') as HTMLElement | null;\n if (!removeButton) return;\n\n const token = removeButton.closest('[data-token-type=\"quick-action\"]') as HTMLElement | null;\n const tokenValue = token?.dataset.tokenValue ?? '';\n if (!tokenValue) return;\n\n e.preventDefault();\n const index = value.indexOf(tokenValue);\n if (index < 0) return;\n const rawNext = `${value.slice(0, index)}${value.slice(index + tokenValue.length)}`;\n const next = rawNext.replace(/\\s{2,}/g, ' ').trimStart();\n const caret = Math.min(index, next.length);\n commitChange({ value: next, start: caret, end: caret }, 'deleteContentBackward');\n }}\n onMouseDownCapture={(e: MouseEvent<HTMLDivElement>) => {\n const target = resolveEventElement(e.target);\n if (!target) return;\n const skillToken = target.closest('[data-token-type=\"skill\"]');\n if (!skillToken) return;\n // Keep caret stable when clicking highlighted skill token.\n e.preventDefault();\n }}\n onInput={(e) => {\n const native = e.nativeEvent as InputEvent;\n const inputType = native.inputType ?? '';\n if (historyInputGuardRef.current === inputType) {\n historyInputGuardRef.current = null;\n return;\n }\n if (inputType === 'historyUndo') {\n applyUndo();\n return;\n }\n if (inputType === 'historyRedo') {\n applyRedo();\n return;\n }\n const root = rootRef.current;\n if (!root) return;\n if (isComposingRef.current) {\n // Avoid controlled writes during IME composition; commit on compositionend.\n onInput?.();\n return;\n }\n const rawNext = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n const rawStart = getSelectionOffset(root, false);\n const rawEnd = getSelectionOffset(root, true);\n const nextState = clampWithSelection(rawNext, rawStart, rawEnd, maxLength);\n pendingSelectionRef.current = { start: nextState.start, end: nextState.end };\n if (nextState.value !== rawNext) {\n // Keep DOM immediately in sync when parent state doesn't change\n // (e.g. already at max length and user keeps typing).\n forceSyncPlainText(e.currentTarget, nextState.value, nextState.start, nextState.end);\n }\n commitChange(nextState, inputType);\n }}\n onBeforeInput={(e) => {\n const root = rootRef.current;\n const native = e.nativeEvent as InputEvent;\n const inputType = native.inputType ?? '';\n if (inputType === 'historyUndo') {\n e.preventDefault();\n armHistoryInputGuard('historyUndo');\n applyUndo();\n return;\n }\n if (inputType === 'historyRedo') {\n e.preventDefault();\n armHistoryInputGuard('historyRedo');\n applyRedo();\n return;\n }\n if (!root || !maxLength || maxLength <= 0) return;\n // Let IME composition flow complete naturally; enforce max in onCompositionEnd/onInput.\n if (isComposingRef.current || inputType.includes('Composition')) return;\n if (!inputType.startsWith('insert')) return;\n const current = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n const start = getSelectionOffset(root, false);\n const end = getSelectionOffset(root, true);\n const selectedLength = Math.max(0, end - start);\n // For insertParagraph/insertLineBreak, data may be null; treat it as one-char insertion.\n const insertedLength = native.data != null ? native.data.length : 1;\n const nextLength = current.length - selectedLength + insertedLength;\n if (nextLength > maxLength) {\n e.preventDefault();\n }\n }}\n onCompositionStart={() => {\n isComposingRef.current = true;\n setShowPlaceholder(false);\n onCompositionStateChange?.(true);\n }}\n onCompositionEnd={() => {\n isComposingRef.current = false;\n onCompositionStateChange?.(false);\n const root = rootRef.current;\n if (!root) return;\n const rawNext = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n const rawStart = getSelectionOffset(root, false);\n const rawEnd = getSelectionOffset(root, true);\n const nextState = clampWithSelection(rawNext, rawStart, rawEnd, maxLength);\n if (nextState.value !== rawNext) {\n forceSyncPlainText(root, nextState.value, nextState.start, nextState.end);\n }\n commitChange(nextState, 'insertCompositionText');\n }}\n onKeyDown={(e) => {\n const isUndo = (e.ctrlKey || e.metaKey) && !e.altKey && !e.shiftKey && e.key.toLowerCase() === 'z';\n const isRedo =\n (e.ctrlKey || e.metaKey) &&\n !e.altKey &&\n ((e.shiftKey && e.key.toLowerCase() === 'z') || (!e.shiftKey && e.key.toLowerCase() === 'y'));\n if (isUndo) {\n e.preventDefault();\n applyUndo();\n return;\n }\n if (isRedo) {\n e.preventDefault();\n applyRedo();\n return;\n }\n const root = rootRef.current;\n if (root && maxLength && maxLength > 0 && !isComposingRef.current) {\n // Fallback guard: some browsers/IME flows may skip reliable beforeinput checks.\n // When already at max and no active selection, block text-inserting keys directly.\n const hasModifier = e.ctrlKey || e.metaKey || e.altKey;\n if (!hasModifier && isTextInsertionKey(e)) {\n const current = Array.from(root.childNodes)\n .map((n) => serializeRichTextareaNode(n))\n .join('');\n const start = getSelectionOffset(root, false);\n const end = getSelectionOffset(root, true);\n const hasSelection = end > start;\n if (!hasSelection && current.length >= maxLength) {\n e.preventDefault();\n }\n }\n }\n onKeyDown?.(e);\n }}\n onPaste={(e) => {\n onPaste?.(e);\n if (e.defaultPrevented) return;\n\n e.preventDefault();\n const root = rootRef.current;\n if (!root) return;\n const plain = (e.clipboardData?.getData('text/plain') ?? '').replace(/\\r\\n?/g, '\\n');\n\n const start = getSelectionOffset(root, false);\n const end = getSelectionOffset(root, true);\n const rawNext = `${value.slice(0, start)}${plain}${value.slice(end)}`;\n const rawCaret = start + plain.length;\n const nextState = clampWithSelection(rawNext, rawCaret, rawCaret, maxLength);\n shouldScrollToBottomRef.current = plain.length > 0;\n commitChange(nextState, 'insertFromPaste');\n if (plain.length > 0) {\n requestAnimationFrame(() => {\n const currentRoot = rootRef.current;\n if (!currentRoot) return;\n currentRoot.scrollTop = currentRoot.scrollHeight;\n });\n }\n }}\n onScroll={onScroll}\n />\n )}\n </div>\n );\n});\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\n\ninterface DropdownOption {\n label: string;\n onClick: () => void;\n danger?: boolean;\n disabled?: boolean;\n icon?: React.ReactNode;\n /** Applied to the menu item button for tests and automation. */\n testId?: string;\n type?: 'divider';\n children?: DropdownOption[];\n}\n\ninterface DropdownProps {\n trigger: React.ReactNode;\n options: DropdownOption[];\n align?: 'left' | 'right';\n /** 自定义容器样式 */\n containerClassName?: string;\n /** 自定义菜单样式 */\n menuClassName?: string;\n /** 菜单宽度 */\n menuWidth?: number;\n /** 自定义菜单项样式 */\n menuItemClassName?: string;\n}\n\nexport function Dropdown({ trigger, options, align = 'right', menuClassName, menuWidth, menuItemClassName }: DropdownProps) {\n const [isOpen, setIsOpen] = useState(false);\n const [focusedIndex, setFocusedIndex] = useState(-1);\n const [activeSubMenu, setActiveSubMenu] = useState<number | null>(null);\n const dropdownRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const itemRefs = useRef<(HTMLButtonElement | null)[]>([]);\n\n const navigableOptions = options.filter((opt) => opt.type !== 'divider' && !opt.disabled);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n isOpen &&\n dropdownRef.current &&\n !dropdownRef.current.contains(event.target as Node) &&\n menuRef.current &&\n !menuRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false);\n setFocusedIndex(-1);\n setActiveSubMenu(null);\n }\n };\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside);\n }\n\n return () => {\n document.removeEventListener('mousedown', handleClickOutside);\n };\n }, [isOpen]);\n\n const handleOptionClick = (option: DropdownOption, index: number) => {\n if (option.disabled) return;\n if (option.children && option.children.length > 0) {\n setActiveSubMenu(activeSubMenu === index ? null : index);\n return;\n }\n option.onClick();\n setIsOpen(false);\n setFocusedIndex(-1);\n };\n\n const handleKeyDown = (e: React.KeyboardEvent) => {\n if (!isOpen) {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n setIsOpen(true);\n setFocusedIndex(0);\n }\n return;\n }\n\n switch (e.key) {\n case 'Escape':\n setIsOpen(false);\n setFocusedIndex(-1);\n setActiveSubMenu(null);\n break;\n case 'ArrowDown':\n e.preventDefault();\n setFocusedIndex((prev) => (prev < navigableOptions.length - 1 ? prev + 1 : 0));\n break;\n case 'ArrowUp':\n e.preventDefault();\n setFocusedIndex((prev) => (prev > 0 ? prev - 1 : navigableOptions.length - 1));\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n if (focusedIndex >= 0 && focusedIndex < navigableOptions.length) {\n const option = navigableOptions[focusedIndex];\n if (option.children && option.children.length > 0) {\n setActiveSubMenu(activeSubMenu === focusedIndex ? null : focusedIndex);\n } else {\n option.onClick();\n setIsOpen(false);\n setFocusedIndex(-1);\n }\n }\n break;\n case 'ArrowRight':\n if (activeSubMenu !== null && navigableOptions[activeSubMenu]?.children) {\n // Will be handled by submenu\n }\n break;\n case 'ArrowLeft':\n if (activeSubMenu !== null) {\n setActiveSubMenu(null);\n }\n break;\n }\n };\n\n const getSubMenuPosition = () => {\n if (!menuRef.current) return { top: 0, left: 0 };\n const menuRect = menuRef.current.getBoundingClientRect();\n return {\n top: menuRect.top,\n left: menuRect.right,\n };\n };\n\n const triggerEl = (\n <div\n ref={triggerRef}\n onClick={(e) => {\n e.stopPropagation();\n setIsOpen(!isOpen);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n setIsOpen(!isOpen);\n }\n }}\n role=\"button\"\n tabIndex={0}\n aria-haspopup=\"true\"\n aria-expanded={isOpen}\n >\n {trigger}\n </div>\n );\n\n const renderMenuItem = (option: DropdownOption, globalIndex: number) => {\n if (option.type === 'divider') {\n return (\n <div\n key={globalIndex}\n role=\"separator\"\n style={{\n height: '1px',\n backgroundColor: 'rgba(0,0,0,0.08)',\n marginTop: '4px',\n marginBottom: '4px',\n }}\n />\n );\n }\n\n const isDisabled = option.disabled;\n const isFocused = navigableOptions[focusedIndex] === option;\n const hasChildren = option.children && option.children.length > 0;\n const isSubMenuOpen = activeSubMenu === globalIndex;\n\n const defaultItemClass = menuItemClassName\n ? ''\n : `w-full text-left text-sm transition-colors text-[#191919] ${\n isFocused ? 'bg-[rgba(245,245,245,1)]' : 'hover:bg-[rgba(245,245,245,1)]'\n }`;\n\n return (\n <div key={globalIndex} style={{ position: 'relative' }}>\n <button\n ref={(el) => { itemRefs.current[globalIndex] = el; }}\n type=\"button\"\n role=\"menuitem\"\n data-testid={option.testId}\n disabled={isDisabled}\n onClick={() => handleOptionClick(option, globalIndex)}\n onMouseEnter={() => {\n if (hasChildren) {\n setActiveSubMenu(globalIndex);\n }\n }}\n title={option.label}\n aria-haspopup={hasChildren ? 'true' : undefined}\n aria-expanded={hasChildren ? isSubMenuOpen : undefined}\n className={menuItemClassName ?? defaultItemClass}\n style={menuItemClassName ? {\n opacity: isDisabled ? 0.4 : 1,\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n } : {\n height: '32px',\n paddingLeft: '16px',\n paddingRight: hasChildren ? '8px' : '16px',\n maxWidth: '200px',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n opacity: isDisabled ? 0.4 : 1,\n cursor: isDisabled ? 'not-allowed' : 'pointer',\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n }}\n >\n {option.icon && <span style={{ display: 'flex', alignItems: 'center' }}>{option.icon}</span>}\n <span style={{ flex: 1, overflow: 'hidden', textOverflow: 'ellipsis' }}>{option.label}</span>\n {hasChildren && <span style={{ fontSize: '10px' }}>▶</span>}\n </button>\n {hasChildren && isSubMenuOpen && (\n <div\n role=\"menu\"\n className=\"fixed z-[9999] rounded-lg bg-[var(--surface-card)] overflow-hidden\"\n style={{\n top: getSubMenuPosition().top + (globalIndex * 32),\n left: getSubMenuPosition().left,\n boxShadow: '0px 2px 12px rgba(0,0,0,0.16)',\n paddingTop: '8px',\n paddingBottom: '8px',\n minWidth: '180px',\n }}\n >\n {option.children!.map((child, childIndex) =>\n renderMenuItem(child, globalIndex * 1000 + childIndex)\n )}\n </div>\n )}\n </div>\n );\n };\n\n const menu = isOpen ? (\n <div\n ref={menuRef}\n role=\"menu\"\n onMouseDown={(e) => {\n e.stopPropagation();\n }}\n onClick={(e) => {\n e.stopPropagation();\n }}\n className={`fixed z-[9999] rounded-lg bg-[var(--surface-card)] overflow-hidden ${menuClassName ?? ''}`}\n style={{\n top: triggerRef.current?.getBoundingClientRect().bottom ?? 0,\n boxShadow: '0px 2px 12px rgba(0,0,0,0.16)',\n paddingTop: '8px',\n paddingBottom: '8px',\n ...(align === 'right'\n ? { right: window.innerWidth - (triggerRef.current?.getBoundingClientRect().right ?? 0) }\n : { left: triggerRef.current?.getBoundingClientRect().left ?? 0 }),\n ...(menuWidth ? { width: menuWidth } : {}),\n }}\n >\n {options.map((option, index) => renderMenuItem(option, index))}\n </div>\n ) : null;\n\n return (\n <div ref={dropdownRef} className=\"relative inline-block\" onKeyDown={handleKeyDown}>\n {triggerEl}\n {isOpen && createPortal(menu, document.body)}\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Button } from './Button';\n\ninterface PromptDialogProps {\n open: boolean;\n title: string;\n message?: string;\n inputValue: string;\n inputPlaceholder?: string;\n confirmLabel?: string;\n cancelLabel?: string;\n confirmDisabled?: boolean;\n modalTestId?: string;\n onConfirm: (value: string) => void;\n onCancel: () => void;\n onInputChange?: (value: string) => void;\n}\n\nexport function PromptDialog({\n open,\n title,\n message,\n inputValue,\n inputPlaceholder,\n confirmLabel = '确认',\n cancelLabel = '取消',\n confirmDisabled = false,\n modalTestId,\n onConfirm,\n onCancel,\n onInputChange,\n}: PromptDialogProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [localValue, setLocalValue] = useState(inputValue);\n\n useEffect(() => {\n if (open) {\n setLocalValue(inputValue);\n setTimeout(() => {\n inputRef.current?.focus();\n inputRef.current?.select();\n }, 50);\n }\n }, [open]);\n\n useEffect(() => {\n if (!open) return;\n const handleKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') onCancel();\n };\n window.addEventListener('keydown', handleKey);\n return () => window.removeEventListener('keydown', handleKey);\n }, [open, onCancel]);\n\n if (!open) return null;\n\n const handleConfirm = () => {\n onConfirm(localValue);\n };\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center bg-[var(--overlay-backdrop-medium)]\">\n <div\n className=\"w-[400px] rounded-[8px] border border-[var(--modal-border)] bg-[var(--modal-surface)] p-6 shadow-[var(--modal-shadow)]\"\n data-testid={modalTestId}\n >\n <div className=\"flex flex-col gap-4\">\n <div className=\"flex items-center justify-between\">\n <h3 className=\"text-[16px] font-bold text-[var(--modal-title-text)]\">{title}</h3>\n <button\n type=\"button\"\n onClick={onCancel}\n aria-label=\"close\"\n className=\"flex h-6 w-6 items-center justify-center rounded text-[var(--text-label-secondary)] transition-colors hover:text-[var(--text-primary)]\"\n style={{ transform: 'translate(4px, -4px)' }}\n >\n <svg className=\"h-4 w-4\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\">\n <path d=\"M18 6L6 18M6 6l12 12\" />\n </svg>\n </button>\n </div>\n\n {message && (\n <p className=\"text-sm text-[var(--modal-text-muted)]\">{message}</p>\n )}\n\n <input\n ref={inputRef}\n type=\"text\"\n value={localValue}\n onChange={(e) => {\n setLocalValue(e.target.value);\n onInputChange?.(e.target.value);\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !confirmDisabled) {\n handleConfirm();\n }\n }}\n placeholder={inputPlaceholder}\n className=\"ui-input w-full rounded-lg px-3 py-2 text-sm\"\n />\n\n <div className=\"flex items-center justify-end gap-2\">\n <Button\n onClick={onCancel}\n color=\"default\"\n >\n {cancelLabel}\n </Button>\n <Button\n onClick={handleConfirm}\n color=\"major\"\n disabled={confirmDisabled}\n >\n {confirmLabel}\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { Tab } from '@/components/shared/Tab';\nimport { SearchInput } from '@/components/shared/SearchInput';\nimport { MaskIcon } from '@/components/shared/MaskIcon';\nimport { Button } from '@/components/shared/Button';\nimport { Dropdown } from '@/components/shared/Dropdown';\nimport { OverflowTooltip } from '@/components/shared/OverflowTooltip';\nimport { PromptDialog } from '@/components/shared/PromptDialog';\nimport { useToastStore } from '@/stores/toastStore';\nimport { useConfirm } from '@/components/useConfirm';\nimport { apiFetch } from '@/utils/api-client';\nimport styles from './TemplatePicker.module.css';\n\ninterface TemplateItem {\n id: string;\n name: string;\n thumbnailUrl: string;\n source: 'preset' | 'my';\n status: 'ready' | 'parsing' | 'failed';\n filePath?: string;\n}\n\ninterface TemplatePickerProps {\n selectedTemplateId?: string;\n onSelectChange: (template: TemplateItem | null) => void;\n /** 是否显示右侧关闭按钮,默认 false */\n showCloseButton?: boolean;\n /** 关闭按钮点击回调 */\n onClose?: () => void;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nconst ALLOWED_EXTENSIONS = ['.pptx'];\nconst PPT_UPLOAD_FORMAT_MESSAGE = '仅支持 .pptx 格式文件';\nconst PPT_UPLOAD_SIZE_MESSAGE = '仅支持上传 100MB 以下的 PPT';\nconst MAX_PPT_TEMPLATE_NAME_LENGTH = 30;\nconst PPT_UPLOAD_NAME_LENGTH_MESSAGE = `上传文件名长度不能超过 ${MAX_PPT_TEMPLATE_NAME_LENGTH} 个字符(不含 .pptx 后缀)`;\n\ninterface ApiTemplateItem {\n templateId: string;\n name: string;\n source: 'builtin' | 'user';\n status: 'ready' | 'generating' | 'failed';\n previewImageUrl?: string | null;\n}\n\ninterface ApiTemplateListResponse {\n templates?: ApiTemplateItem[];\n total?: number;\n builtinCount?: number;\n userCount?: number;\n}\n\nfunction mapApiTemplate(template: ApiTemplateItem): TemplateItem {\n return {\n id: template.templateId,\n name: template.name,\n thumbnailUrl: template.previewImageUrl ?? '',\n source: template.source === 'builtin' ? 'preset' : 'my',\n status: template.status === 'ready' ? 'ready' : template.status === 'failed' ? 'failed' : 'parsing',\n };\n}\n\nfunction isValidPptFile(file: File): boolean {\n const name = file.name.toLowerCase();\n return ALLOWED_EXTENSIONS.some((ext) => name.endsWith(ext));\n}\n\n// ─── Sub-components ───────────────────────────────────────────────────────────\n\nfunction PlusIcon() {\n return (\n <svg\n className={styles.uploadIcon}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n );\n}\n\ninterface TemplateCardProps {\n template: TemplateItem;\n onMakeSame: (template: TemplateItem) => void;\n onRename?: (template: TemplateItem) => void;\n onDelete?: (template: TemplateItem) => void;\n}\n\nfunction TemplateCard({ template, onMakeSame, onRename, onDelete, isSelected }: TemplateCardProps & { isSelected?: boolean }) {\n const isDisabled = template.status === 'parsing';\n\n const renderMoreMenu = () => {\n if (template.source !== 'my' || !onRename || !onDelete) {\n return null;\n }\n\n return (\n <Dropdown\n trigger={\n <button\n type=\"button\"\n className={`p-1 rounded hover:bg-[var(--surface-hover)] transition-colors ${styles.moreMenuBtn}`}\n data-testid={`template-card-menu-trigger-${template.id}`}\n >\n <img src=\"/icons/more-trigger.svg\" alt=\"更多\" className=\"h-4 w-4\" />\n </button>\n }\n options={[\n { label: '重命名', onClick: () => onRename(template) },\n { label: '删除', onClick: () => onDelete(template), danger: true },\n ]}\n align=\"right\"\n containerClassName=\"flex-shrink-0\"\n />\n );\n };\n\n return (\n <div\n role=\"presentation\"\n aria-disabled={isDisabled}\n className={[\n styles.card,\n isDisabled ? styles.cardDisabled : '',\n isSelected ? styles.cardSelected : '',\n ]\n .filter(Boolean)\n .join(' ')}\n data-testid={`template-card-${template.id}`}\n >\n <div className={styles.previewContainer}>\n {template.thumbnailUrl ? (\n <img\n src={template.thumbnailUrl}\n alt={template.name}\n className={styles.previewImage}\n draggable={false}\n />\n ) : (\n <img\n src=\"/images/ppt-template/template-default.png\"\n alt={template.name}\n className={styles.previewImage}\n draggable={false}\n />\n )}\n </div>\n <div className={styles.cardTitleArea}>\n <OverflowTooltip content={template.name} className={styles.cardNameTooltip}>\n <div className={styles.cardName}>{template.name}</div>\n </OverflowTooltip>\n {renderMoreMenu()}\n </div>\n {!isDisabled && (\n <div className={styles.cardAction}>\n <Button variant=\"major\"\n onClick={(e) => {\n e.stopPropagation();\n onMakeSame(template);\n }}\n >\n 做同款\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nconst MemoizedTemplateCard = memo(TemplateCard);\n\ninterface UploadCardProps {\n isDragOver: boolean;\n isUploading: boolean;\n /** 是否有模板正在生成中 */\n isGenerating: boolean;\n /** 文件选择回调 */\n onFileSelect: (file: File) => void;\n /** 独占整个内容区(我的模板为空时) */\n isFull?: boolean;\n}\n\nfunction UploadCard({ isDragOver: isDragOverProp, isUploading, isGenerating, onFileSelect, isFull }: UploadCardProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [dragOver, setDragOver] = useState(false);\n const addToast = useToastStore((state) => state.addToast);\n\n const isDragOver = isDragOverProp || dragOver;\n\n const handleDragOver = (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (!isUploading) {\n setDragOver(true);\n }\n };\n\n const handleDragLeave = (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n };\n\n const handleDrop = (e: React.DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setDragOver(false);\n if (isUploading || isGenerating) return;\n\n const files = e.dataTransfer.files;\n if (files.length === 0) return;\n\n const file = files[0];\n if (!isValidPptFile(file)) {\n addToast({\n type: 'error',\n title: '上传失败',\n message: PPT_UPLOAD_FORMAT_MESSAGE,\n duration: 4000,\n });\n return;\n }\n onFileSelect(file);\n };\n\n const handleClick = () => {\n if (isUploading || isGenerating) return;\n inputRef.current?.click();\n };\n\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files || files.length === 0) return;\n\n const file = files[0];\n if (!isValidPptFile(file)) {\n addToast({\n type: 'error',\n title: '上传失败',\n message: PPT_UPLOAD_FORMAT_MESSAGE,\n duration: 4000,\n });\n return;\n }\n onFileSelect(file);\n // Reset input so same file can be selected again\n e.target.value = '';\n };\n\n const isDisabled = isUploading || isGenerating;\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n aria-label=\"上传 PPT 模板\"\n aria-disabled={isDisabled}\n onClick={handleClick}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleClick();\n }\n }}\n className={[\n styles.uploadCard,\n isDragOver ? styles.uploadCardDragOver : '',\n isDisabled ? styles.uploadCardDisabled : '',\n isFull ? styles.uploadCardFull : '',\n ]\n .filter(Boolean)\n .join(' ')}\n data-testid=\"upload-card\"\n data-is-full={isFull ? 'true' : 'false'}\n data-drag-over={isDragOver}\n >\n <input\n ref={inputRef}\n type=\"file\"\n accept=\".pptx\"\n onChange={handleInputChange}\n className=\"hidden\"\n aria-hidden=\"true\"\n tabIndex={-1}\n />\n <div className={styles.uploadContent}>\n <PlusIcon />\n <span className={styles.uploadText}>导入模版</span>\n <span className={styles.uploadHint}>拖拽或点击上传 .pptx 文件,大小不超过 100MB</span>\n </div>\n </div>\n );\n}\n\ninterface LoadingCardProps {\n name: string;\n}\n\nfunction LoadingCard({ name: _name }: LoadingCardProps) {\n return (\n <div\n className={styles.loadingCard}\n aria-label=\"模版生成中\"\n data-testid={`loading-card-${_name}`}\n >\n <span className={styles.loadingLabel}>模版生成中...</span>\n </div>\n );\n}\n\ninterface FailedCardProps extends LoadingCardProps {\n onDelete: () => void;\n}\n\nfunction FailedCard({ name, onDelete }: FailedCardProps) {\n return (\n <div className={[styles.loadingCard, styles.failedCard].join(' ')} aria-label=\"模版生成失败\" data-testid={`failed-card-${name}`}>\n <div className={styles.previewContainer}>\n <img src=\"/images/ppt-template/template-error.png\" alt={name} className={styles.previewImage} draggable={false} />\n </div>\n <div className={styles.failedTitleArea}>\n <div className={styles.failedNameArea}>\n <OverflowTooltip content={name} forceShow className={styles.failedNameTooltip}>\n <span className={styles.failedName}>{name}</span>\n </OverflowTooltip>\n <OverflowTooltip content=\"模版生成失败,请删除后重新上传\" forceShow className={styles.failedInfoIcon}>\n <img src=\"/icons/status/info-error.svg\" alt=\"错误\" width={16} height={16} />\n </OverflowTooltip>\n </div>\n <span\n className={styles.failedDeleteBtn}\n onClick={onDelete}\n data-testid={`failed-card-delete-${name}`}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') onDelete(); }}\n >\n <MaskIcon name=\"delete\" className={styles.failedDeleteIcon} />\n </span>\n </div>\n </div>\n );\n}\n\n// ─── Main Component ────────────────────────────────────────────────────────────\n\nconst TAB_ITEMS = [\n { value: 'preset', label: '平台推荐' },\n { value: 'my', label: '我的模板' },\n];\n\nexport function TemplatePicker({ selectedTemplateId, onSelectChange, showCloseButton = false, onClose }: TemplatePickerProps) {\n const [activeTab, setActiveTab] = useState<'preset' | 'my'>('preset');\n const [presetTemplates, setPresetTemplates] = useState<TemplateItem[]>([]);\n const [myTemplates, setMyTemplates] = useState<TemplateItem[]>([]);\n const [searchKeyword, setSearchKeyword] = useState('');\n const [isUploading, setIsUploading] = useState(false);\n const [pollingIds, setPollingIds] = useState<string[]>([]);\n const [renameDialogTemplate, setRenameDialogTemplate] = useState<TemplateItem | null>(null);\n const [renameDialogValue, setRenameDialogValue] = useState('');\n const failedTemplateIdsRef = useRef<Set<string>>(new Set());\n const addToast = useToastStore((state) => state.addToast);\n const confirm = useConfirm();\n\n const refreshTemplates = useCallback(async () => {\n const res = await apiFetch('/api/ppt-templates');\n if (!res.ok) {\n throw new Error(`模板列表加载失败: HTTP ${res.status}`);\n }\n const data = (await res.json()) as ApiTemplateListResponse;\n const mapped = (data.templates ?? []).map(mapApiTemplate);\n const failedTemplates = mapped.filter((item) => item.source === 'my' && item.status === 'failed');\n const nextFailedIds = new Set(failedTemplates.map((item) => item.id));\n for (const failedTemplate of failedTemplates) {\n if (failedTemplateIdsRef.current.has(failedTemplate.id)) continue;\n addToast({\n type: 'error',\n title: '模板生成失败',\n message: `模板“${failedTemplate.name}”生成失败,请重新上传或删除该模板`,\n duration: 4000,\n });\n }\n failedTemplateIdsRef.current = nextFailedIds;\n setPresetTemplates(mapped.filter((item) => item.source === 'preset'));\n setMyTemplates(mapped.filter((item) => item.source === 'my'));\n setPollingIds(\n mapped\n .filter((item) => item.source === 'my' && item.status === 'parsing')\n .map((item) => item.id),\n );\n return mapped;\n }, [addToast]);\n\n const handleTabChange = useCallback((value: string) => {\n setActiveTab(value as 'preset' | 'my');\n setSearchKeyword('');\n }, []);\n\n const handleSearchChange = useCallback((value: string) => {\n setSearchKeyword(value);\n }, []);\n\n const handleSearchClear = useCallback(() => {\n setSearchKeyword('');\n }, []);\n\n const filteredMyTemplates = useMemo(\n () =>\n searchKeyword\n ? myTemplates.filter((t) => t.name.toLowerCase().includes(searchKeyword.toLowerCase()))\n : myTemplates,\n [searchKeyword, myTemplates],\n );\n\n const templates = activeTab === 'preset' ? presetTemplates : filteredMyTemplates;\n\n const handleMakeSame = useCallback(\n (template: TemplateItem) => {\n if (template.status !== 'ready') return;\n onSelectChange(template);\n },\n [onSelectChange],\n );\n\n const handleRename = useCallback(\n async (template: TemplateItem) => {\n setRenameDialogTemplate(template);\n setRenameDialogValue(template.name);\n },\n [],\n );\n\n const handleRenameConfirm = useCallback(\n async (nextName: string) => {\n if (!renameDialogTemplate) return;\n const normalizedName = normalizeTemplateName(nextName);\n if (!normalizedName || normalizedName === renameDialogTemplate.name) {\n setRenameDialogTemplate(null);\n return;\n }\n if (!isValidTemplateName(normalizedName)) {\n addToast({ type: 'error', title: '重命名失败', message: getTemplateNameValidationMessage(), duration: 4000 });\n return;\n }\n try {\n const res = await apiFetch(`/api/ppt-templates/${encodeURIComponent(renameDialogTemplate.id)}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ name: normalizedName }),\n });\n if (!res.ok) {\n const data = (await res.json().catch(() => null)) as { error?: string } | null;\n throw new Error(data?.error ?? `HTTP ${res.status}`);\n }\n await refreshTemplates();\n addToast({ type: 'success', title: '重命名成功', message: `模板已重命名为\"${normalizedName}\"`, duration: 2500 });\n } catch (error) {\n addToast({\n type: 'error',\n title: '重命名失败',\n message: error instanceof Error ? error.message : '模板重命名失败',\n duration: 4000,\n });\n } finally {\n setRenameDialogTemplate(null);\n }\n },\n [addToast, refreshTemplates, renameDialogTemplate],\n );\n\n const handleDelete = useCallback(\n async (template: TemplateItem) => {\n const ok = await confirm({ title: '确认删除模版', message: `确定要删除模板”${template.name}”吗?删除后,该模版将不可恢复`, confirmLabel: '删除' });\n if (!ok) return;\n try {\n const res = await apiFetch(`/api/ppt-templates/${encodeURIComponent(template.id)}`, {\n method: 'DELETE',\n });\n if (!res.ok) {\n const data = (await res.json().catch(() => null)) as { error?: string } | null;\n throw new Error(data?.error ?? `HTTP ${res.status}`);\n }\n if (selectedTemplateId === template.id) {\n onSelectChange(null);\n }\n await refreshTemplates();\n addToast({ type: 'success', title: '删除成功', message: `模板”${template.name}”已删除`, duration: 2500 });\n } catch (error) {\n addToast({\n type: 'error',\n title: '删除失败',\n message: error instanceof Error ? error.message : '模板删除失败',\n duration: 4000,\n });\n }\n },\n [addToast, confirm, onSelectChange, refreshTemplates, selectedTemplateId],\n );\n\n const handleFileSelect = useCallback(async (file: File) => {\n if (file.size > MAX_PPT_TEMPLATE_FILE_SIZE) {\n addToast({ type: 'error', title: '上传失败', message: PPT_UPLOAD_SIZE_MESSAGE, duration: 4000 });\n return;\n }\n\n const uploadBaseName = file.name.replace(/\\.(ppt|pptx)$/i, '').trim();\n if (uploadBaseName.length > MAX_PPT_TEMPLATE_NAME_LENGTH) {\n addToast({ type: 'error', title: '上传失败', message: PPT_UPLOAD_NAME_LENGTH_MESSAGE, duration: 4000 });\n return;\n }\n\n const normalizedName = normalizeTemplateName(uploadBaseName);\n // Create a placeholder template with parsing status\n const tempId = `uploading-${Date.now()}`;\n const newTemplate: TemplateItem = {\n id: tempId,\n name: normalizedName,\n thumbnailUrl: '',\n source: 'my',\n status: 'parsing',\n };\n\n setIsUploading(true);\n setMyTemplates((prev) => [newTemplate, ...prev]);\n\n try {\n const formData = new FormData();\n formData.append('file', file);\n formData.append('name', newTemplate.name);\n const res = await apiFetch('/api/ppt-templates/upload', {\n method: 'POST',\n body: formData,\n });\n const data = (await res.json().catch(() => null)) as { template?: ApiTemplateItem; error?: string } | null;\n if (!res.ok || !data?.template) {\n throw new Error(data?.error ?? `HTTP ${res.status}`);\n }\n const uploadedTemplate = data.template;\n setMyTemplates((prev) => [mapApiTemplate(uploadedTemplate), ...prev.filter((t) => t.id !== tempId)]);\n setPollingIds((prev) =>\n uploadedTemplate.status === 'ready'\n ? prev\n : Array.from(new Set([...prev, uploadedTemplate.templateId])),\n );\n addToast({ type: 'success', title: '上传成功', message: '模板已开始生成', duration: 2500 });\n } catch (error) {\n // On error, remove the placeholder\n setMyTemplates((prev) => prev.filter((t) => t.id !== tempId));\n const refreshedTemplates = await refreshTemplates().catch(() => null);\n const hasFailedTemplate = refreshedTemplates?.some(\n (template) => template.source === 'my' && template.status === 'failed' && template.name === newTemplate.name,\n );\n if (!hasFailedTemplate) {\n addToast({\n type: 'error',\n title: '上传失败',\n message: error instanceof Error ? error.message : '模板上传失败',\n duration: 4000,\n });\n }\n } finally {\n setIsUploading(false);\n }\n }, [addToast, refreshTemplates]);\n\n useEffect(() => {\n void refreshTemplates().catch((error) => {\n addToast({\n type: 'error',\n title: '加载失败',\n message: error instanceof Error ? error.message : '模板列表加载失败',\n duration: 4000,\n });\n });\n }, [addToast, refreshTemplates]);\n\n useEffect(() => {\n if (pollingIds.length === 0) return;\n const timer = window.setInterval(() => {\n void refreshTemplates().catch(() => {\n // Best effort polling; keep quiet to avoid repeated toast spam.\n });\n }, 2000);\n return () => {\n window.clearInterval(timer);\n };\n }, [pollingIds, refreshTemplates]);\n\n const renderGrid = () => {\n // 我的模板为空(无搜索关键词):上传卡片独占整个内容区\n if (activeTab === 'my' && myTemplates.length === 0 && !searchKeyword) {\n return (\n <div className={styles.grid}>\n <UploadCard\n isDragOver={false}\n isUploading={isUploading}\n isGenerating={pollingIds.length > 0}\n onFileSelect={handleFileSelect}\n isFull\n />\n </div>\n );\n }\n\n if (templates.length === 0) {\n return (\n <div className={styles.grid}>\n {activeTab === 'my' && (\n <UploadCard\n isDragOver={false}\n isUploading={isUploading}\n isGenerating={pollingIds.length > 0}\n onFileSelect={handleFileSelect}\n />\n )}\n <div className={styles.emptyState}>\n {activeTab === 'preset' ? '暂无论置模板' : '未找到匹配的模板'}\n </div>\n </div>\n );\n }\n\n return (\n <div className={styles.grid}>\n {activeTab === 'my' && (\n <UploadCard\n isDragOver={false}\n isUploading={isUploading}\n isGenerating={pollingIds.length > 0}\n onFileSelect={handleFileSelect}\n />\n )}\n {templates.map((template) => {\n if (template.status === 'parsing') {\n return <LoadingCard key={template.id} name={template.name} />;\n }\n if (template.status === 'failed') {\n return <FailedCard key={template.id} name={template.name} onDelete={() => void handleDelete(template)} />;\n }\n return (\n <MemoizedTemplateCard\n key={template.id}\n template={template}\n onMakeSame={handleMakeSame}\n onRename={handleRename}\n onDelete={handleDelete}\n isSelected={selectedTemplateId === template.id}\n />\n );\n })}\n </div>\n );\n };\n\n return (\n <div className={styles.container} data-testid=\"template-picker\">\n <div className={styles.tabRow}>\n <div className={styles.tabSection}>\n <Tab\n items={TAB_ITEMS}\n value={activeTab}\n onChange={handleTabChange}\n activeBorderColor=\"var(--tab-active-color)\"\n activeTextColor=\"var(--tab-active-color)\"\n />\n </div>\n {showCloseButton && (\n <button\n type=\"button\"\n aria-label=\"关闭\"\n onClick={onClose}\n className={styles.closeBtn}\n >\n <MaskIcon name=\"close\" className=\"h-4 w-4\" />\n </button>\n )}\n </div>\n\n {activeTab === 'my' && myTemplates.length > 3 && (\n <div className={styles.searchSection}>\n <SearchInput\n value={searchKeyword}\n onChange={handleSearchChange}\n onClear={handleSearchClear}\n placeholder=\"搜索我的模板...\"\n wrapperClassName=\"w-full\"\n />\n </div>\n )}\n\n <div className={styles.cardGrid}>{renderGrid()}</div>\n\n <PromptDialog\n open={renameDialogTemplate !== null}\n title=\"编辑模版名称\"\n inputValue={renameDialogValue}\n inputPlaceholder=\"请输入新的模板名称\"\n confirmLabel=\"确认\"\n cancelLabel=\"取消\"\n onConfirm={handleRenameConfirm}\n onCancel={() => setRenameDialogTemplate(null)}\n onInputChange={setRenameDialogValue}\n confirmDisabled={!renameDialogValue.trim() || renameDialogValue.trim() === renameDialogTemplate?.name}\n />\n </div>\n );\n}\nconst MAX_PPT_TEMPLATE_FILE_SIZE = 100 * 1024 * 1024;\nconst PPT_TEMPLATE_NAME_PATTERN = /^[A-Za-z0-9\\u4e00-\\u9fa5_-]+(?:[ ]+[A-Za-z0-9\\u4e00-\\u9fa5_-]+)*$/;\n\nfunction normalizeTemplateName(value: string): string {\n return value.trim().replace(/\\s+/g, ' ');\n}\n\nfunction isValidTemplateName(value: string): boolean {\n const normalized = normalizeTemplateName(value);\n return normalized.length > 0 && normalized.length <= MAX_PPT_TEMPLATE_NAME_LENGTH && PPT_TEMPLATE_NAME_PATTERN.test(normalized);\n}\n\nfunction getTemplateNameValidationMessage(): string {\n return `模板名称仅支持汉字、字母、数字、中划线、下划线和空格,且长度不超过 ${MAX_PPT_TEMPLATE_NAME_LENGTH} 个字符`;\n}\n","import { useEffect, useState } from 'react';\nimport type {\n ClipboardEvent,\n CSSProperties,\n Dispatch,\n DragEvent,\n KeyboardEvent,\n MutableRefObject,\n RefObject,\n SetStateAction,\n} from 'react';\nimport type { QuickActionConfig } from '@/config/quick-actions';\nimport type { PathEntry } from '@/hooks/usePathCompletion';\nimport type { QueueEntry } from '@/stores/chat-types';\nimport type { ParsedPrompt } from '@/utils/promptParser';\nimport type { SkillOption } from '@/utils/skill-options-cache';\nimport type { AgentOption } from '../chat-input-options';\nimport type { SelectedTemplateSummary, WorkspaceMenuItem } from '../types';\nimport { ACCEPTED_TYPES, MAX_INPUT_LENGTH } from '../utils/constants';\nimport { normalizeQuickActionsForSend, normalizeSkillsForSend } from '../utils/helpers';\nimport { ChatDragUploadOverlay } from './ChatDragUploadOverlay';\nimport { ChatInputBottomLeft } from './ChatInputBottomLeft';\nimport { ChatInputBottomRight } from './ChatInputBottomRight';\nimport { ChatInputMenus } from './ChatInputMenus';\nimport { ChatInputQueuePanel } from './ChatInputQueuePanel';\nimport { HistorySearchModal } from './HistorySearchModal';\nimport { ImagePreview } from './ImagePreview';\nimport { PathCompletionMenu } from './PathCompletionMenu';\nimport { QuickActionsPanel } from './QuickActionsPanel';\nimport type { RichTextareaHandle } from './RichTextarea';\nimport { RichTextarea } from './RichTextarea';\nimport type { RichQuickActionOption, RichSkillOption } from './rich-textarea-token-rendering';\nimport { TemplatePicker } from './TemplatePicker';\n\nexport interface ChatInputLayoutProps {\n hasActiveInvocation?: boolean;\n activeMenu: string | null;\n pathCompletion: {\n isOpen: boolean;\n entries: PathEntry[];\n selectedIdx: number;\n setSelectedIdx: (idx: number) => void;\n selectEntry: (entry: PathEntry) => string;\n };\n setInput: (next: string | ((prev: string) => string)) => void;\n textareaRef: RefObject<RichTextareaHandle>;\n mentionDataVersion?: number;\n\n filteredAgentOptions: AgentOption[];\n showMentions: boolean;\n mentionFilter: string;\n onMentionSearchChange: (value: string) => void;\n closeMenus: () => void;\n setMentionStart: Dispatch<SetStateAction<number>>;\n setMentionEnd: Dispatch<SetStateAction<number>>;\n clearMentionFilter: () => void;\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n insertMention: (option: AgentOption) => void;\n menuRef: RefObject<HTMLDivElement>;\n mentionMenuStyle: CSSProperties;\n\n imageLifecycleStatus: 'idle' | 'preparing' | 'uploading' | 'failed';\n uploadError: string | null;\n fileInputRef: RefObject<HTMLInputElement>;\n handleFileSelect: (event: React.ChangeEvent<HTMLInputElement>) => void;\n\n showQuickPrompts: boolean;\n quickActionsExpanded: boolean;\n quickActionsOverflowing: boolean;\n visibleQuickActions: QuickActionConfig[];\n selectedQuickAction: QuickActionConfig | null;\n queueAwareDisabled: boolean;\n quickActionsContainerRef: RefObject<HTMLDivElement>;\n quickActionsRowRef: RefObject<HTMLDivElement>;\n handleQuickAction: (config: QuickActionConfig) => void;\n handleQuickPrompt: (prompt: string) => void;\n handleExpertCardClick: (card: NonNullable<QuickActionConfig['expertCards']>[number]) => void;\n setQuickActionsExpanded: Dispatch<SetStateAction<boolean>>;\n\n queueCount: number;\n queuedEntries: QueueEntry[];\n queueAttachmentNamesByEntryId: Record<string, string[]>;\n queueExpanded: boolean;\n queueBusy: boolean;\n queueHighlightedEntryId: string | null;\n queueListRef: RefObject<HTMLDivElement>;\n setQueueExpanded: Dispatch<SetStateAction<boolean>>;\n handleQueueClear: () => Promise<void>;\n handleQueuePinToTop: (entryId: string) => Promise<void>;\n handleQueueDelete: (entryId: string) => Promise<void>;\n handleQueueEdit: (entryId: string) => void;\n\n showStyleTemplatePopover: boolean;\n styleTemplatePopoverRef: RefObject<HTMLDivElement>;\n selectedTemplate: SelectedTemplateSummary | null;\n onTemplateSelectChange: (template: { id: string; name: string } | null) => void;\n onTemplatePopoverClose: () => void;\n\n images: File[];\n handleRemoveImage: (index: number) => void;\n isDraggingFiles: boolean;\n input: string;\n handleChange: (value: string, selectionStart: number, selectionEnd: number) => void;\n setIsComposing: Dispatch<SetStateAction<boolean>>;\n resizeTextarea: () => void;\n handleKeyDown: (e: KeyboardEvent<HTMLDivElement>) => void;\n handlePaste: (event: ClipboardEvent<HTMLDivElement>) => void;\n handleDragEnter: (event: DragEvent<HTMLElement>) => void;\n handleDragOver: (event: DragEvent<HTMLElement>) => void;\n handleDragLeave: (event: DragEvent<HTMLElement>) => void;\n handleDrop: (event: DragEvent<HTMLElement>) => void;\n skillOptionsData: SkillOption[] | RichSkillOption[];\n quickActionOptions: RichQuickActionOption[];\n ghostSuggestion: string | null;\n isComposing: boolean;\n\n skillInsertAnchorRef: MutableRefObject<{ start: number; end: number } | null>;\n routerPush: (path: string) => void;\n skillBtnRef: RefObject<HTMLButtonElement>;\n styleTemplateBtnRef: RefObject<HTMLButtonElement>;\n handleSkillClick: () => void;\n guidedModeEnabled: boolean;\n onToggleGuidedMode: () => void;\n hasPptSkillInInput: boolean;\n handleStyleTemplateClick: () => void;\n onClearSelectedTemplate: () => void;\n showSkillMenu: boolean;\n skillFilter: string;\n onSkillSearchChange: (value: string) => void;\n filteredSkillOptions: SkillOption[];\n skillOptionsLoading: boolean;\n skillOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n insertSkill: (skillName: string) => void;\n\n setWorkspaceFilter: Dispatch<SetStateAction<string>>;\n folderSelectionEnabled: boolean;\n selectedFolderTitle: string | null;\n folderButtonLabel: string;\n shouldShowFolderTooltip: boolean;\n folderBtnRef: RefObject<HTMLButtonElement>;\n workspaceSearchInputRef: RefObject<HTMLInputElement>;\n workspaceFilter: string;\n showWorkspaceMenu: boolean;\n workspaceMenuItems: WorkspaceMenuItem[];\n workspaceOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n isFolderButtonDisabled: boolean;\n sendTemporarilyDisabled: boolean;\n queueSendDisabled: boolean;\n handleWorkspaceClick: () => void;\n handleWorkspaceMenuSelect: (item: WorkspaceMenuItem) => void;\n\n handleTranscript: (text: string) => void;\n handleSend: () => void;\n onStop?: () => void;\n handleQueueSend: () => void;\n dragOverlayHost: HTMLElement | null;\n\n showHistorySearch: boolean;\n handleHistorySelect: (text: string) => void;\n setShowHistorySearch: Dispatch<SetStateAction<boolean>>;\n\n isTemplate: boolean;\n parsed: ParsedPrompt | null;\n activePlaceholderId: string | null;\n handlePlaceholderFocus: (id: string) => void;\n handlePlaceholderBlur: () => void;\n handlePlaceholderDelete: (id: string) => void;\n handlePlaceholderTabNext: (currentId: string) => void;\n}\n\nexport function ChatInputLayout({\n hasActiveInvocation,\n activeMenu,\n pathCompletion,\n setInput,\n textareaRef,\n mentionDataVersion,\n filteredAgentOptions,\n showMentions,\n mentionFilter,\n onMentionSearchChange,\n closeMenus,\n setMentionStart,\n setMentionEnd,\n clearMentionFilter,\n selectedIdx,\n setSelectedIdx,\n insertMention,\n menuRef,\n mentionMenuStyle,\n imageLifecycleStatus,\n uploadError,\n fileInputRef,\n handleFileSelect,\n showQuickPrompts,\n quickActionsExpanded,\n quickActionsOverflowing,\n visibleQuickActions,\n selectedQuickAction,\n queueAwareDisabled,\n quickActionsContainerRef,\n quickActionsRowRef,\n handleQuickAction,\n handleQuickPrompt,\n handleExpertCardClick,\n setQuickActionsExpanded,\n queueCount,\n queuedEntries,\n queueAttachmentNamesByEntryId,\n queueExpanded,\n queueBusy,\n queueHighlightedEntryId,\n queueListRef,\n setQueueExpanded,\n handleQueueClear,\n handleQueuePinToTop,\n handleQueueDelete,\n handleQueueEdit,\n showStyleTemplatePopover,\n styleTemplatePopoverRef,\n selectedTemplate,\n onTemplateSelectChange,\n onTemplatePopoverClose,\n images,\n handleRemoveImage,\n isDraggingFiles,\n input,\n handleChange,\n setIsComposing,\n resizeTextarea,\n handleKeyDown,\n handlePaste,\n handleDragEnter,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n skillOptionsData,\n quickActionOptions,\n ghostSuggestion,\n isComposing,\n skillInsertAnchorRef,\n routerPush,\n skillBtnRef,\n styleTemplateBtnRef,\n handleSkillClick,\n guidedModeEnabled,\n onToggleGuidedMode,\n hasPptSkillInInput,\n handleStyleTemplateClick,\n onClearSelectedTemplate,\n showSkillMenu,\n skillFilter,\n onSkillSearchChange,\n filteredSkillOptions,\n skillOptionsLoading,\n skillOptionRefs,\n insertSkill,\n setWorkspaceFilter,\n folderSelectionEnabled,\n selectedFolderTitle,\n folderButtonLabel,\n shouldShowFolderTooltip,\n folderBtnRef,\n workspaceSearchInputRef,\n workspaceFilter,\n showWorkspaceMenu,\n workspaceMenuItems,\n workspaceOptionRefs,\n isFolderButtonDisabled,\n sendTemporarilyDisabled,\n queueSendDisabled,\n handleWorkspaceClick,\n handleWorkspaceMenuSelect,\n handleTranscript,\n handleSend,\n onStop,\n handleQueueSend,\n dragOverlayHost,\n showHistorySearch,\n handleHistorySelect,\n setShowHistorySearch,\n isTemplate,\n parsed,\n activePlaceholderId,\n handlePlaceholderFocus,\n handlePlaceholderBlur,\n handlePlaceholderDelete,\n handlePlaceholderTabNext,\n}: ChatInputLayoutProps) {\n const [isVoiceRecording, setIsVoiceRecording] = useState(false);\n\n useEffect(() => {\n if (typeof window === 'undefined') return;\n const handleVoiceState = (event: Event) => {\n const customEvent = event as CustomEvent<{ state?: string }>;\n setIsVoiceRecording(customEvent.detail?.state === 'recording');\n };\n window.addEventListener('office-claw:voice-state', handleVoiceState as EventListener);\n return () => {\n window.removeEventListener('office-claw:voice-state', handleVoiceState as EventListener);\n };\n }, []);\n\n const ghostDisplayInput = normalizeSkillsForSend(normalizeQuickActionsForSend(input));\n const ghostDisplaySuggestion = ghostSuggestion\n ? normalizeSkillsForSend(normalizeQuickActionsForSend(ghostSuggestion))\n : '';\n const ghostDisplaySuffix = ghostDisplaySuggestion.startsWith(ghostDisplayInput)\n ? ghostDisplaySuggestion.slice(ghostDisplayInput.length)\n : ghostDisplaySuggestion;\n const hasQuickActionToken = /\\[\\[quick_action:[^[\\]]+\\]\\]/.test(input);\n\n return (\n <div className=\"relative safe-area-bottom bg-transparent\">\n <div\n aria-hidden=\"true\"\n className=\"chat-layout-rail-glow pointer-events-none absolute bottom-0 left-1/2 z-0 h-[100px] -translate-x-1/2 opacity-[0.25] blur-[50px]\"\n style={{ borderRadius: '490px', background: 'var(--chat-input-accent-glow)' }}\n />\n\n {hasActiveInvocation && (\n <div className=\"chat-layout-rail hidden items-center gap-2 pt-2\">\n <span className=\"inline-block w-2 h-2 rounded-full bg-[var(--chat-input-queue-accent)] animate-pulse\" />\n <span className=\"text-xs font-medium text-[var(--chat-input-queue-accent)]\">正在回复中...</span>\n <span className=\"hidden text-xs text-[var(--text-label-secondary)]\">继续输入,消息会排队</span>\n </div>\n )}\n\n {pathCompletion.isOpen && !activeMenu && (\n <PathCompletionMenu\n entries={pathCompletion.entries}\n selectedIdx={pathCompletion.selectedIdx}\n onSelectIdx={pathCompletion.setSelectedIdx}\n onSelect={(entry) => {\n const newText = pathCompletion.selectEntry(entry);\n setInput(newText);\n setTimeout(() => textareaRef.current?.focus(), 0);\n }}\n />\n )}\n\n <ChatInputMenus\n agentOptions={filteredAgentOptions}\n showMentions={showMentions}\n mentionFilter={mentionFilter}\n onMentionFilterChange={onMentionSearchChange}\n onCloseMentionMenu={() => {\n closeMenus();\n setMentionStart(-1);\n setMentionEnd(-1);\n clearMentionFilter();\n }}\n selectedIdx={selectedIdx}\n onSelectIdx={setSelectedIdx}\n onInsertMention={insertMention}\n menuRef={menuRef}\n mentionMenuStyle={mentionMenuStyle}\n />\n\n {imageLifecycleStatus === 'preparing' && (\n <div className=\"chat-layout-rail pt-2 text-xs text-[var(--text-muted)]\" role=\"status\">\n 文件处理中,完成后可发送\n </div>\n )}\n {imageLifecycleStatus === 'uploading' && (\n <div className=\"chat-layout-rail pt-2 text-xs text-[var(--state-info-text)]\" role=\"status\">\n 文件上传中,请稍候...\n </div>\n )}\n {imageLifecycleStatus === 'failed' && uploadError && (\n <div className=\"chat-layout-rail pt-2 text-xs text-[var(--state-error-text)]\" role=\"alert\">\n 文件发送失败:{uploadError}\n </div>\n )}\n\n <input\n ref={fileInputRef}\n type=\"file\"\n accept={ACCEPTED_TYPES}\n multiple\n className=\"hidden\"\n onChange={handleFileSelect}\n />\n\n <div className=\"chat-layout-rail relative z-10 pt-2\">\n <div className=\"flex gap-2 items-end\">\n <div className=\"group min-w-0 flex-1\">\n <QuickActionsPanel\n showQuickPrompts={showQuickPrompts}\n quickActionsExpanded={quickActionsExpanded}\n quickActionsOverflowing={quickActionsOverflowing}\n visibleQuickActions={visibleQuickActions}\n selectedQuickAction={selectedQuickAction}\n queueAwareDisabled={queueAwareDisabled}\n quickActionsContainerRef={quickActionsContainerRef}\n quickActionsRowRef={quickActionsRowRef}\n onQuickAction={handleQuickAction}\n onQuickPrompt={handleQuickPrompt}\n onExpertCardClick={handleExpertCardClick}\n onToggleExpanded={() => setQuickActionsExpanded((prev) => !prev)}\n />\n\n {queueCount > 0 && (\n <ChatInputQueuePanel\n queuedEntries={queuedEntries}\n attachmentNamesByEntryId={queueAttachmentNamesByEntryId}\n queueCount={queueCount}\n queueExpanded={queueExpanded}\n queueBusy={queueBusy}\n queueHighlightedEntryId={queueHighlightedEntryId}\n listRef={queueListRef}\n onToggleExpanded={() => setQueueExpanded((prev) => !prev)}\n onClear={() => void handleQueueClear()}\n onPinToTop={(entryId) => void handleQueuePinToTop(entryId)}\n onDelete={(entryId) => void handleQueueDelete(entryId)}\n onEdit={handleQueueEdit}\n />\n )}\n\n <div className={`relative ${queueCount > 0 ? '-mt-5 z-10' : ''}`}>\n {showStyleTemplatePopover && (\n <div\n ref={styleTemplatePopoverRef}\n className=\"absolute bottom-full left-0 right-0 z-[260] mb-[8px] rounded-[16px] overflow-tooltip overflow-hidden\"\n data-testid=\"chat-input-style-template-popover\"\n >\n <TemplatePicker\n selectedTemplateId={selectedTemplate?.id}\n onSelectChange={onTemplateSelectChange}\n showCloseButton\n onClose={onTemplatePopoverClose}\n />\n </div>\n )}\n\n <div\n data-chat-input-dropzone=\"true\"\n className={`relative min-h-[114px] w-full min-w-0 overflow-visible rounded-[24px] border chat-input-shell bg-[var(--chat-input-bg)] ${\n isDraggingFiles ? 'border-[var(--text-accent)]' : ''\n }`}\n onDragEnter={handleDragEnter}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n <ImagePreview files={images} onRemove={handleRemoveImage} />\n <div className=\"relative overflow-hidden rounded-t-[24px]\">\n <RichTextarea\n ref={textareaRef}\n value={input}\n onValueChange={handleChange}\n mentionDataVersion={mentionDataVersion}\n onCompositionStateChange={setIsComposing}\n maxLength={MAX_INPUT_LENGTH}\n onInput={resizeTextarea}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={\n hasActiveInvocation ? '继续输入内容,将任务加入待执行队列' : '描述你想研究的主题或@助手协助工作'\n }\n className=\"chat-input-textarea block min-h-[70px] w-full bg-transparent px-[18px] py-4 text-[16px] leading-[24px] text-[var(--text-primary)] whitespace-pre-wrap break-words [overflow-wrap:anywhere] placeholder:text-[var(--text-field-placeholder)] focus:outline-none\"\n disabled={false}\n skillOptions={skillOptionsData}\n quickActionOptions={quickActionOptions}\n promptBlocks={\n isTemplate && parsed\n ? {\n parsed,\n activePlaceholderId,\n onFocus: handlePlaceholderFocus,\n onBlur: handlePlaceholderBlur,\n onDelete: handlePlaceholderDelete,\n onTabNext: handlePlaceholderTabNext,\n }\n : null\n }\n />\n\n {ghostSuggestion &&\n !isComposing &&\n !pathCompletion.isOpen &&\n !showMentions &&\n !hasQuickActionToken &&\n !/(^|\\s)@/.test(input) && (\n <div\n data-testid=\"ghost-suggestion\"\n className=\"pointer-events-none absolute inset-0 w-full overflow-hidden whitespace-pre-wrap break-words [overflow-wrap:anywhere] rounded-t-[24px] px-[18px] py-4 text-[16px] leading-[24px]\"\n aria-hidden=\"true\"\n >\n <span className=\"select-none opacity-0\">{ghostDisplayInput}</span>\n <span className=\"text-[var(--text-field-placeholder)]\">{ghostDisplaySuffix}</span>\n </div>\n )}\n </div>\n\n <div className=\"px-[10px] pb-[10px]\">\n <div className={`flex items-center gap-2 ${isVoiceRecording ? 'justify-end' : 'justify-between'}`}>\n {!isVoiceRecording && (\n <ChatInputBottomLeft\n input={input}\n textareaRef={textareaRef}\n skillInsertAnchorRef={skillInsertAnchorRef}\n closeMenus={closeMenus}\n routerPush={routerPush}\n skillBtnRef={skillBtnRef}\n styleTemplateBtnRef={styleTemplateBtnRef}\n onSkillClick={handleSkillClick}\n selectedQuickAction={selectedQuickAction}\n guidedModeEnabled={guidedModeEnabled}\n onToggleGuidedMode={onToggleGuidedMode}\n hasPptSkillInInput={hasPptSkillInInput}\n selectedTemplate={selectedTemplate}\n onStyleTemplateClick={handleStyleTemplateClick}\n onClearSelectedTemplate={onClearSelectedTemplate}\n showSkillMenu={showSkillMenu}\n menuRef={menuRef}\n skillFilter={skillFilter}\n onSkillFilterChange={onSkillSearchChange}\n filteredSkillOptions={filteredSkillOptions}\n skillOptionsLoading={skillOptionsLoading}\n selectedIdx={selectedIdx}\n setSelectedIdx={setSelectedIdx}\n skillOptionRefs={skillOptionRefs}\n onInsertSkill={insertSkill}\n onCloseMenus={closeMenus}\n />\n )}\n\n <ChatInputBottomRight\n fileInputRef={fileInputRef}\n setWorkspaceFilter={setWorkspaceFilter}\n closeMenus={closeMenus}\n folderSelectionEnabled={folderSelectionEnabled}\n selectedFolderTitle={selectedFolderTitle}\n folderButtonLabel={folderButtonLabel}\n shouldShowFolderTooltip={shouldShowFolderTooltip}\n folderBtnRef={folderBtnRef}\n menuRef={menuRef}\n workspaceSearchInputRef={workspaceSearchInputRef}\n workspaceFilter={workspaceFilter}\n showWorkspaceMenu={showWorkspaceMenu}\n workspaceMenuItems={workspaceMenuItems}\n selectedIdx={selectedIdx}\n setSelectedIdx={setSelectedIdx}\n workspaceOptionRefs={workspaceOptionRefs}\n isFolderButtonDisabled={isFolderButtonDisabled}\n queueAwareDisabled={queueAwareDisabled}\n sendTemporarilyDisabled={sendTemporarilyDisabled}\n imagesCount={images.length}\n hasActiveInvocation={hasActiveInvocation}\n inputTrimmed={!!input.trim()}\n queueSendDisabled={queueSendDisabled}\n queueCount={queueCount}\n onWorkspaceClick={handleWorkspaceClick}\n onWorkspaceSelect={handleWorkspaceMenuSelect}\n onTranscript={handleTranscript}\n onSend={handleSend}\n onStop={onStop}\n onQueueSend={handleQueueSend}\n />\n </div>\n </div>\n </div>\n\n <p className=\"mt-2 mb-4 text-center text-[12px] font-normal leading-[20px] text-[var(--text-disabled)]\">\n 内容由AI生成,仅供参考\n </p>\n </div>\n </div>\n </div>\n </div>\n\n {showHistorySearch && (\n <HistorySearchModal onSelect={handleHistorySelect} onClose={() => setShowHistorySearch(false)} />\n )}\n\n <ChatDragUploadOverlay isVisible={isDraggingFiles} host={dragOverlayHost} />\n </div>\n );\n}\n\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport type { UploadStatus } from '@/hooks/useSendMessage';\n\nexport type ImageLifecycleStatus = UploadStatus | 'preparing';\n\nexport function deriveImageLifecycleStatus(\n isPreparingImages: boolean,\n uploadStatus: UploadStatus,\n): ImageLifecycleStatus {\n if (isPreparingImages) return 'preparing';\n return uploadStatus;\n}\n\nexport function isImageLifecycleBlockingSend(status: ImageLifecycleStatus): boolean {\n return status === 'preparing' || status === 'uploading';\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n FILE_SIZE_EXCEEDED_MESSAGE,\n IMAGE_SIZE_EXCEEDED_MESSAGE,\n MAX_ATTACHMENT_FILES,\n MAX_FILE_SIZE,\n MAX_IMAGE_SIZE,\n UNSUPPORTED_FILE_TYPE_MESSAGE,\n} from '../utils/constants';\nimport { isSupportedAttachmentFile, mergeFilesByName } from '../utils/helpers';\n\nexport type AddToast = (toast: { type: 'error' | 'success' | 'info'; title: string; message: string; duration?: number }) => void;\n\nexport function useAttachmentManager(addToast: AddToast, dropScope?: HTMLElement | null) {\n const [images, setImages] = useState<File[]>([]);\n const [isDraggingFiles, setIsDraggingFiles] = useState(false);\n const imagesRef = useRef<File[]>([]);\n const dragDepthRef = useRef(0);\n const dragHideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n useEffect(() => {\n imagesRef.current = images;\n }, [images]);\n\n const onFilesAccepted = useCallback(\n (files: File[]) => {\n const supportedFiles: File[] = [];\n let hasUnsupported = false;\n let hasOversizedFile = false;\n let hasOversizedImage = false;\n\n for (const file of files) {\n if (!isSupportedAttachmentFile(file)) {\n hasUnsupported = true;\n continue;\n }\n const isImage = file.type.startsWith('image/');\n const maxSize = isImage ? MAX_IMAGE_SIZE : MAX_FILE_SIZE;\n if (file.size > maxSize) {\n if (isImage) {\n hasOversizedImage = true;\n } else {\n hasOversizedFile = true;\n }\n continue;\n }\n supportedFiles.push(file);\n }\n\n if (hasUnsupported) {\n addToast({ type: 'error', title: '上传失败', message: UNSUPPORTED_FILE_TYPE_MESSAGE, duration: 2600 });\n }\n if (hasOversizedFile) {\n addToast({ type: 'error', title: '上传失败', message: FILE_SIZE_EXCEEDED_MESSAGE, duration: 2600 });\n }\n if (hasOversizedImage) {\n addToast({ type: 'error', title: '上传失败', message: IMAGE_SIZE_EXCEEDED_MESSAGE, duration: 2600 });\n }\n\n if (supportedFiles.length > 0) {\n const result = mergeFilesByName(imagesRef.current, supportedFiles, MAX_ATTACHMENT_FILES);\n setImages(result.files);\n if (result.dropped > 0) {\n addToast({\n type: 'error',\n title: '附件数量已达上限',\n message: `最多支持选择 ${MAX_ATTACHMENT_FILES} 个附件`,\n duration: 2600,\n });\n }\n }\n\n return supportedFiles.length > 0;\n },\n [addToast],\n );\n\n const handleFileSelect = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const files = e.target.files;\n if (!files) return;\n onFilesAccepted(Array.from(files));\n e.target.value = '';\n },\n [onFilesAccepted],\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent) => {\n const items = e.clipboardData?.items;\n if (!items) return;\n const hasText = Array.from(items).some(\n (item) => item.kind === 'string' && (item.type === 'text/plain' || item.type === 'text/html'),\n );\n if (hasText) return;\n\n const pastedFiles: File[] = [];\n for (let i = 0; i < items.length; i++) {\n if (items[i].kind !== 'file') continue;\n const file = items[i].getAsFile();\n if (file) pastedFiles.push(file);\n }\n if (pastedFiles.length === 0) return;\n\n const accepted = onFilesAccepted(pastedFiles);\n if (accepted) {\n e.preventDefault();\n }\n },\n [onFilesAccepted],\n );\n\n const handleRemoveImage = useCallback((index: number) => {\n setImages((prev: File[]) => prev.filter((_: File, i: number) => i !== index));\n }, []);\n\n const hasDraggedFiles = useCallback((dataTransfer: DataTransfer | null | undefined) => {\n if (!dataTransfer) return false;\n if ((dataTransfer.files?.length ?? 0) > 0) return true;\n const types = Array.from(dataTransfer.types ?? []);\n return types.includes('Files') || types.includes('application/x-moz-file') || types.includes('public.file-url');\n }, []);\n\n const handleDragEnter = useCallback(\n (event: React.DragEvent<HTMLElement>) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n event.preventDefault();\n dragDepthRef.current += 1;\n setIsDraggingFiles(true);\n },\n [hasDraggedFiles],\n );\n\n const handleDragOver = useCallback(\n (event: React.DragEvent<HTMLElement>) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = 'copy';\n setIsDraggingFiles(true);\n },\n [hasDraggedFiles],\n );\n\n const handleDragLeave = useCallback(\n (event: React.DragEvent<HTMLElement>) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n event.preventDefault();\n dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);\n if (dragDepthRef.current === 0) {\n setIsDraggingFiles(false);\n }\n },\n [hasDraggedFiles],\n );\n\n const handleDrop = useCallback(\n (event: React.DragEvent<HTMLElement>) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n event.preventDefault();\n dragDepthRef.current = 0;\n setIsDraggingFiles(false);\n const droppedFiles = Array.from(event.dataTransfer?.files ?? []);\n if (droppedFiles.length === 0) return;\n onFilesAccepted(droppedFiles);\n },\n [hasDraggedFiles, onFilesAccepted],\n );\n\n useEffect(() => {\n const scope = dropScope;\n if (!scope) return;\n\n const clearHideTimer = () => {\n if (!dragHideTimerRef.current) return;\n clearTimeout(dragHideTimerRef.current);\n dragHideTimerRef.current = null;\n };\n\n const clearDragging = () => {\n clearHideTimer();\n dragDepthRef.current = 0;\n setIsDraggingFiles(false);\n };\n\n const scheduleHideDragging = () => {\n clearHideTimer();\n dragHideTimerRef.current = setTimeout(() => {\n dragDepthRef.current = 0;\n setIsDraggingFiles(false);\n dragHideTimerRef.current = null;\n }, 80);\n };\n\n const isInDropScope = (event: DragEvent) => {\n const target = event.target;\n return target instanceof Node && scope.contains(target);\n };\n\n const shouldHandleNativeEvent = (event: DragEvent) => {\n const target = event.target;\n if (!(target instanceof Node)) return false;\n if (!scope.contains(target)) return false;\n if (target instanceof Element && target.closest('[data-chat-input-dropzone=\"true\"]')) {\n return false;\n }\n return true;\n };\n\n const onNativeDragEnter = (event: DragEvent) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n if (!isInDropScope(event)) return;\n event.preventDefault();\n clearHideTimer();\n dragDepthRef.current += 1;\n setIsDraggingFiles(true);\n };\n\n const onNativeDragOver = (event: DragEvent) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n if (!isInDropScope(event)) {\n scheduleHideDragging();\n return;\n }\n event.preventDefault();\n clearHideTimer();\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'copy';\n }\n setIsDraggingFiles(true);\n };\n\n const onNativeDragLeave = (event: DragEvent) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n if (!isInDropScope(event)) return;\n event.preventDefault();\n dragDepthRef.current = Math.max(0, dragDepthRef.current - 1);\n if (dragDepthRef.current === 0) {\n scheduleHideDragging();\n }\n };\n\n const onNativeDrop = (event: DragEvent) => {\n if (!hasDraggedFiles(event.dataTransfer)) return;\n if (!shouldHandleNativeEvent(event)) {\n clearDragging();\n return;\n }\n event.preventDefault();\n clearDragging();\n const droppedFiles = Array.from(event.dataTransfer?.files ?? []);\n if (droppedFiles.length === 0) return;\n onFilesAccepted(droppedFiles);\n };\n\n // Use capture phase on document to reliably receive native drag events\n // across deeply nested children inside the chat session area.\n document.addEventListener('dragenter', onNativeDragEnter, true);\n document.addEventListener('dragover', onNativeDragOver, true);\n document.addEventListener('dragleave', onNativeDragLeave, true);\n document.addEventListener('drop', onNativeDrop, true);\n\n return () => {\n document.removeEventListener('dragenter', onNativeDragEnter, true);\n document.removeEventListener('dragover', onNativeDragOver, true);\n document.removeEventListener('dragleave', onNativeDragLeave, true);\n document.removeEventListener('drop', onNativeDrop, true);\n clearDragging();\n };\n }, [dropScope, hasDraggedFiles, onFilesAccepted]);\n\n return {\n images,\n setImages,\n imagesRef,\n isDraggingFiles,\n handleFileSelect,\n handlePaste,\n handleRemoveImage,\n handleDragEnter,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n };\n}\n\n","import { useCallback } from 'react';\nimport type { Dispatch, MutableRefObject, SetStateAction } from 'react';\nimport { detectMenuTrigger } from '../chat-input-options';\nimport { clampInputLength } from '../utils/helpers';\n\ninterface UseChatInputInputFlowParams {\n setInput: (next: string | ((prev: string) => string)) => void;\n setShowMentions: Dispatch<SetStateAction<boolean>>;\n setShowSkillMenu: Dispatch<SetStateAction<boolean>>;\n setMentionStart: Dispatch<SetStateAction<number>>;\n setMentionEnd: Dispatch<SetStateAction<number>>;\n setMentionFilterValue: (value: string) => void;\n clearMentionFilter: () => void;\n clearSkillFilter: () => void;\n closeMenus: () => void;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n skillInsertAnchorRef: MutableRefObject<{ start: number; end: number } | null>;\n}\n\nexport function useChatInputInputFlow({\n setInput,\n setShowMentions,\n setShowSkillMenu,\n setMentionStart,\n setMentionEnd,\n setMentionFilterValue,\n clearMentionFilter,\n clearSkillFilter,\n closeMenus,\n setSelectedIdx,\n skillInsertAnchorRef,\n}: UseChatInputInputFlowParams) {\n const handleChange = useCallback(\n (val: string, selectionStart: number, selectionEnd: number) => {\n const next = clampInputLength(val);\n setInput(next);\n const normalizedSelectionStart = Math.min(selectionStart, next.length);\n const normalizedSelectionEnd = Math.min(selectionEnd, next.length);\n skillInsertAnchorRef.current = { start: normalizedSelectionStart, end: normalizedSelectionEnd };\n const trigger = detectMenuTrigger(next, normalizedSelectionStart);\n if (trigger?.type === 'mention') {\n setShowMentions(true);\n setShowSkillMenu(false);\n setMentionStart(trigger.start);\n setMentionEnd(normalizedSelectionStart);\n setMentionFilterValue(trigger.filter);\n setSelectedIdx(0);\n } else {\n closeMenus();\n setMentionStart(-1);\n setMentionEnd(-1);\n clearMentionFilter();\n clearSkillFilter();\n }\n },\n [\n clearMentionFilter,\n clearSkillFilter,\n closeMenus,\n setInput,\n setMentionEnd,\n setMentionFilterValue,\n setMentionStart,\n setSelectedIdx,\n setShowMentions,\n setShowSkillMenu,\n skillInsertAnchorRef,\n ],\n );\n\n return { handleChange };\n}\n","import { useCallback } from 'react';\nimport type { Dispatch, KeyboardEvent, MutableRefObject, RefObject, SetStateAction } from 'react';\nimport type { PathEntry } from '@/hooks/usePathCompletion';\nimport { useInputHistoryStore } from '@/stores/inputHistoryStore';\nimport type { AgentOption } from '../chat-input-options';\nimport { restoreSkillTokensFromSendText } from '../utils/helpers';\nimport type { WorkspaceMenuItem } from '../types';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\n\ninterface UseChatInputKeyboardParams {\n input: string;\n hasActiveInvocation?: boolean;\n activeMenu: 'mention' | 'skill' | 'workspace' | null;\n activeOptionsCount: number;\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n filteredAgentOptions: AgentOption[];\n filteredSkillOptions: Array<{ name: string }>;\n workspaceMenuItems: WorkspaceMenuItem[];\n textareaRef: RefObject<RichTextareaHandle>;\n setInput: (next: string | ((prev: string) => string)) => void;\n closeMenus: () => void;\n clearMentionFilter: () => void;\n clearSkillFilter: () => void;\n setMentionStart: Dispatch<SetStateAction<number>>;\n setMentionEnd: Dispatch<SetStateAction<number>>;\n insertMention: (option: AgentOption) => void;\n insertSkill: (skillName: string) => void;\n handleWorkspaceMenuSelect: (item: WorkspaceMenuItem) => void;\n handleSend: () => void;\n handleQueueSend: () => void;\n setGhostSuggestion: Dispatch<SetStateAction<string | null>>;\n ghostRef: MutableRefObject<string | null>;\n setShowHistorySearch: Dispatch<SetStateAction<boolean>>;\n pathCompletion: {\n isOpen: boolean;\n entries: PathEntry[];\n selectedIdx: number;\n setSelectedIdx: (idx: number) => void;\n selectEntry: (entry: PathEntry) => string;\n close: () => void;\n };\n}\n\nfunction isOpenHistoryShortcut(e: KeyboardEvent<HTMLDivElement>): boolean {\n return e.ctrlKey && e.key === 'r';\n}\n\nfunction isInsertNewlineShortcut(e: KeyboardEvent<HTMLDivElement>): boolean {\n return e.ctrlKey && e.key === 'Enter';\n}\n\nexport function useChatInputKeyboard({\n input,\n hasActiveInvocation,\n activeMenu,\n activeOptionsCount,\n selectedIdx,\n setSelectedIdx,\n filteredAgentOptions,\n filteredSkillOptions,\n workspaceMenuItems,\n textareaRef,\n setInput,\n closeMenus,\n clearMentionFilter,\n clearSkillFilter,\n setMentionStart,\n setMentionEnd,\n insertMention,\n insertSkill,\n handleWorkspaceMenuSelect,\n handleSend,\n handleQueueSend,\n setGhostSuggestion,\n ghostRef,\n setShowHistorySearch,\n pathCompletion,\n}: UseChatInputKeyboardParams) {\n const closeAllMenus = useCallback(() => {\n closeMenus();\n setMentionStart(-1);\n setMentionEnd(-1);\n clearMentionFilter();\n clearSkillFilter();\n }, [clearMentionFilter, clearSkillFilter, closeMenus, setMentionEnd, setMentionStart]);\n\n const handleMenuNavigation = useCallback(\n (e: KeyboardEvent<HTMLDivElement>): boolean => {\n if (!activeMenu) return false;\n\n if (activeOptionsCount === 0) {\n if ((e.key === 'Enter' && !e.shiftKey) || e.key === 'Tab' || e.key === 'Escape') {\n e.preventDefault();\n }\n closeAllMenus();\n return true;\n }\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setSelectedIdx((i) => (i + 1) % activeOptionsCount);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setSelectedIdx((i) => (i - 1 + activeOptionsCount) % activeOptionsCount);\n return true;\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n if (activeMenu === 'mention') {\n const opt = filteredAgentOptions[selectedIdx];\n if (!opt) {\n closeMenus();\n return true;\n }\n insertMention(opt);\n return true;\n }\n if (activeMenu === 'skill') {\n const skill = filteredSkillOptions[selectedIdx];\n if (!skill) {\n closeMenus();\n return true;\n }\n insertSkill(skill.name);\n return true;\n }\n const item = workspaceMenuItems[selectedIdx];\n if (!item) {\n closeMenus();\n return true;\n }\n handleWorkspaceMenuSelect(item);\n return true;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n closeMenus();\n setMentionStart(-1);\n setMentionEnd(-1);\n return true;\n }\n return false;\n },\n [\n activeMenu,\n activeOptionsCount,\n closeAllMenus,\n closeMenus,\n filteredAgentOptions,\n filteredSkillOptions,\n handleWorkspaceMenuSelect,\n insertMention,\n insertSkill,\n selectedIdx,\n setMentionEnd,\n setMentionStart,\n setSelectedIdx,\n workspaceMenuItems,\n ],\n );\n\n const handlePathCompletionNavigation = useCallback(\n (e: KeyboardEvent<HTMLDivElement>): boolean => {\n if (!pathCompletion.isOpen) return false;\n\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n pathCompletion.setSelectedIdx((pathCompletion.selectedIdx + 1) % pathCompletion.entries.length);\n return true;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n pathCompletion.setSelectedIdx(\n (pathCompletion.selectedIdx - 1 + pathCompletion.entries.length) % pathCompletion.entries.length,\n );\n return true;\n }\n if (e.key === 'Tab' || e.key === 'Enter') {\n e.preventDefault();\n const entry = pathCompletion.entries[pathCompletion.selectedIdx];\n if (entry) {\n const newText = pathCompletion.selectEntry(entry);\n const el = textareaRef.current;\n if (el) {\n el.applyProgrammaticChange(newText, newText.length, newText.length);\n } else {\n setInput(newText);\n }\n }\n return true;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n pathCompletion.close();\n return true;\n }\n return false;\n },\n [pathCompletion, setInput, textareaRef],\n );\n\n const handleHistoryGhostAccept = useCallback(\n (e: KeyboardEvent<HTMLDivElement>): boolean => {\n if (e.key !== 'Tab' && e.key !== 'ArrowRight') return false;\n\n const ta = textareaRef.current;\n const currentVal = input;\n const selectionStart = ta?.getSelectionStart() ?? currentVal.length;\n const selectionEnd = ta?.getSelectionEnd() ?? currentVal.length;\n const cursorAtEnd = selectionStart === selectionEnd && selectionStart === currentVal.length;\n if (e.key === 'ArrowRight' && !cursorAtEnd) return false;\n\n const match = useInputHistoryStore.getState().findMatch(currentVal);\n if (!match) return false;\n const restoredMatch = restoreSkillTokensFromSendText(match, []);\n\n e.preventDefault();\n const el = textareaRef.current;\n if (el) {\n el.applyProgrammaticChange(restoredMatch, restoredMatch.length, restoredMatch.length);\n } else {\n setInput(restoredMatch);\n }\n ghostRef.current = null;\n setGhostSuggestion(null);\n return true;\n },\n [ghostRef, input, setGhostSuggestion, setInput, textareaRef],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (e.nativeEvent.isComposing) return;\n\n if (isOpenHistoryShortcut(e)) {\n e.preventDefault();\n closeAllMenus();\n setShowHistorySearch(true);\n return;\n }\n\n if (isInsertNewlineShortcut(e)) {\n e.preventDefault();\n const ta = textareaRef.current;\n const start = ta?.getSelectionStart() ?? input.length;\n const end = ta?.getSelectionEnd() ?? input.length;\n const next = `${input.slice(0, start)}\\n${input.slice(end)}`;\n setInput(next);\n closeMenus();\n pathCompletion.close();\n setTimeout(() => {\n textareaRef.current?.focus();\n textareaRef.current?.setSelectionRange(start + 1, start + 1);\n }, 0);\n return;\n }\n\n if (handleMenuNavigation(e)) return;\n if (handlePathCompletionNavigation(e)) return;\n if (handleHistoryGhostAccept(e)) return;\n\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n if (hasActiveInvocation) handleQueueSend();\n else handleSend();\n }\n },\n [\n closeAllMenus,\n closeMenus,\n handleHistoryGhostAccept,\n handleMenuNavigation,\n handlePathCompletionNavigation,\n handleQueueSend,\n handleSend,\n hasActiveInvocation,\n input,\n pathCompletion,\n setInput,\n setShowHistorySearch,\n textareaRef,\n ],\n );\n\n return { handleKeyDown };\n}\n","import { useCallback, useState } from 'react';\n\nexport function useChatInputMenus() {\n const [showMentions, setShowMentions] = useState(false);\n const [showSkillMenu, setShowSkillMenu] = useState(false);\n const [showWorkspaceMenu, setShowWorkspaceMenu] = useState(false);\n const [showStyleTemplatePopover, setShowStyleTemplatePopover] = useState(false);\n const [selectedIdx, setSelectedIdx] = useState(0);\n\n const closeMenus = useCallback(() => {\n setShowMentions(false);\n setShowSkillMenu(false);\n setShowWorkspaceMenu(false);\n setShowStyleTemplatePopover(false);\n }, []);\n\n const toggleSkillMenu = useCallback((onOpen?: () => void) => {\n setShowMentions(false);\n setShowSkillMenu((prev) => {\n const next = !prev;\n if (next) onOpen?.();\n return next;\n });\n setShowWorkspaceMenu(false);\n setShowStyleTemplatePopover(false);\n setSelectedIdx(0);\n }, []);\n\n const toggleWorkspaceMenu = useCallback(() => {\n setShowMentions(false);\n setShowSkillMenu(false);\n setShowStyleTemplatePopover(false);\n setShowWorkspaceMenu((prev) => !prev);\n setSelectedIdx(0);\n }, []);\n\n const toggleStyleTemplatePopover = useCallback(() => {\n setShowMentions(false);\n setShowSkillMenu(false);\n setShowWorkspaceMenu(false);\n setShowStyleTemplatePopover((prev) => !prev);\n }, []);\n\n return {\n showMentions,\n setShowMentions,\n showSkillMenu,\n setShowSkillMenu,\n showWorkspaceMenu,\n setShowWorkspaceMenu,\n showStyleTemplatePopover,\n setShowStyleTemplatePopover,\n selectedIdx,\n setSelectedIdx,\n closeMenus,\n toggleSkillMenu,\n toggleWorkspaceMenu,\n toggleStyleTemplatePopover,\n };\n}\n","'use client';\n\nimport {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type RefObject,\n} from 'react';\nimport { QUICK_ACTIONS, type QuickActionConfig } from '@/config/quick-actions';\nimport type { AgentData } from '@/hooks/useAgentData';\nimport type { MentionRef } from '@/hooks/useSendMessage';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\nimport { QUICK_ACTION_TOKEN_PREFIX, QUICK_ACTION_TOKEN_SUFFIX } from '../utils/constants';\nimport { buildResolvedMention } from '../utils/helpers';\n\nfunction stripExpertCardMentionPrefix(content: string, displayNames: string[]): string {\n const displayPrefix = displayNames.map((name) => `@${name}`).join('');\n if (displayPrefix && content.startsWith(displayPrefix)) {\n return content\n .slice(displayPrefix.length)\n .replace(/^[,,]\\s*/, '')\n .trimStart();\n }\n return content.replace(/^(?:@[^@\\s,,]+)+[,,]?\\s*/, '').trimStart();\n}\n\nexport function getQuickActionToken(label: string): string {\n return `${QUICK_ACTION_TOKEN_PREFIX}${label}${QUICK_ACTION_TOKEN_SUFFIX}`;\n}\n\nexport function normalizeQuickActionsForSend(input: string): string {\n let output = input;\n for (const action of QUICK_ACTIONS) {\n const token = getQuickActionToken(action.label);\n output = output.split(token).join(action.label);\n }\n return output;\n}\n\ninterface UseQuickActionsArgs {\n input: string;\n agents: AgentData[];\n queueAwareDisabled: boolean;\n textareaRef: RefObject<RichTextareaHandle | null>;\n applyProgrammaticInput: (next: string, caret: number) => void;\n onQuickActionSelected?: () => void;\n onExpertCardClicked?: () => void;\n onMentionRefsChanged?: (refs: MentionRef[]) => void;\n onMentionRefsCleared?: () => void;\n}\n\nexport function useQuickActions({\n input,\n agents,\n queueAwareDisabled,\n textareaRef,\n applyProgrammaticInput,\n onQuickActionSelected,\n onExpertCardClicked,\n onMentionRefsChanged,\n onMentionRefsCleared,\n}: UseQuickActionsArgs) {\n const [selectedQuickAction, setSelectedQuickAction] = useState<QuickActionConfig | null>(null);\n const [showQuickPrompts, setShowQuickPrompts] = useState(false);\n const [pendingQuickPromptExpand, setPendingQuickPromptExpand] = useState(false);\n const [quickActionsExpanded, setQuickActionsExpanded] = useState(false);\n const [quickActionsOverflowing, setQuickActionsOverflowing] = useState(false);\n\n const quickActionsContainerRef = useRef<HTMLDivElement>(null);\n const quickActionsRowRef = useRef<HTMLDivElement>(null);\n const expertCardClickedRef = useRef(false);\n\n const visibleQuickActions = useMemo(() => QUICK_ACTIONS.filter((action) => action.show !== false), []);\n\n const handleQuickAction = useCallback(\n (action: QuickActionConfig) => {\n const token = getQuickActionToken(action.label);\n const next = `${token} `;\n applyProgrammaticInput(next, next.length);\n setPendingQuickPromptExpand(false);\n setShowQuickPrompts(true);\n expertCardClickedRef.current = false;\n onMentionRefsCleared?.();\n onQuickActionSelected?.();\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n el.setSelectionRange(next.length, next.length);\n }, 0);\n },\n [applyProgrammaticInput, onMentionRefsCleared, onQuickActionSelected, textareaRef],\n );\n\n const handleQuickPrompt = useCallback(\n (prompt: string) => {\n const startIdx = input.indexOf(QUICK_ACTION_TOKEN_PREFIX);\n const endIdx =\n startIdx >= 0 ? input.indexOf(QUICK_ACTION_TOKEN_SUFFIX, startIdx + QUICK_ACTION_TOKEN_PREFIX.length) : -1;\n\n let next = input;\n let caret = input.length;\n if (startIdx >= 0 && endIdx > startIdx) {\n const tokenEndExclusive = endIdx + QUICK_ACTION_TOKEN_SUFFIX.length;\n const before = input.slice(0, tokenEndExclusive);\n const after = input.slice(tokenEndExclusive).replace(/^\\s+/, '');\n const joiner = after.length > 0 ? ' ' : '';\n next = `${before} ${prompt}${joiner}${after}`;\n caret = next.length;\n } else {\n const ta = textareaRef.current;\n const start = ta?.getSelectionStart() ?? input.length;\n const end = ta?.getSelectionEnd() ?? input.length;\n const before = input.slice(0, start);\n const after = input.slice(end);\n const leftJoiner = before.endsWith(' ') || before.length === 0 ? '' : ' ';\n const rightJoiner = after.startsWith(' ') || after.length === 0 ? '' : ' ';\n next = `${before}${leftJoiner}${prompt}${rightJoiner}${after}`;\n caret = next.length;\n }\n\n applyProgrammaticInput(next, caret);\n setPendingQuickPromptExpand(false);\n setShowQuickPrompts(false);\n onMentionRefsCleared?.();\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n el.setSelectionRange(caret, caret);\n }, 0);\n },\n [applyProgrammaticInput, input, onMentionRefsCleared, textareaRef],\n );\n\n const handleExpertCardClick = useCallback(\n (card: NonNullable<QuickActionConfig['expertCards']>[number]) => {\n const mentionTargets =\n card.mentionTargetIds\n ?.map((id) => agents.find((row) => row.id === id))\n .filter((row): row is AgentData => Boolean(row)) ?? [];\n const mentionText = mentionTargets\n .map(buildResolvedMention)\n .filter((item): item is string => Boolean(item))\n .join(' ');\n const mentionRefs = mentionTargets\n .map((agent) => {\n const mention = buildResolvedMention(agent);\n return mention ? ({ catId: agent.id, mention } satisfies MentionRef) : null;\n })\n .filter((item): item is MentionRef => item !== null);\n const displayNames = mentionTargets.map((row) => row.displayName.trim()).filter(Boolean);\n const body = mentionText ? stripExpertCardMentionPrefix(card.content, displayNames) : card.content;\n const fullText = mentionText ? `${mentionText} ${body}`.trim() : `@${card.agentName} ${card.content}`;\n\n const startIdx = input.indexOf(QUICK_ACTION_TOKEN_PREFIX);\n const endIdx =\n startIdx >= 0 ? input.indexOf(QUICK_ACTION_TOKEN_SUFFIX, startIdx + QUICK_ACTION_TOKEN_PREFIX.length) : -1;\n\n let next = input;\n let caret = 0;\n if (startIdx >= 0 && endIdx > startIdx) {\n const tokenEndExclusive = endIdx + QUICK_ACTION_TOKEN_SUFFIX.length;\n const before = input.slice(0, tokenEndExclusive);\n const after = input.slice(tokenEndExclusive).replace(/^\\s+/, '');\n const rightJoiner = after.length > 0 ? ' ' : '';\n next = `${before} ${fullText}${rightJoiner}${after}`;\n caret = (before + ' ' + fullText).length;\n } else {\n const ta = textareaRef.current;\n const start = ta?.getSelectionStart() ?? input.length;\n const end = ta?.getSelectionEnd() ?? input.length;\n const before = input.slice(0, start);\n const after = input.slice(end);\n const leftJoiner = before.endsWith(' ') || before.length === 0 ? '' : ' ';\n const rightJoiner = after.startsWith(' ') || after.length === 0 ? '' : ' ';\n next = `${before}${leftJoiner}${fullText}${rightJoiner}${after}`;\n caret = (before + leftJoiner + fullText).length;\n }\n\n applyProgrammaticInput(next, caret);\n expertCardClickedRef.current = true;\n setShowQuickPrompts(false);\n if (mentionRefs.length > 0) onMentionRefsChanged?.(mentionRefs);\n else onMentionRefsCleared?.();\n onExpertCardClicked?.();\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n el.setSelectionRange(caret, caret);\n }, 0);\n },\n [applyProgrammaticInput, agents, input, onExpertCardClicked, onMentionRefsChanged, onMentionRefsCleared, textareaRef],\n );\n\n const measureQuickActionsOverflow = useCallback(() => {\n const row = quickActionsRowRef.current;\n const container = quickActionsContainerRef.current;\n if (!row) {\n setQuickActionsOverflowing(false);\n return;\n }\n const actionButtons = Array.from(row.querySelectorAll<HTMLElement>('[data-quick-action-button=\"true\"]'));\n const gap = Number.parseFloat(window.getComputedStyle(row).columnGap || '0') || 0;\n const actionButtonsWidth = actionButtons.reduce((total, button) => total + button.getBoundingClientRect().width, 0);\n const singleLineWidth = actionButtonsWidth + Math.max(0, actionButtons.length - 1) * gap;\n const availableWidth = container?.clientWidth || row.clientWidth;\n setQuickActionsOverflowing(singleLineWidth > availableWidth + 1);\n }, []);\n\n useLayoutEffect(() => {\n measureQuickActionsOverflow();\n const row = quickActionsRowRef.current;\n const container = quickActionsContainerRef.current;\n if (!row || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => measureQuickActionsOverflow());\n observer.observe(row);\n if (container) observer.observe(container);\n return () => observer.disconnect();\n }, [measureQuickActionsOverflow, visibleQuickActions]);\n\n useEffect(() => {\n let frameId: number | null = null;\n const handleResize = () => {\n if (frameId !== null) cancelAnimationFrame(frameId);\n frameId = requestAnimationFrame(() => {\n frameId = null;\n measureQuickActionsOverflow();\n });\n };\n window.addEventListener('resize', handleResize);\n return () => {\n window.removeEventListener('resize', handleResize);\n if (frameId !== null) cancelAnimationFrame(frameId);\n };\n }, [measureQuickActionsOverflow]);\n\n useEffect(() => {\n if (!quickActionsOverflowing) setQuickActionsExpanded(false);\n }, [quickActionsOverflowing]);\n\n useEffect(() => {\n if (showQuickPrompts) setQuickActionsExpanded(false);\n }, [showQuickPrompts]);\n\n useEffect(() => {\n const matched = visibleQuickActions.find((action) => input.includes(getQuickActionToken(action.label))) ?? null;\n setSelectedQuickAction(matched);\n }, [input, visibleQuickActions]);\n\n useEffect(() => {\n if (selectedQuickAction) {\n if (selectedQuickAction.expertCards && selectedQuickAction.expertCards.length > 0) {\n setShowQuickPrompts(!expertCardClickedRef.current);\n if (pendingQuickPromptExpand) setPendingQuickPromptExpand(false);\n return;\n }\n const hasMatchedPrompt = selectedQuickAction.prompts.some((prompt) => input.includes(prompt));\n setShowQuickPrompts(!hasMatchedPrompt);\n if (pendingQuickPromptExpand) setPendingQuickPromptExpand(false);\n return;\n }\n\n if (!pendingQuickPromptExpand) setShowQuickPrompts(false);\n }, [input, pendingQuickPromptExpand, selectedQuickAction]);\n\n const onExternalQuickActionInsert = useCallback(() => {\n setPendingQuickPromptExpand(false);\n setShowQuickPrompts(true);\n expertCardClickedRef.current = false;\n }, []);\n\n const resetQuickActions = useCallback(() => {\n setSelectedQuickAction(null);\n setPendingQuickPromptExpand(false);\n setShowQuickPrompts(false);\n setQuickActionsExpanded(false);\n expertCardClickedRef.current = false;\n onMentionRefsCleared?.();\n }, [onMentionRefsCleared]);\n\n const quickActionOptions = useMemo(\n () =>\n QUICK_ACTIONS.map((action) => ({\n label: action.label,\n icon: action.icon,\n token: getQuickActionToken(action.label),\n })),\n [],\n );\n\n return {\n selectedQuickAction,\n showQuickPrompts,\n quickActionsExpanded,\n quickActionsOverflowing,\n visibleQuickActions,\n quickActionOptions,\n quickActionsContainerRef,\n quickActionsRowRef,\n setQuickActionsExpanded,\n handleQuickAction,\n handleQuickPrompt,\n handleExpertCardClick,\n onExternalQuickActionInsert,\n resetQuickActions,\n queueAwareDisabled,\n };\n}\n","import { useCallback } from 'react';\nimport type { Dispatch, MutableRefObject, SetStateAction } from 'react';\nimport type { AgentOption } from '../chat-input-options';\nimport type { SelectedTemplateSummary } from '../types';\nimport { normalizeMentionsForSend, normalizeSkillsForSend } from '../utils/helpers';\nimport { normalizeQuickActionsForSend } from './useQuickActions';\nimport type { DeliveryMode } from '@/stores/chat-types';\nimport type { MentionRef, SendMessageOptions, WhisperOptions } from '@/hooks/useSendMessage';\n\n\ninterface UseChatInputSendFlowParams {\n input: string;\n images: File[];\n mentionOptions: AgentOption[];\n queueAwareDisabled: boolean;\n sendTemporarilyDisabled: boolean;\n guidedModeEnabled: boolean;\n selectedQuickActionLabel?: string;\n hasPptSkillInInput: boolean;\n selectedTemplate: SelectedTemplateSummary | null;\n queueSendDisabled: boolean;\n mentionRefs: MentionRef[];\n onSend: (\n content: string,\n images?: File[],\n whisper?: WhisperOptions,\n deliveryMode?: DeliveryMode,\n sendOptions?: SendMessageOptions,\n ) => void;\n addHistoryEntry: (text: string) => void;\n setInput: (next: string | ((prev: string) => string)) => void;\n setImages: Dispatch<SetStateAction<File[]>>;\n setShowMentions: Dispatch<SetStateAction<boolean>>;\n setShowSkillMenu: Dispatch<SetStateAction<boolean>>;\n setShowWorkspaceMenu: Dispatch<SetStateAction<boolean>>;\n setSelectedTemplate: Dispatch<SetStateAction<SelectedTemplateSummary | null>>;\n setQueueExpanded: Dispatch<SetStateAction<boolean>>;\n clearMentionRefs: () => void;\n setGhostSuggestion: Dispatch<SetStateAction<string | null>>;\n ghostRef: MutableRefObject<string | null>;\n resetQuickActions: () => void;\n resolveQueueSendOptions?: () => SendMessageOptions | undefined;\n}\n\nexport function useChatInputSendFlow({\n input,\n images,\n mentionOptions,\n queueAwareDisabled,\n sendTemporarilyDisabled,\n guidedModeEnabled,\n selectedQuickActionLabel,\n hasPptSkillInInput,\n selectedTemplate,\n queueSendDisabled,\n mentionRefs,\n onSend,\n addHistoryEntry,\n setInput,\n setImages,\n setShowMentions,\n setShowSkillMenu,\n setShowWorkspaceMenu,\n setSelectedTemplate,\n setQueueExpanded,\n clearMentionRefs,\n setGhostSuggestion,\n ghostRef,\n resetQuickActions,\n resolveQueueSendOptions,\n}: UseChatInputSendFlowParams) {\n const doSend = useCallback(\n (deliveryMode?: DeliveryMode): boolean => {\n if (sendTemporarilyDisabled) return false;\n const trimmed = input.trim();\n const payload = normalizeMentionsForSend(\n normalizeSkillsForSend(normalizeQuickActionsForSend(trimmed)),\n mentionOptions,\n );\n if (payload && !queueAwareDisabled) {\n // Preserve raw user-typed tokens (e.g. [[skill:xxx]]) in history so\n // Tab/ArrowRight completion can restore highlighted rich tokens.\n addHistoryEntry(trimmed);\n const sendOptions: SendMessageOptions = {\n ...(guidedModeEnabled ? { interactiveAsk: true } : {}),\n ...((selectedQuickActionLabel === '幻灯片' || hasPptSkillInInput) && selectedTemplate\n ? { pptTemplateId: selectedTemplate.id }\n : {}),\n ...(mentionRefs.length > 0 ? { mentionRefs } : {}),\n ...(deliveryMode === 'queue' ? resolveQueueSendOptions?.() : {}),\n };\n onSend(\n payload,\n images.length > 0 ? images : undefined,\n undefined,\n deliveryMode,\n Object.keys(sendOptions).length > 0 ? sendOptions : undefined,\n );\n setInput('');\n ghostRef.current = null;\n setGhostSuggestion(null);\n setImages([]);\n setShowMentions(false);\n setShowSkillMenu(false);\n setShowWorkspaceMenu(false);\n setSelectedTemplate(null);\n clearMentionRefs();\n resetQuickActions();\n return true;\n }\n return false;\n },\n [\n addHistoryEntry,\n mentionOptions,\n ghostRef,\n guidedModeEnabled,\n hasPptSkillInInput,\n mentionRefs,\n images,\n input,\n onSend,\n queueAwareDisabled,\n resetQuickActions,\n selectedQuickActionLabel,\n selectedTemplate,\n sendTemporarilyDisabled,\n setGhostSuggestion,\n setImages,\n setInput,\n setSelectedTemplate,\n setShowMentions,\n setShowSkillMenu,\n setShowWorkspaceMenu,\n clearMentionRefs,\n resolveQueueSendOptions,\n ],\n );\n\n const handleSend = useCallback((): boolean => doSend(undefined), [doSend]);\n\n const handleQueueSend = useCallback((): boolean => {\n if (queueSendDisabled) return false;\n setQueueExpanded(true);\n return doSend('queue');\n }, [doSend, queueSendDisabled, setQueueExpanded]);\n\n return {\n handleSend,\n handleQueueSend,\n };\n}\n\n","import { useCallback, useEffect } from 'react';\nimport type { Dispatch, RefObject, SetStateAction } from 'react';\nimport type { SelectedTemplateSummary } from '../types';\n\ninterface PickerTemplate {\n id: string;\n name: string;\n}\n\ninterface UseChatInputTemplateFlowParams {\n showStyleTemplatePopover: boolean;\n styleTemplatePopoverRef: RefObject<HTMLDivElement>;\n styleTemplateBtnRef: RefObject<HTMLButtonElement>;\n setShowStyleTemplatePopover: Dispatch<SetStateAction<boolean>>;\n selectedQuickActionLabel?: string;\n setSelectedTemplate: Dispatch<SetStateAction<SelectedTemplateSummary | null>>;\n}\n\nexport function useChatInputTemplateFlow({\n showStyleTemplatePopover,\n styleTemplatePopoverRef,\n styleTemplateBtnRef,\n setShowStyleTemplatePopover,\n selectedQuickActionLabel,\n setSelectedTemplate,\n}: UseChatInputTemplateFlowParams) {\n useEffect(() => {\n if (!showStyleTemplatePopover) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n if (!target.isConnected) return;\n if (\n styleTemplatePopoverRef.current &&\n !styleTemplatePopoverRef.current.contains(target) &&\n !styleTemplateBtnRef.current?.contains(target)\n ) {\n setShowStyleTemplatePopover(false);\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [setShowStyleTemplatePopover, showStyleTemplatePopover, styleTemplateBtnRef, styleTemplatePopoverRef]);\n\n useEffect(() => {\n if (selectedQuickActionLabel === '幻灯片') return;\n setShowStyleTemplatePopover(false);\n setSelectedTemplate(null);\n }, [selectedQuickActionLabel, setSelectedTemplate, setShowStyleTemplatePopover]);\n\n const onTemplateSelectChange = useCallback(\n (template: PickerTemplate | null) => {\n setSelectedTemplate(template ? { id: template.id, name: template.name } : null);\n if (template) setShowStyleTemplatePopover(false);\n },\n [setSelectedTemplate, setShowStyleTemplatePopover],\n );\n\n const onTemplatePopoverClose = useCallback(() => {\n setShowStyleTemplatePopover(false);\n }, [setShowStyleTemplatePopover]);\n\n return {\n onTemplateSelectChange,\n onTemplatePopoverClose,\n };\n}\n\n","import { useCallback } from 'react';\n\ninterface UseCloseMenusCoordinatorParams {\n closeMenusBase: () => void;\n clearSearchFilters: () => void;\n setWorkspaceFilter: (value: string) => void;\n}\n\nexport function useCloseMenusCoordinator({\n closeMenusBase,\n clearSearchFilters,\n setWorkspaceFilter,\n}: UseCloseMenusCoordinatorParams) {\n const closeMenus = useCallback(() => {\n closeMenusBase();\n clearSearchFilters();\n setWorkspaceFilter('');\n }, [clearSearchFilters, closeMenusBase, setWorkspaceFilter]);\n\n return { closeMenus };\n}\n\n","import { useLayoutEffect } from 'react';\n\nexport function useDraftSync(params: {\n threadId?: string;\n input: string;\n threadDrafts: Map<string, string>;\n}) {\n const { threadId, input, threadDrafts } = params;\n\n useLayoutEffect(() => {\n if (!threadId) return;\n if (input) threadDrafts.set(threadId, input);\n else threadDrafts.delete(threadId);\n }, [input, threadDrafts, threadId]);\n}\n\n","import { useEffect, type MutableRefObject, type Dispatch, type SetStateAction } from 'react';\n\ninterface UseHistorySuggestionSyncParams {\n input: string;\n findHistoryMatch: (text: string) => string | null;\n ghostRef: MutableRefObject<string | null>;\n setGhostSuggestion: Dispatch<SetStateAction<string | null>>;\n}\n\nexport function useHistorySuggestionSync({\n input,\n findHistoryMatch,\n ghostRef,\n setGhostSuggestion,\n}: UseHistorySuggestionSyncParams) {\n useEffect(() => {\n const match = input.trim() ? findHistoryMatch(input) : null;\n ghostRef.current = match;\n setGhostSuggestion(match);\n }, [findHistoryMatch, ghostRef, input, setGhostSuggestion]);\n}\n\n","import { useEffect, useLayoutEffect } from 'react';\n\ninterface UseMentionMenuPositioningParams {\n showMentions: boolean;\n input: string;\n mentionFilter: string;\n updateMentionMenuPosition: () => void;\n}\n\nexport function useMentionMenuPositioning({\n showMentions,\n input,\n mentionFilter,\n updateMentionMenuPosition,\n}: UseMentionMenuPositioningParams) {\n useLayoutEffect(() => {\n updateMentionMenuPosition();\n }, [input, mentionFilter, showMentions, updateMentionMenuPosition]);\n\n useEffect(() => {\n if (!showMentions) return;\n const onWindowChange = () => updateMentionMenuPosition();\n window.addEventListener('resize', onWindowChange);\n window.addEventListener('scroll', onWindowChange, true);\n return () => {\n window.removeEventListener('resize', onWindowChange);\n window.removeEventListener('scroll', onWindowChange, true);\n };\n }, [showMentions, updateMentionMenuPosition]);\n}\n\n","import type { CSSProperties, Dispatch, MutableRefObject, RefObject, SetStateAction } from 'react';\nimport { useCallback } from 'react';\nimport type { AgentOption } from '../chat-input-options';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\nimport type { MentionRef } from '@/hooks/useSendMessage';\nimport { getSkillToken } from '../utils/helpers';\n\ninterface UseMentionSkillActionsParams {\n showMentions: boolean;\n mentionStart: number;\n mentionEnd: number;\n input: string;\n textareaRef: RefObject<RichTextareaHandle>;\n menuRef: RefObject<HTMLDivElement>;\n skillInsertAnchorRef: MutableRefObject<{ start: number; end: number } | null>;\n setInput: (next: string | ((prev: string) => string)) => void;\n setShowMentions: Dispatch<SetStateAction<boolean>>;\n setShowSkillMenu: Dispatch<SetStateAction<boolean>>;\n setMentionStart: Dispatch<SetStateAction<number>>;\n setMentionEnd: Dispatch<SetStateAction<number>>;\n setMentionMenuStyle: Dispatch<SetStateAction<CSSProperties>>;\n clearMentionFilter: () => void;\n clearSkillFilter: () => void;\n onMentionRefInserted?: (ref: MentionRef) => void;\n}\n\nexport function useMentionSkillActions({\n showMentions,\n mentionStart,\n mentionEnd,\n input,\n textareaRef,\n menuRef,\n skillInsertAnchorRef,\n setInput,\n setShowMentions,\n setShowSkillMenu,\n setMentionStart,\n setMentionEnd,\n setMentionMenuStyle,\n clearMentionFilter,\n clearSkillFilter,\n onMentionRefInserted,\n}: UseMentionSkillActionsParams) {\n const updateMentionMenuPosition = useCallback(() => {\n if (!showMentions) return;\n const ta = textareaRef.current;\n const root = ta?.getElement();\n if (!root) return;\n const offset = mentionStart >= 0 ? mentionStart : (ta?.getSelectionStart() ?? 0);\n const anchorRect = ta?.getClientRectAtOffset(offset) ?? root.getBoundingClientRect();\n const menuWidth = 200;\n const menuHeight = Math.max(120, menuRef.current?.offsetHeight ?? 220);\n const viewportPadding = 8;\n const desiredLeft = anchorRect.left;\n const desiredTop = anchorRect.top - menuHeight - 8;\n const maxLeft = window.innerWidth - menuWidth - viewportPadding;\n const maxTop = window.innerHeight - menuHeight - viewportPadding;\n const left = Math.min(Math.max(desiredLeft, viewportPadding), Math.max(viewportPadding, maxLeft));\n const top = Math.min(Math.max(desiredTop, viewportPadding), Math.max(viewportPadding, maxTop));\n setMentionMenuStyle({ left, top });\n }, [mentionStart, menuRef, setMentionMenuStyle, showMentions, textareaRef]);\n\n const insertMention = useCallback(\n (option: AgentOption) => {\n const cursor = textareaRef.current?.getSelectionStart() ?? input.length;\n const start = mentionStart >= 0 ? mentionStart : cursor;\n const end = mentionEnd >= start ? mentionEnd : cursor;\n const before = input.slice(0, start);\n const after = input.slice(end);\n const mentionText = option.insert.trim();\n const leftJoiner = before.length > 0 && !/\\s$/.test(before) ? ' ' : '';\n const rightJoiner = ' ';\n const normalizedAfter = after.replace(/^\\s+/, '');\n const nextValue = `${before}${leftJoiner}${mentionText}${rightJoiner}${normalizedAfter}`;\n const cursorPos = (before + leftJoiner + mentionText + rightJoiner).length;\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.applyProgrammaticChange(nextValue, cursorPos, cursorPos);\n } else {\n setInput(nextValue);\n }\n if (mentionText) {\n onMentionRefInserted?.({ catId: option.id, mention: mentionText });\n }\n setShowMentions(false);\n setMentionStart(-1);\n setMentionEnd(-1);\n clearMentionFilter();\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n const cursorPos = (before + leftJoiner + mentionText + rightJoiner).length;\n el.focus();\n el.setSelectionRange(cursorPos, cursorPos);\n }, 0);\n },\n [\n clearMentionFilter,\n input,\n mentionEnd,\n mentionStart,\n setInput,\n setMentionEnd,\n onMentionRefInserted,\n setMentionStart,\n setShowMentions,\n textareaRef,\n ],\n );\n\n const insertSkill = useCallback(\n (skillName: string) => {\n const ta = textareaRef.current;\n const anchor = skillInsertAnchorRef.current;\n const start = anchor?.start ?? ta?.getSelectionStart() ?? input.length;\n const end = anchor?.end ?? ta?.getSelectionEnd() ?? input.length;\n const before = input.slice(0, start);\n const after = input.slice(end);\n const leftJoiner = before.endsWith(' ') ? '' : ' ';\n const rightJoiner = ' ';\n const normalizedAfter = after.replace(/^\\s+/, '');\n const triggerText = getSkillToken(skillName);\n const next = `${before}${leftJoiner}${triggerText}${rightJoiner}${normalizedAfter}`;\n const cursorPos = (before + leftJoiner + triggerText + rightJoiner).length;\n const textarea = textareaRef.current;\n if (textarea) {\n textarea.applyProgrammaticChange(next, cursorPos, cursorPos);\n } else {\n setInput(next);\n }\n setShowSkillMenu(false);\n clearSkillFilter();\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n const cursorPos = (before + leftJoiner + triggerText + rightJoiner).length;\n skillInsertAnchorRef.current = { start: cursorPos, end: cursorPos };\n el.focus();\n el.setSelectionRange(cursorPos, cursorPos);\n }, 0);\n },\n [clearSkillFilter, input, setInput, setShowSkillMenu, skillInsertAnchorRef, textareaRef],\n );\n\n return {\n updateMentionMenuPosition,\n insertMention,\n insertSkill,\n };\n}\n","import { useEffect, useMemo } from 'react';\nimport type { Dispatch, MutableRefObject, SetStateAction } from 'react';\nimport type { WorkspaceMenuItem } from '../types';\n\ntype ActiveMenuKind = 'mention' | 'skill' | 'workspace' | null;\n\ninterface UsePanelMenuCoordinatorParams {\n showMentions: boolean;\n showSkillMenu: boolean;\n showWorkspaceMenu: boolean;\n filteredAgentOptionsLength: number;\n filteredSkillOptionsLength: number;\n workspaceMenuItems: WorkspaceMenuItem[];\n selectedIdx: number;\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n skillOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n workspaceOptionRefs: MutableRefObject<Array<HTMLButtonElement | null>>;\n folderSelectionEnabled: boolean;\n setShowWorkspaceMenu: Dispatch<SetStateAction<boolean>>;\n}\n\nexport function usePanelMenuCoordinator({\n showMentions,\n showSkillMenu,\n showWorkspaceMenu,\n filteredAgentOptionsLength,\n filteredSkillOptionsLength,\n workspaceMenuItems,\n selectedIdx,\n setSelectedIdx,\n skillOptionRefs,\n workspaceOptionRefs,\n folderSelectionEnabled,\n setShowWorkspaceMenu,\n}: UsePanelMenuCoordinatorParams) {\n const activeMenu = useMemo<ActiveMenuKind>(\n () => (showMentions ? 'mention' : showSkillMenu ? 'skill' : showWorkspaceMenu ? 'workspace' : null),\n [showMentions, showSkillMenu, showWorkspaceMenu],\n );\n\n const activeOptionsCount = useMemo(() => {\n if (activeMenu === 'mention') return filteredAgentOptionsLength;\n if (activeMenu === 'skill') return filteredSkillOptionsLength;\n return workspaceMenuItems.length;\n }, [activeMenu, filteredAgentOptionsLength, filteredSkillOptionsLength, workspaceMenuItems.length]);\n\n useEffect(() => {\n if (!showMentions) return;\n setSelectedIdx((i) => Math.min(i, Math.max(0, filteredAgentOptionsLength - 1)));\n }, [filteredAgentOptionsLength, setSelectedIdx, showMentions]);\n\n useEffect(() => {\n if (!showSkillMenu) return;\n setSelectedIdx((i) => Math.min(i, Math.max(0, filteredSkillOptionsLength - 1)));\n }, [filteredSkillOptionsLength, setSelectedIdx, showSkillMenu]);\n\n useEffect(() => {\n if (!folderSelectionEnabled && showWorkspaceMenu) setShowWorkspaceMenu(false);\n }, [folderSelectionEnabled, setShowWorkspaceMenu, showWorkspaceMenu]);\n\n useEffect(() => {\n if (!showWorkspaceMenu) return;\n setSelectedIdx((i) => Math.min(i, Math.max(0, workspaceMenuItems.length - 1)));\n }, [setSelectedIdx, showWorkspaceMenu, workspaceMenuItems.length]);\n\n useEffect(() => {\n if (!showSkillMenu) return;\n const el = skillOptionRefs.current[selectedIdx];\n if (!el) return;\n el.scrollIntoView({ block: 'nearest' });\n }, [selectedIdx, showSkillMenu, skillOptionRefs]);\n\n useEffect(() => {\n if (!showWorkspaceMenu) return;\n const el = workspaceOptionRefs.current[selectedIdx];\n if (!el) return;\n el.scrollIntoView({ block: 'nearest' });\n }, [selectedIdx, showWorkspaceMenu, workspaceOptionRefs]);\n\n return {\n activeMenu,\n activeOptionsCount,\n };\n}\n\n","import { useCallback, useMemo, useState } from 'react';\nimport type { Dispatch, SetStateAction } from 'react';\nimport type { AgentOption } from '../chat-input-options';\nimport type { SkillOption } from '@/utils/skill-options-cache';\n\ninterface UsePanelSearchFillParams {\n agentOptions: AgentOption[];\n skillOptions: SkillOption[];\n setSelectedIdx: Dispatch<SetStateAction<number>>;\n}\n\nexport function usePanelSearchFill({ agentOptions, skillOptions, setSelectedIdx }: UsePanelSearchFillParams) {\n const [mentionFilter, setMentionFilterState] = useState('');\n const [skillFilter, setSkillFilterState] = useState('');\n\n const filteredAgentOptions = useMemo(() => {\n if (!mentionFilter) return agentOptions;\n const lower = mentionFilter.toLowerCase();\n return agentOptions.filter(\n (opt) =>\n opt.label.toLowerCase().includes(lower) ||\n opt.insert.toLowerCase().includes(lower) ||\n opt.id.toLowerCase().includes(lower),\n );\n }, [agentOptions, mentionFilter]);\n\n const filteredSkillOptions = useMemo(() => {\n const lower = skillFilter.trim().toLowerCase();\n if (!lower) return skillOptions;\n return skillOptions.filter((item) => item.name.toLowerCase().includes(lower));\n }, [skillFilter, skillOptions]);\n\n const setMentionFilterValue = useCallback((value: string) => {\n setMentionFilterState(value);\n }, []);\n\n const onMentionSearchChange = useCallback(\n (value: string) => {\n setMentionFilterState(value);\n setSelectedIdx(0);\n },\n [setSelectedIdx],\n );\n\n const onSkillSearchChange = useCallback(\n (value: string) => {\n setSkillFilterState(value);\n setSelectedIdx(0);\n },\n [setSelectedIdx],\n );\n\n const clearMentionFilter = useCallback(() => setMentionFilterState(''), []);\n const clearSkillFilter = useCallback(() => setSkillFilterState(''), []);\n const clearSearchFilters = useCallback(() => {\n setMentionFilterState('');\n setSkillFilterState('');\n }, []);\n\n return {\n mentionFilter,\n skillFilter,\n filteredAgentOptions,\n filteredSkillOptions,\n setMentionFilterValue,\n onMentionSearchChange,\n onSkillSearchChange,\n clearMentionFilter,\n clearSkillFilter,\n clearSearchFilters,\n };\n}\n","import { type MutableRefObject, type RefObject, useEffect } from 'react';\nimport type { MentionRef } from '@/hooks/useSendMessage';\nimport type { InspirationPendingChatInsert } from '@/stores/chat-types';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\n\ninterface PendingChatInsert {\n threadId: string;\n text: string;\n replaceTrailingMentionTrigger?: boolean;\n suppressMentionMenu?: boolean;\n mentionRefs?: MentionRef[];\n /** 为 true 时直接覆盖输入框内容,不追加 */\n replaceAll?: boolean;\n inspirationData?: InspirationPendingChatInsert;\n}\n\ninterface UsePendingChatInsertSyncParams {\n pendingChatInsert: PendingChatInsert | null;\n setPendingChatInsert: (value: PendingChatInsert | null) => void;\n threadId?: string;\n quickActionTokenPrefix: string;\n consumedRef: MutableRefObject<PendingChatInsert | null>;\n textareaRef: RefObject<RichTextareaHandle>;\n setInput: (next: string | ((prev: string) => string)) => void;\n onExternalQuickActionInsert: () => void;\n onExternalMentionInsert: (filter: string, start: number) => void;\n onMentionRefsChanged?: (refs: MentionRef[]) => void;\n onMentionRefsCleared?: () => void;\n}\n\nexport function usePendingChatInsertSync({\n pendingChatInsert,\n setPendingChatInsert,\n threadId,\n quickActionTokenPrefix,\n consumedRef,\n textareaRef,\n setInput,\n onExternalQuickActionInsert,\n onExternalMentionInsert,\n onMentionRefsChanged,\n onMentionRefsCleared,\n}: UsePendingChatInsertSyncParams) {\n const stripTrailingMentionTrigger = (value: string): string => {\n const match = value.match(/^(.*?)(\\s*)@\\s*$/);\n if (!match) return value;\n return `${match[1] ?? ''}${match[2] ?? ''}`;\n };\n\n useEffect(() => {\n if (!pendingChatInsert) return;\n if (pendingChatInsert.threadId !== threadId) return;\n if (consumedRef.current === pendingChatInsert) return;\n consumedRef.current = pendingChatInsert;\n\n const isQuickActionInsert =\n pendingChatInsert.text.includes(quickActionTokenPrefix) && !pendingChatInsert.inspirationData;\n const shouldReplaceTrailingMentionTrigger = pendingChatInsert.replaceTrailingMentionTrigger === true;\n const shouldReplaceAll = pendingChatInsert.replaceAll === true;\n const shouldKeepForInspirationTemplate = Boolean(pendingChatInsert.inspirationData?.prompt.includes('{{'));\n\n if (isQuickActionInsert) {\n setInput(pendingChatInsert.text);\n onMentionRefsCleared?.();\n onExternalQuickActionInsert();\n setPendingChatInsert(null);\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n el.setSelectionRange(pendingChatInsert.text.length, pendingChatInsert.text.length);\n }, 0);\n return;\n }\n\n const mentionMatch = pendingChatInsert.text.match(/^@(\\S+)/);\n const isMentionInsert = !!mentionMatch;\n\n if (isMentionInsert) {\n const filter = mentionMatch[1] ?? '';\n setInput((prev) => {\n const base = shouldReplaceTrailingMentionTrigger ? stripTrailingMentionTrigger(prev) : prev;\n const separator = base && !base.endsWith('\\n') ? '\\n' : '';\n return base + separator + pendingChatInsert.text;\n });\n if (pendingChatInsert.mentionRefs?.length) {\n onMentionRefsChanged?.(pendingChatInsert.mentionRefs);\n } else {\n onMentionRefsCleared?.();\n }\n setPendingChatInsert(null);\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n if (!pendingChatInsert.suppressMentionMenu) {\n onExternalMentionInsert(filter, 0);\n }\n }, 0);\n } else {\n if (shouldReplaceAll) {\n // 覆盖模式:直接替换输入框内容\n setInput(pendingChatInsert.text);\n } else {\n setInput((prev) => {\n const base = shouldReplaceTrailingMentionTrigger ? stripTrailingMentionTrigger(prev) : prev;\n const separator = base && !base.endsWith('\\n') ? '\\n' : '';\n return base + separator + pendingChatInsert.text;\n });\n }\n if (pendingChatInsert.mentionRefs?.length) {\n onMentionRefsChanged?.(pendingChatInsert.mentionRefs);\n } else {\n onMentionRefsCleared?.();\n }\n\n // Keep placeholder templates for useInspirationTemplate; plain inspiration inserts can be consumed here.\n if (!shouldKeepForInspirationTemplate) {\n setPendingChatInsert(null);\n }\n\n setTimeout(() => {\n const el = textareaRef.current;\n if (!el) return;\n el.focus();\n }, 0);\n }\n }, [\n consumedRef,\n onExternalQuickActionInsert,\n onExternalMentionInsert,\n onMentionRefsChanged,\n onMentionRefsCleared,\n pendingChatInsert,\n quickActionTokenPrefix,\n setInput,\n setPendingChatInsert,\n textareaRef,\n threadId,\n ]);\n}\n","import { useCallback, useEffect, useRef, useState, type Dispatch, type RefObject, type SetStateAction } from 'react';\nimport type { SendMessageOptions } from '@/hooks/useSendMessage';\nimport type { QueueEntry } from '@/stores/chat-types';\nimport type { RichTextareaHandle } from '../components/RichTextarea';\nimport { restoreSkillTokensFromSendText } from '../utils/helpers';\n\nconst queueEditDraftCache = new Map<string, { input: string; images: File[] }>();\nconst QUEUE_EDIT_DRAFT_DB = 'relay-claw-chat-input-cache';\nconst QUEUE_EDIT_DRAFT_DB_VERSION = 2;\nconst QUEUE_EDIT_DRAFT_STORE = 'queue-edit-drafts';\nconst QUEUE_EDIT_PENDING_STORE = 'queue-edit-pending';\nconst QUEUE_EDIT_PENDING_TTL_MS = 10 * 60 * 1000;\nconst QUEUE_EDIT_PENDING_MATCH_TIMEOUT_MS = 30 * 1000;\n\ninterface PersistedQueueEditDraftRecord {\n id: string;\n input: string;\n images: File[];\n updatedAt: number;\n}\n\ninterface PersistedQueueEditPendingRecord {\n id: string;\n threadId: string;\n draftId: string;\n input: string;\n images: File[];\n updatedAt: number;\n}\n\ninterface QueueEditReinsertContext {\n previousEntryId: string | null;\n nextEntryId: string | null;\n}\n\ninterface UseQueueEditDraftManagerParams {\n activeQueueThreadId?: string;\n queuedEntries: QueueEntry[];\n input: string;\n images: File[];\n skillNames: string[];\n setInput: (next: string | ((prev: string) => string)) => void;\n setImages: Dispatch<SetStateAction<File[]>>;\n setQueueExpanded: Dispatch<SetStateAction<boolean>>;\n textareaRef: RefObject<RichTextareaHandle>;\n handleQueueExtractForEdit: (entryId: string) => Promise<QueueEntry | null>;\n handleQueueMoveToIndex: (entryId: string, targetIndex: number) => Promise<void>;\n handleQueueDelete: (entryId: string) => Promise<void>;\n handleQueueClear: () => Promise<void>;\n}\n\nfunction buildQueueEditDraftKey(threadId: string, entryId: string): string {\n return `${threadId}::${entryId}`;\n}\n\nfunction createClientDraftId(): string {\n if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();\n const randomHex = (length: number) =>\n Array.from({ length }, () => Math.floor(Math.random() * 16).toString(16)).join('');\n return [\n randomHex(8),\n randomHex(4),\n `4${randomHex(3)}`,\n `${['8', '9', 'a', 'b'][Math.floor(Math.random() * 4)]}${randomHex(3)}`,\n randomHex(12),\n ].join('-');\n}\n\nlet queueEditDraftDbPromise: Promise<IDBDatabase | null> | null = null;\n\nfunction openQueueEditDraftDb(): Promise<IDBDatabase | null> {\n if (typeof window === 'undefined' || !('indexedDB' in window)) return Promise.resolve(null);\n if (queueEditDraftDbPromise) return queueEditDraftDbPromise;\n queueEditDraftDbPromise = new Promise((resolve) => {\n try {\n const request = window.indexedDB.open(QUEUE_EDIT_DRAFT_DB, QUEUE_EDIT_DRAFT_DB_VERSION);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(QUEUE_EDIT_DRAFT_STORE)) {\n db.createObjectStore(QUEUE_EDIT_DRAFT_STORE, { keyPath: 'id' });\n }\n if (!db.objectStoreNames.contains(QUEUE_EDIT_PENDING_STORE)) {\n db.createObjectStore(QUEUE_EDIT_PENDING_STORE, { keyPath: 'id' });\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => resolve(null);\n request.onblocked = () => resolve(null);\n } catch {\n resolve(null);\n }\n });\n return queueEditDraftDbPromise;\n}\n\nasync function persistQueueEditDraft(threadId: string, entryId: string, draft: { input: string; images: File[] }) {\n const db = await openQueueEditDraftDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_DRAFT_STORE, 'readwrite');\n tx.objectStore(QUEUE_EDIT_DRAFT_STORE).put({\n id: buildQueueEditDraftKey(threadId, entryId),\n input: draft.input,\n images: draft.images,\n updatedAt: Date.now(),\n } satisfies PersistedQueueEditDraftRecord);\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\nasync function loadQueueEditDraft(threadId: string, entryId: string): Promise<{ input: string; images: File[] } | null> {\n const db = await openQueueEditDraftDb();\n if (!db) return null;\n return new Promise((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_DRAFT_STORE, 'readonly');\n const req = tx.objectStore(QUEUE_EDIT_DRAFT_STORE).get(buildQueueEditDraftKey(threadId, entryId));\n req.onsuccess = () => {\n const value = req.result as PersistedQueueEditDraftRecord | undefined;\n if (!value) {\n resolve(null);\n return;\n }\n resolve({\n input: value.input,\n images: Array.isArray(value.images) ? value.images : [],\n });\n };\n req.onerror = () => resolve(null);\n } catch {\n resolve(null);\n }\n });\n}\n\nasync function clearQueueEditDraft(threadId: string, entryId: string) {\n const db = await openQueueEditDraftDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_DRAFT_STORE, 'readwrite');\n tx.objectStore(QUEUE_EDIT_DRAFT_STORE).delete(buildQueueEditDraftKey(threadId, entryId));\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\nasync function persistPendingQueueEditDraft(record: PersistedQueueEditPendingRecord): Promise<void> {\n const db = await openQueueEditDraftDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_PENDING_STORE, 'readwrite');\n tx.objectStore(QUEUE_EDIT_PENDING_STORE).put(record);\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\nasync function loadPendingQueueEditDrafts(threadId: string): Promise<PersistedQueueEditPendingRecord[]> {\n const db = await openQueueEditDraftDb();\n if (!db) return [];\n return new Promise((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_PENDING_STORE, 'readonly');\n const req = tx.objectStore(QUEUE_EDIT_PENDING_STORE).getAll();\n req.onsuccess = () => {\n const all = (req.result as PersistedQueueEditPendingRecord[] | undefined) ?? [];\n const now = Date.now();\n resolve(\n all.filter(\n (item) =>\n item.threadId === threadId &&\n typeof item.draftId === 'string' &&\n item.draftId.length > 0 &&\n now - item.updatedAt <= QUEUE_EDIT_PENDING_TTL_MS,\n ),\n );\n };\n req.onerror = () => resolve([]);\n } catch {\n resolve([]);\n }\n });\n}\n\nasync function clearPendingQueueEditDraft(recordId: string): Promise<void> {\n const db = await openQueueEditDraftDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction(QUEUE_EDIT_PENDING_STORE, 'readwrite');\n tx.objectStore(QUEUE_EDIT_PENDING_STORE).delete(recordId);\n tx.oncomplete = () => resolve();\n tx.onerror = () => resolve();\n tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\nasync function clearPendingQueueEditDraftsByThread(threadId: string): Promise<void> {\n const db = await openQueueEditDraftDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const readTx = db.transaction(QUEUE_EDIT_PENDING_STORE, 'readonly');\n const readReq = readTx.objectStore(QUEUE_EDIT_PENDING_STORE).getAll();\n readReq.onsuccess = () => {\n const all = (readReq.result as PersistedQueueEditPendingRecord[] | undefined) ?? [];\n const targetIds = all.filter((item) => item.threadId === threadId).map((item) => item.id);\n if (targetIds.length === 0) {\n resolve();\n return;\n }\n const writeTx = db.transaction(QUEUE_EDIT_PENDING_STORE, 'readwrite');\n const store = writeTx.objectStore(QUEUE_EDIT_PENDING_STORE);\n for (const id of targetIds) store.delete(id);\n writeTx.oncomplete = () => resolve();\n writeTx.onerror = () => resolve();\n writeTx.onabort = () => resolve();\n };\n readReq.onerror = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\nexport function useQueueEditDraftManager({\n activeQueueThreadId,\n queuedEntries,\n input,\n images,\n skillNames,\n setInput,\n setImages,\n setQueueExpanded,\n textareaRef,\n handleQueueExtractForEdit,\n handleQueueMoveToIndex,\n handleQueueDelete,\n handleQueueClear,\n}: UseQueueEditDraftManagerParams) {\n const queueEditDraftRef = useRef<QueueEditReinsertContext | null>(null);\n const previousQueuedIdsRef = useRef<string[]>(queuedEntries.map((entry) => entry.id));\n const pendingDraftByIdRef = useRef(new Map<string, { input: string; images: File[] }>());\n const queueSendOptionsRef = useRef<SendMessageOptions | undefined>(undefined);\n const [pendingQueueReinsert, setPendingQueueReinsert] = useState<QueueEditReinsertContext | null>(null);\n\n useEffect(() => {\n if (!activeQueueThreadId || queuedEntries.length === 0) return;\n let cancelled = false;\n void (async () => {\n const now = Date.now();\n const pendingDrafts = await loadPendingQueueEditDrafts(activeQueueThreadId);\n if (cancelled) return;\n const pendingByDraftId = new Map(pendingDrafts.map((pending) => [pending.draftId, pending] as const));\n const matchedPendingIds = new Set<string>();\n for (const entry of queuedEntries) {\n if (!entry.clientDraftId) continue;\n if (queueEditDraftCache.has(entry.id)) continue;\n const runtimeDraft = pendingDraftByIdRef.current.get(entry.clientDraftId);\n const pending = pendingByDraftId.get(entry.clientDraftId);\n const draft = runtimeDraft ?? (pending ? { input: pending.input, images: pending.images } : null);\n if (!draft) continue;\n queueEditDraftCache.set(entry.id, draft);\n void persistQueueEditDraft(activeQueueThreadId, entry.id, draft);\n if (pending) {\n void clearPendingQueueEditDraft(pending.id);\n matchedPendingIds.add(pending.id);\n }\n pendingDraftByIdRef.current.delete(entry.clientDraftId);\n }\n for (const pending of pendingDrafts) {\n if (matchedPendingIds.has(pending.id)) continue;\n if (now - pending.updatedAt > QUEUE_EDIT_PENDING_MATCH_TIMEOUT_MS) {\n void clearPendingQueueEditDraft(pending.id);\n pendingDraftByIdRef.current.delete(pending.draftId);\n }\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [activeQueueThreadId, queuedEntries]);\n\n useEffect(() => {\n const previousIds = previousQueuedIdsRef.current;\n const currentIds = queuedEntries.map((entry) => entry.id);\n if (!pendingQueueReinsert) {\n previousQueuedIdsRef.current = currentIds;\n return;\n }\n const previousIdSet = new Set(previousIds);\n const addedEntries = queuedEntries.filter((entry) => !previousIdSet.has(entry.id));\n const newestAdded = addedEntries[addedEntries.length - 1];\n if (!newestAdded) {\n previousQueuedIdsRef.current = currentIds;\n return;\n }\n\n const previousIndex = pendingQueueReinsert.previousEntryId\n ? queuedEntries.findIndex((entry) => entry.id === pendingQueueReinsert.previousEntryId)\n : -1;\n const nextIndex = pendingQueueReinsert.nextEntryId\n ? queuedEntries.findIndex((entry) => entry.id === pendingQueueReinsert.nextEntryId)\n : -1;\n const defaultTailIndex = queuedEntries.length - 1;\n let targetIndex = defaultTailIndex;\n if (previousIndex >= 0 && nextIndex >= 0) targetIndex = previousIndex < nextIndex ? previousIndex + 1 : nextIndex;\n else if (previousIndex >= 0) targetIndex = previousIndex + 1;\n else if (nextIndex >= 0) targetIndex = nextIndex;\n\n void handleQueueMoveToIndex(newestAdded.id, targetIndex);\n setPendingQueueReinsert(null);\n previousQueuedIdsRef.current = currentIds;\n }, [handleQueueMoveToIndex, pendingQueueReinsert, queuedEntries]);\n\n const handleQueueEdit = useCallback(\n async (entryId: string) => {\n const entryIndex = queuedEntries.findIndex((entry) => entry.id === entryId);\n if (entryIndex < 0) return;\n const previousEntryId = queuedEntries[entryIndex - 1]?.id ?? null;\n const nextEntryId = queuedEntries[entryIndex + 1]?.id ?? null;\n const extracted = await handleQueueExtractForEdit(entryId);\n if (!extracted) return;\n queueEditDraftRef.current = { previousEntryId, nextEntryId };\n const memoryDraft = queueEditDraftCache.get(entryId) ?? null;\n const persistedDraft =\n !memoryDraft && activeQueueThreadId ? await loadQueueEditDraft(activeQueueThreadId, entryId) : null;\n const cachedDraft = memoryDraft ?? persistedDraft;\n queueEditDraftCache.delete(entryId);\n if (activeQueueThreadId) void clearQueueEditDraft(activeQueueThreadId, entryId);\n const restoredInput = cachedDraft?.input ?? restoreSkillTokensFromSendText(extracted.content, skillNames);\n setInput(restoredInput);\n setImages(cachedDraft?.images ?? []);\n setQueueExpanded(true);\n setTimeout(() => {\n const el = textareaRef.current?.getElement();\n if (!el) return;\n textareaRef.current?.focus();\n const caret = restoredInput.length;\n textareaRef.current?.setSelectionRange(caret, caret);\n }, 0);\n },\n [\n activeQueueThreadId,\n handleQueueExtractForEdit,\n queuedEntries,\n setImages,\n setInput,\n setQueueExpanded,\n skillNames,\n textareaRef,\n ],\n );\n\n const handleQueueSend = useCallback((handleQueueSendBase: () => boolean) => {\n const editContext = queueEditDraftRef.current;\n const draft = { input, images: [...images] };\n const draftId = createClientDraftId();\n const clearPendingDraft = () => {\n pendingDraftByIdRef.current.delete(draftId);\n void clearPendingQueueEditDraft(draftId);\n };\n pendingDraftByIdRef.current.set(draftId, draft);\n if (activeQueueThreadId) {\n void persistPendingQueueEditDraft({\n id: draftId,\n threadId: activeQueueThreadId,\n draftId,\n input: draft.input,\n images: draft.images,\n updatedAt: Date.now(),\n });\n }\n queueSendOptionsRef.current = {\n clientDraftId: draftId,\n onQueueResult: (result) => {\n if (!activeQueueThreadId) {\n clearPendingDraft();\n return;\n }\n if (result.status === 'queued' && result.entryId) {\n const runtimeDraft = pendingDraftByIdRef.current.get(draftId);\n if (runtimeDraft) {\n queueEditDraftCache.set(result.entryId, runtimeDraft);\n void persistQueueEditDraft(activeQueueThreadId, result.entryId, runtimeDraft);\n }\n clearPendingDraft();\n return;\n }\n clearPendingDraft();\n },\n };\n const didQueueSend = handleQueueSendBase();\n if (didQueueSend && editContext) {\n setPendingQueueReinsert(editContext);\n queueEditDraftRef.current = null;\n }\n if (!didQueueSend) {\n queueSendOptionsRef.current = undefined;\n clearPendingDraft();\n }\n }, [activeQueueThreadId, images, input]);\n\n const handleQueueDeleteSafe = useCallback(\n async (entryId: string) => {\n queueEditDraftCache.delete(entryId);\n pendingDraftByIdRef.current.clear();\n if (activeQueueThreadId) void clearQueueEditDraft(activeQueueThreadId, entryId);\n if (activeQueueThreadId) void clearPendingQueueEditDraftsByThread(activeQueueThreadId);\n await handleQueueDelete(entryId);\n },\n [activeQueueThreadId, handleQueueDelete],\n );\n\n const handleQueueClearSafe = useCallback(async () => {\n pendingDraftByIdRef.current.clear();\n for (const entry of queuedEntries) {\n queueEditDraftCache.delete(entry.id);\n if (activeQueueThreadId) void clearQueueEditDraft(activeQueueThreadId, entry.id);\n }\n if (activeQueueThreadId) void clearPendingQueueEditDraftsByThread(activeQueueThreadId);\n await handleQueueClear();\n }, [activeQueueThreadId, handleQueueClear, queuedEntries]);\n\n const resolveQueueSendOptions = useCallback(() => {\n const next = queueSendOptionsRef.current;\n queueSendOptionsRef.current = undefined;\n return next;\n }, []);\n\n const resetQueueEditState = useCallback(() => {\n queueEditDraftRef.current = null;\n setPendingQueueReinsert(null);\n }, []);\n\n return {\n handleQueueEdit,\n handleQueueSend,\n handleQueueDeleteSafe,\n handleQueueClearSafe,\n resolveQueueSendOptions,\n resetQueueEditState,\n };\n}\n\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useChatStore } from '@/stores/chatStore';\nimport { apiFetch } from '@/utils/api-client';\n\ninterface QueueMessageBlock {\n type: string;\n fileName?: string;\n}\n\ninterface QueueMessage {\n id: string;\n contentBlocks?: QueueMessageBlock[];\n}\n\ninterface ToastPayload {\n type: 'error' | 'success' | 'info';\n title: string;\n message: string;\n duration?: number;\n}\n\ninterface UseQueueManagerParams {\n threadId?: string;\n hasActiveInvocation?: boolean;\n addToast: (toast: ToastPayload) => void;\n}\n\nexport function useQueueManager({ threadId, hasActiveInvocation, addToast }: UseQueueManagerParams) {\n const setQueue = useChatStore((s) => s.setQueue);\n const currentThreadId = useChatStore((s) => s.currentThreadId);\n const activeQueueThreadId = threadId ?? currentThreadId;\n\n const queue = useChatStore(\n useCallback(\n (s) => {\n if (!activeQueueThreadId || activeQueueThreadId === s.currentThreadId) return s.queue;\n return s.threadStates[activeQueueThreadId]?.queue ?? [];\n },\n [activeQueueThreadId],\n ),\n );\n\n const queueMessages = useChatStore(\n useCallback(\n (s) => {\n if (!activeQueueThreadId || activeQueueThreadId === s.currentThreadId) return s.messages as QueueMessage[];\n return (s.threadStates[activeQueueThreadId]?.messages ?? []) as QueueMessage[];\n },\n [activeQueueThreadId],\n ),\n );\n\n const queuedEntries = useMemo(() => queue.filter((entry) => entry.status === 'queued'), [queue]);\n const queueAttachmentNamesByEntryId = useMemo(() => {\n const messageById = new Map(queueMessages.map((msg) => [msg.id, msg] as const));\n const result: Record<string, string[]> = {};\n for (const entry of queuedEntries) {\n if (entry.attachmentNames && entry.attachmentNames.length > 0) {\n result[entry.id] = [...entry.attachmentNames];\n continue;\n }\n const ids = [entry.messageId, ...entry.mergedMessageIds].filter(Boolean) as string[];\n if (ids.length === 0) continue;\n const names: string[] = [];\n for (const msgId of ids) {\n const msg = messageById.get(msgId);\n const fileNames =\n msg?.contentBlocks\n ?.filter((block) => block.type === 'file')\n .map((block) => block.fileName)\n .filter(Boolean) ?? [];\n names.push(...fileNames);\n }\n if (names.length > 0) result[entry.id] = names;\n }\n return result;\n }, [queueMessages, queuedEntries]);\n\n const queueCount = queuedEntries.length;\n const [queueExpanded, setQueueExpanded] = useState(false);\n const [queueBusy, setQueueBusy] = useState(false);\n const [queueHighlightedEntryId, setQueueHighlightedEntryId] = useState<string | null>(null);\n const queueHighlightTimerRef = useRef<number | null>(null);\n const queueListRef = useRef<HTMLDivElement>(null);\n const previousQueueCountRef = useRef(queueCount);\n const previousQueueExpandedRef = useRef(queueExpanded);\n\n useEffect(() => {\n if (hasActiveInvocation && queueCount > 0) setQueueExpanded(true);\n }, [hasActiveInvocation, queueCount]);\n\n useEffect(() => {\n const queueCountIncreased = queueCount > previousQueueCountRef.current;\n const queueJustExpanded = queueExpanded && !previousQueueExpandedRef.current;\n if (queueExpanded && (queueCountIncreased || queueJustExpanded)) {\n const listEl = queueListRef.current;\n if (listEl) {\n requestAnimationFrame(() => {\n listEl.scrollTop = listEl.scrollHeight;\n });\n }\n }\n previousQueueCountRef.current = queueCount;\n previousQueueExpandedRef.current = queueExpanded;\n }, [queueCount, queueExpanded]);\n\n useEffect(\n () => () => {\n if (queueHighlightTimerRef.current !== null) window.clearTimeout(queueHighlightTimerRef.current);\n },\n [],\n );\n\n const highlightQueueEntry = useCallback((entryId: string) => {\n setQueueHighlightedEntryId(entryId);\n if (queueHighlightTimerRef.current !== null) window.clearTimeout(queueHighlightTimerRef.current);\n queueHighlightTimerRef.current = window.setTimeout(() => {\n setQueueHighlightedEntryId(null);\n queueHighlightTimerRef.current = null;\n }, 900);\n }, []);\n\n const persistQueuePromote = useCallback(\n async (entryId: string) => {\n if (!activeQueueThreadId) throw new Error('队列线程不存在');\n const res = await apiFetch(`/api/threads/${activeQueueThreadId}/queue/${entryId}/steer`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ mode: 'promote' }),\n });\n if (!res.ok) {\n const payload = await res.json().catch(() => null);\n throw new Error(payload?.error ?? '置顶失败');\n }\n },\n [activeQueueThreadId],\n );\n\n const applyLocalQueueReorder = useCallback(\n (sourceIndex: number, targetIndex: number) => {\n if (sourceIndex === targetIndex) return;\n const nextQueued = [...queuedEntries];\n const [moved] = nextQueued.splice(sourceIndex, 1);\n if (!moved) return;\n nextQueued.splice(targetIndex, 0, moved);\n const queuedOrder = new Map(nextQueued.map((entry, idx) => [entry.id, idx]));\n const nextQueue = [...queue].sort((a, b) => {\n const aOrder = queuedOrder.get(a.id);\n const bOrder = queuedOrder.get(b.id);\n if (aOrder == null && bOrder == null) return 0;\n if (aOrder == null) return 1;\n if (bOrder == null) return -1;\n return aOrder - bOrder;\n });\n setQueue(activeQueueThreadId, nextQueue);\n },\n [activeQueueThreadId, queue, queuedEntries, setQueue],\n );\n\n const handleQueueDelete = useCallback(\n async (entryId: string) => {\n if (!activeQueueThreadId) return;\n const prevQueue = queue;\n setQueue(activeQueueThreadId, prevQueue.filter((entry) => entry.id !== entryId));\n try {\n const res = await apiFetch(`/api/threads/${activeQueueThreadId}/queue/${entryId}`, { method: 'DELETE' });\n if (!res.ok) throw new Error('删除失败');\n } catch {\n setQueue(activeQueueThreadId, prevQueue);\n addToast({ type: 'error', title: '删除失败', message: '队列消息删除失败,请重试', duration: 2400 });\n }\n },\n [activeQueueThreadId, addToast, queue, setQueue],\n );\n\n const handleQueueExtractForEdit = useCallback(\n async (entryId: string) => {\n if (!activeQueueThreadId) return null;\n const queuedEntry = queuedEntries.find((entry) => entry.id === entryId);\n if (!queuedEntry || queuedEntry.status !== 'queued') return null;\n const prevQueue = queue;\n setQueue(activeQueueThreadId, prevQueue.filter((entry) => entry.id !== entryId));\n try {\n const res = await apiFetch(`/api/threads/${activeQueueThreadId}/queue/${entryId}`, { method: 'DELETE' });\n if (!res.ok) throw new Error('删除失败');\n return queuedEntry;\n } catch {\n setQueue(activeQueueThreadId, prevQueue);\n addToast({ type: 'error', title: '编辑失败', message: '队列消息提取失败,请重试', duration: 2400 });\n return null;\n }\n },\n [activeQueueThreadId, addToast, queue, queuedEntries, setQueue],\n );\n\n const handleQueueClear = useCallback(async () => {\n if (!activeQueueThreadId) return;\n if (queuedEntries.length === 0) return;\n const prevQueue = queue;\n setQueue(activeQueueThreadId, queue.filter((entry) => entry.status !== 'queued'));\n try {\n const res = await apiFetch(`/api/threads/${activeQueueThreadId}/queue`, { method: 'DELETE' });\n if (!res.ok) throw new Error('清空失败');\n } catch {\n setQueue(activeQueueThreadId, prevQueue);\n addToast({ type: 'error', title: '清空失败', message: '队列清空失败,请重试', duration: 2400 });\n }\n }, [activeQueueThreadId, addToast, queue, queuedEntries.length, setQueue]);\n\n const handleQueuePinToTop = useCallback(\n async (entryId: string) => {\n if (!activeQueueThreadId) return;\n const sourceIndex = queuedEntries.findIndex((entry) => entry.id === entryId);\n if (sourceIndex <= 0) return;\n const prevQueue = queue;\n applyLocalQueueReorder(sourceIndex, 0);\n setQueueBusy(true);\n try {\n await persistQueuePromote(entryId);\n highlightQueueEntry(entryId);\n } catch (error) {\n setQueue(activeQueueThreadId, prevQueue);\n addToast({\n type: 'error',\n title: '置顶失败',\n message: error instanceof Error ? error.message : '队列置顶失败,请重试',\n duration: 2400,\n });\n } finally {\n setQueueBusy(false);\n }\n },\n [activeQueueThreadId, addToast, applyLocalQueueReorder, highlightQueueEntry, persistQueuePromote, queue, queuedEntries, setQueue],\n );\n\n const handleQueueMoveToIndex = useCallback(\n async (entryId: string, targetIndex: number) => {\n if (!activeQueueThreadId) return;\n const sourceIndex = queuedEntries.findIndex((entry) => entry.id === entryId);\n if (sourceIndex < 0) return;\n const maxIndex = Math.max(0, queuedEntries.length - 1);\n const clampedTarget = Math.max(0, Math.min(targetIndex, maxIndex));\n if (sourceIndex === clampedTarget) return;\n const prevQueue = queue;\n applyLocalQueueReorder(sourceIndex, clampedTarget);\n setQueueBusy(true);\n try {\n const direction = clampedTarget < sourceIndex ? 'up' : 'down';\n const steps = Math.abs(clampedTarget - sourceIndex);\n for (let i = 0; i < steps; i += 1) {\n const res = await apiFetch(`/api/threads/${activeQueueThreadId}/queue/${entryId}/move`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ direction }),\n });\n if (!res.ok) {\n const payload = await res.json().catch(() => null);\n throw new Error(payload?.error ?? '重排失败');\n }\n }\n } catch (error) {\n setQueue(activeQueueThreadId, prevQueue);\n addToast({\n type: 'error',\n title: '重排失败',\n message: error instanceof Error ? error.message : '队列重排失败,请重试',\n duration: 2400,\n });\n } finally {\n setQueueBusy(false);\n }\n },\n [activeQueueThreadId, addToast, applyLocalQueueReorder, queue, queuedEntries, setQueue],\n );\n\n return {\n activeQueueThreadId,\n queue,\n queuedEntries,\n queueAttachmentNamesByEntryId,\n queueCount,\n queueExpanded,\n setQueueExpanded,\n queueBusy,\n queueHighlightedEntryId,\n queueListRef,\n handleQueueDelete,\n handleQueueExtractForEdit,\n handleQueueClear,\n handleQueuePinToTop,\n handleQueueMoveToIndex,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n fetchSkillOptionsWithCache,\n SKILL_OPTIONS_UPDATED_EVENT,\n seedSkillOptionsCache,\n type SkillOption,\n} from '@/utils/skill-options-cache';\n\nexport function useSkillOptionsSource() {\n const [skillOptions, setSkillOptions] = useState<SkillOption[]>([]);\n const [skillOptionsLoading, setSkillOptionsLoading] = useState(false);\n const requestSeqRef = useRef(0);\n const mountedRef = useRef(true);\n\n const loadSkillOptions = useCallback((force = false) => {\n const requestId = ++requestSeqRef.current;\n setSkillOptionsLoading(true);\n void fetchSkillOptionsWithCache(force ? { force: true } : undefined)\n .then((options) => {\n if (!mountedRef.current || requestSeqRef.current !== requestId) return;\n setSkillOptions(options);\n seedSkillOptionsCache(options);\n })\n .finally(() => {\n if (!mountedRef.current || requestSeqRef.current !== requestId) return;\n setSkillOptionsLoading(false);\n });\n }, []);\n\n useEffect(() => {\n mountedRef.current = true;\n loadSkillOptions();\n return () => {\n mountedRef.current = false;\n requestSeqRef.current += 1;\n };\n }, [loadSkillOptions]);\n\n useEffect(() => {\n const onUpdated = () => loadSkillOptions(true);\n window.addEventListener(SKILL_OPTIONS_UPDATED_EVENT, onUpdated);\n return () => window.removeEventListener(SKILL_OPTIONS_UPDATED_EVENT, onUpdated);\n }, [loadSkillOptions]);\n\n return {\n skillOptions,\n skillOptionsLoading,\n loadSkillOptions,\n };\n}\n\n","import { useCallback, useMemo, useState } from 'react';\nimport type { SelectedTemplateSummary } from '../types';\n\n\nexport function useTemplateMode(input: string) {\n const [guidedModeEnabled, setGuidedModeEnabled] = useState(false);\n const [selectedTemplate, setSelectedTemplate] = useState<SelectedTemplateSummary | null>(null);\n\n const hasPptSkillInInput = useMemo(() => /\\[\\[skill:[^\\]]*ppt[^\\]]*\\]\\]/i.test(input), [input]);\n\n const onToggleGuidedMode = useCallback(() => {\n setGuidedModeEnabled((prev) => !prev);\n }, []);\n\n const onClearSelectedTemplate = useCallback(() => {\n setSelectedTemplate(null);\n }, []);\n\n return {\n guidedModeEnabled,\n setGuidedModeEnabled,\n hasPptSkillInInput,\n selectedTemplate,\n setSelectedTemplate,\n onToggleGuidedMode,\n onClearSelectedTemplate,\n };\n}\n\n","import { useCallback, useMemo, useState } from 'react';\nimport type { WorkspaceMenuItem, WorkspaceOptionItem } from '../types';\n\ninterface UseWorkspaceMenuParams {\n workspaceOptions: WorkspaceOptionItem[];\n onSelectEmptyWorkspace?: () => void;\n onSelectExistingWorkspace?: (path: string) => void;\n onOpenFolderPicker?: () => void;\n}\n\nexport function useWorkspaceMenu({\n workspaceOptions,\n onSelectEmptyWorkspace,\n onSelectExistingWorkspace,\n onOpenFolderPicker,\n}: UseWorkspaceMenuParams) {\n const [workspaceFilter, setWorkspaceFilter] = useState('');\n\n const filteredWorkspaceOptions = useMemo(() => {\n const lower = workspaceFilter.trim().toLowerCase();\n if (!lower) return workspaceOptions;\n return workspaceOptions.filter((item) => {\n const title = item.title?.trim() ?? '';\n return (\n item.name.toLowerCase().includes(lower) ||\n item.path.toLowerCase().includes(lower) ||\n title.toLowerCase().includes(lower)\n );\n });\n }, [workspaceFilter, workspaceOptions]);\n\n const workspaceMenuItems = useMemo<WorkspaceMenuItem[]>(\n () => [\n { kind: 'empty' },\n { kind: 'open' },\n ...filteredWorkspaceOptions.map((option): WorkspaceMenuItem => ({ kind: 'workspace', option })),\n ],\n [filteredWorkspaceOptions],\n );\n\n const selectWorkspaceMenuItem = useCallback(\n (item: WorkspaceMenuItem) => {\n if (item.kind === 'empty') {\n onSelectEmptyWorkspace?.();\n } else if (item.kind === 'open') {\n onOpenFolderPicker?.();\n } else {\n onSelectExistingWorkspace?.(item.option.path);\n }\n },\n [onOpenFolderPicker, onSelectEmptyWorkspace, onSelectExistingWorkspace],\n );\n\n return {\n workspaceFilter,\n setWorkspaceFilter,\n workspaceMenuItems,\n selectWorkspaceMenuItem,\n };\n}\n\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { type CSSProperties, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { useAgentData } from '@/hooks/useAgentData';\nimport { useInspirationTemplate } from '@/hooks/useInspirationTemplate';\nimport { usePathCompletion } from '@/hooks/usePathCompletion';\nimport { useChatStore } from '@/stores/chatStore';\nimport { useInputHistoryStore } from '@/stores/inputHistoryStore';\nimport { usePlaceholderStore } from '@/stores/placeholderStore';\nimport { useToastStore } from '@/stores/toastStore';\nimport { useInvitedExpertsForThread } from '@/components/experts-panel/hooks/useInvitedExpertsForThread';\nimport { refreshThreadExpertMentionData } from '@/lib/mention-highlight';\nimport type { MentionRef } from '@/hooks/useSendMessage';\nimport { ChatInputLayout } from './components/ChatInputLayout';\nimport { buildExpertOption, buildMentionOptions } from './chat-input-options';\nimport { deriveImageLifecycleStatus, isImageLifecycleBlockingSend } from './chat-input-upload-state';\nimport { type RichTextareaHandle } from './components/RichTextarea';\nimport { useAttachmentManager } from './hooks/useAttachmentManager';\nimport { useChatInputInputFlow } from './hooks/useChatInputInputFlow';\nimport { useChatInputKeyboard } from './hooks/useChatInputKeyboard';\nimport { useChatInputMenus } from './hooks/useChatInputMenus';\nimport { useChatInputSendFlow } from './hooks/useChatInputSendFlow';\nimport { useChatInputTemplateFlow } from './hooks/useChatInputTemplateFlow';\nimport { useCloseMenusCoordinator } from './hooks/useCloseMenusCoordinator';\nimport { useDraftSync } from './hooks/useDraftSync';\nimport { useHistorySuggestionSync } from './hooks/useHistorySuggestionSync';\nimport { useMentionMenuPositioning } from './hooks/useMentionMenuPositioning';\nimport { useMentionSkillActions } from './hooks/useMentionSkillActions';\nimport { usePanelMenuCoordinator } from './hooks/usePanelMenuCoordinator';\nimport { usePanelSearchFill } from './hooks/usePanelSearchFill';\nimport { usePendingChatInsertSync } from './hooks/usePendingChatInsertSync';\nimport { useQueueEditDraftManager } from './hooks/useQueueEditDraftManager';\nimport { useQueueManager } from './hooks/useQueueManager';\nimport { useQuickActions } from './hooks/useQuickActions';\nimport { useSkillOptionsSource } from './hooks/useSkillOptionsSource';\nimport { useTemplateMode } from './hooks/useTemplateMode';\nimport { useWorkspaceMenu } from './hooks/useWorkspaceMenu';\nimport type { ChatInputProps, WorkspaceMenuItem } from './types';\nimport {\n MAX_PENDING_QUEUE,\n QUICK_ACTION_TOKEN_PREFIX,\n TEXTAREA_MAX_HEIGHT,\n TEXTAREA_MIN_HEIGHT,\n} from './utils/constants';\nimport {\n clampInputLength,\n escapeRegExp,\n normalizeMentionsForSend,\n normalizeQuickActionsForSend,\n normalizeSkillsForSend,\n deriveTargetAgentIds,\n reconcileMentionRefs,\n} from './utils/helpers';\n\n/** Module-level draft storage — survives component unmount/remount across thread switches */\nexport const threadDrafts = new Map<string, string>();\n\nexport function ChatInput({\n threadId,\n onSend,\n onStop,\n disabled,\n hasActiveInvocation,\n uploadStatus = 'idle',\n uploadError = null,\n folderSelectionEnabled = false,\n selectedFolderName = null,\n selectedFolderTitle = null,\n activeWorkspacePath = null,\n workspaceOptions = [],\n onSelectEmptyWorkspace,\n onSelectExistingWorkspace,\n onOpenFolderPicker,\n dragDropScopeRef,\n}: ChatInputProps) {\n const navigate = useNavigate();\n const { agents } = useAgentData();\n const { invitedExperts } = useInvitedExpertsForThread({ threadId: threadId ?? null });\n const [mentionDataVersion, setMentionDataVersion] = useState(0);\n useEffect(() => {\n refreshThreadExpertMentionData(invitedExperts);\n setMentionDataVersion((version) => version + 1);\n return () => {\n refreshThreadExpertMentionData([]);\n };\n }, [invitedExperts]);\n const expertOptions = useMemo(() => invitedExperts.map((expert) => buildExpertOption(expert)), [invitedExperts]);\n const mentionOptions = useMemo(() => buildMentionOptions(agents, expertOptions), [agents, expertOptions]);\n const replaceThreadTargetAgents = useChatStore((s) => s.replaceThreadTargetAgents);\n\n const [input, setInputState] = useState(() => (threadId ? (threadDrafts.get(threadId) ?? '') : ''));\n const [mentionRefs, setMentionRefs] = useState<MentionRef[]>([]);\n const setInput = useCallback((next: string | ((prev: string) => string)) => {\n if (typeof next === 'function') {\n setInputState((prev) => clampInputLength((next as (prev: string) => string)(prev)));\n return;\n }\n setInputState(clampInputLength(next));\n }, []);\n const appendMentionRef = useCallback((ref: MentionRef) => {\n setMentionRefs((prev) => [...prev, ref]);\n }, []);\n const replaceMentionRefs = useCallback((refs: MentionRef[]) => {\n setMentionRefs(refs);\n }, []);\n const clearMentionRefs = useCallback(() => {\n setMentionRefs([]);\n }, []);\n const [mentionStart, setMentionStart] = useState(-1);\n const [mentionEnd, setMentionEnd] = useState(-1);\n const [mentionMenuStyle, setMentionMenuStyle] = useState<CSSProperties>({});\n const isPreparingImages = false;\n const [isComposing, setIsComposing] = useState(false);\n const [ghostSuggestion, setGhostSuggestion] = useState<string | null>(null);\n const [dragOverlayHost, setDragOverlayHost] = useState<HTMLElement | null>(null);\n const [resolvedDragDropScope, setResolvedDragDropScope] = useState<HTMLElement | null>(null);\n const ghostRef = useRef<string | null>(null);\n const [showHistorySearch, setShowHistorySearch] = useState(false);\n const {\n guidedModeEnabled,\n setGuidedModeEnabled,\n hasPptSkillInInput,\n selectedTemplate,\n setSelectedTemplate,\n onToggleGuidedMode,\n onClearSelectedTemplate,\n } = useTemplateMode(input);\n const {\n showMentions,\n setShowMentions,\n showSkillMenu,\n setShowSkillMenu,\n showWorkspaceMenu,\n setShowWorkspaceMenu,\n showStyleTemplatePopover,\n setShowStyleTemplatePopover,\n selectedIdx,\n setSelectedIdx,\n closeMenus: closeMenusBase,\n toggleSkillMenu,\n toggleWorkspaceMenu,\n toggleStyleTemplatePopover,\n } = useChatInputMenus();\n const { skillOptions: skillOptionsData, skillOptionsLoading, loadSkillOptions } = useSkillOptionsSource();\n const {\n mentionFilter,\n skillFilter,\n filteredAgentOptions,\n filteredSkillOptions,\n setMentionFilterValue,\n onMentionSearchChange,\n onSkillSearchChange,\n clearMentionFilter,\n clearSkillFilter,\n clearSearchFilters,\n } = usePanelSearchFill({ agentOptions: mentionOptions, skillOptions: skillOptionsData, setSelectedIdx });\n const textareaRef = useRef<RichTextareaHandle>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n const skillBtnRef = useRef<HTMLButtonElement>(null);\n const styleTemplateBtnRef = useRef<HTMLButtonElement>(null);\n const folderBtnRef = useRef<HTMLButtonElement>(null);\n const skillOptionRefs = useRef<Array<HTMLButtonElement | null>>([]);\n const workspaceOptionRefs = useRef<Array<HTMLButtonElement | null>>([]);\n const workspaceSearchInputRef = useRef<HTMLInputElement>(null);\n const skillInsertAnchorRef = useRef<{ start: number; end: number } | null>(null);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const styleTemplatePopoverRef = useRef<HTMLDivElement>(null);\n const imageLifecycleStatus = deriveImageLifecycleStatus(isPreparingImages, uploadStatus);\n const sendTemporarilyDisabled = isImageLifecycleBlockingSend(imageLifecycleStatus);\n // When a thread is actively running, we still allow queue-send paths.\n // Some parents may pass disabled=true during processing; do not let that\n // block queue-send (button / Enter / quick-scene follow-up sends).\n const queueAwareDisabled = Boolean(disabled && !hasActiveInvocation);\n const addToast = useToastStore((s) => s.addToast);\n const {\n images,\n setImages,\n isDraggingFiles,\n handleFileSelect,\n handlePaste,\n handleRemoveImage,\n handleDragEnter,\n handleDragOver,\n handleDragLeave,\n handleDrop,\n } = useAttachmentManager(addToast as any, resolvedDragDropScope);\n const folderButtonLabel = selectedFolderName?.trim() || '选择文件夹';\n const isFolderButtonDisabled = disabled || !folderSelectionEnabled;\n const shouldShowFolderTooltip = Boolean(selectedFolderTitle?.trim());\n const {\n activeQueueThreadId,\n queuedEntries,\n queueAttachmentNamesByEntryId,\n queueCount,\n queueExpanded,\n setQueueExpanded,\n queueBusy,\n queueHighlightedEntryId,\n queueListRef,\n handleQueueDelete,\n handleQueueExtractForEdit,\n handleQueueClear,\n handleQueuePinToTop,\n handleQueueMoveToIndex,\n } = useQueueManager({ threadId, hasActiveInvocation, addToast: addToast as any });\n const queueSendDisabled = Boolean(hasActiveInvocation && queueCount >= MAX_PENDING_QUEUE);\n\n const pendingChatInsert = useChatStore((s) => s.pendingChatInsert);\n const setPendingChatInsert = useChatStore((s) => s.setPendingChatInsert);\n const [inspirationDraftWorkspacePath, setInspirationDraftWorkspacePath] = useState<string | null>(() => {\n const insert = pendingChatInsert;\n if (!insert || insert.threadId !== threadId) return null;\n return insert.inspirationData?.workspacePath ?? null;\n });\n const consumedPendingChatInsertRef = useRef<{\n threadId: string;\n text: string;\n replaceTrailingMentionTrigger?: boolean;\n suppressMentionMenu?: boolean;\n mentionRefs?: MentionRef[];\n } | null>(null);\n const prevThreadIdRef = useRef<string | undefined>(threadId);\n\n useEffect(() => {\n const insert = pendingChatInsert;\n if (!insert || insert.threadId !== threadId) return;\n const workspacePath = insert.inspirationData?.workspacePath?.trim();\n if (workspacePath) setInspirationDraftWorkspacePath(workspacePath);\n }, [pendingChatInsert, threadId]);\n\n const effectivePlaceholderWorkspacePath =\n activeWorkspacePath?.trim() || inspirationDraftWorkspacePath?.trim() || null;\n\n const handleTranscript = useCallback((text: string) => {\n setInput((prev) => {\n const separator = prev && !prev.endsWith(' ') ? ' ' : '';\n return prev + separator + text;\n });\n }, []);\n\n const applyProgrammaticInput = useCallback((next: string, caret: number) => {\n const el = textareaRef.current;\n if (el) {\n el.applyProgrammaticChange(next, caret, caret);\n return;\n }\n setInput(next);\n }, []);\n\n const {\n selectedQuickAction,\n showQuickPrompts,\n quickActionsExpanded,\n quickActionsOverflowing,\n visibleQuickActions,\n quickActionOptions,\n quickActionsContainerRef,\n quickActionsRowRef,\n setQuickActionsExpanded,\n handleQuickAction,\n handleQuickPrompt,\n handleExpertCardClick,\n onExternalQuickActionInsert,\n resetQuickActions,\n } = useQuickActions({\n input,\n agents,\n queueAwareDisabled,\n textareaRef,\n applyProgrammaticInput,\n onMentionRefsChanged: replaceMentionRefs,\n onMentionRefsCleared: clearMentionRefs,\n onQuickActionSelected: () => {\n setQueueExpanded(false);\n setGuidedModeEnabled(false);\n },\n });\n\n const { workspaceFilter, setWorkspaceFilter, workspaceMenuItems, selectWorkspaceMenuItem } = useWorkspaceMenu({\n workspaceOptions,\n onSelectEmptyWorkspace,\n onSelectExistingWorkspace,\n onOpenFolderPicker,\n });\n\n const { activeMenu, activeOptionsCount } = usePanelMenuCoordinator({\n showMentions,\n showSkillMenu,\n showWorkspaceMenu,\n filteredAgentOptionsLength: filteredAgentOptions.length,\n filteredSkillOptionsLength: filteredSkillOptions.length,\n workspaceMenuItems,\n selectedIdx,\n setSelectedIdx,\n skillOptionRefs,\n workspaceOptionRefs,\n folderSelectionEnabled,\n setShowWorkspaceMenu,\n });\n\n const addHistoryEntry = useInputHistoryStore((s) => s.addEntry);\n const findHistoryMatch = useInputHistoryStore((s) => s.findMatch);\n\n // F080-P2: path completion\n const pathCompletion = usePathCompletion(input);\n const skillNames = useMemo(() => skillOptionsData.map((option) => option.name), [skillOptionsData]);\n\n const {\n handleQueueEdit,\n handleQueueSend: handleQueueSendWithDraft,\n handleQueueDeleteSafe,\n handleQueueClearSafe,\n resolveQueueSendOptions,\n resetQueueEditState,\n } = useQueueEditDraftManager({\n activeQueueThreadId,\n queuedEntries,\n input,\n images,\n skillNames,\n setInput,\n setImages,\n setQueueExpanded,\n textareaRef,\n handleQueueExtractForEdit,\n handleQueueMoveToIndex,\n handleQueueDelete,\n handleQueueClear,\n });\n\n const {\n isTemplate,\n parsed,\n activePlaceholderId,\n handlePlaceholderFocus,\n handlePlaceholderBlur,\n handlePlaceholderDelete,\n handlePlaceholderTabNext,\n buildSendContent,\n resetTemplate,\n } = useInspirationTemplate({\n input,\n setInput,\n textareaRef,\n onSend: undefined,\n });\n\n const { handleSend: handleSendBase, handleQueueSend: handleQueueSendBase } = useChatInputSendFlow({\n input,\n images,\n mentionOptions,\n queueAwareDisabled,\n sendTemporarilyDisabled,\n guidedModeEnabled,\n selectedQuickActionLabel: selectedQuickAction?.label,\n hasPptSkillInInput,\n selectedTemplate,\n queueSendDisabled,\n mentionRefs,\n onSend,\n addHistoryEntry,\n setInput,\n setImages,\n setShowMentions,\n setShowSkillMenu,\n setShowWorkspaceMenu,\n setSelectedTemplate,\n setQueueExpanded,\n clearMentionRefs,\n setGhostSuggestion,\n ghostRef,\n resetQuickActions,\n resolveQueueSendOptions,\n });\n const handleQueueSend = useCallback(\n () => handleQueueSendWithDraft(handleQueueSendBase),\n [handleQueueSendBase, handleQueueSendWithDraft],\n );\n\n useEffect(() => {\n setMentionRefs((prev) => reconcileMentionRefs(input, prev));\n }, [input, mentionRefs]);\n\n const handleSend = useCallback(() => {\n if (isTemplate && parsed) {\n const { text, files } = buildSendContent();\n const placeholderWorkspacePath =\n effectivePlaceholderWorkspacePath || usePlaceholderStore.getState().workspacePath?.trim() || null;\n const payload = normalizeMentionsForSend(\n normalizeSkillsForSend(normalizeQuickActionsForSend(text.trim())),\n mentionOptions,\n )\n .replace(/[^\\S\\r\\n]{2,}/g, ' ')\n .trim();\n if (payload) {\n onSend(\n payload,\n files.length > 0 ? files : undefined,\n undefined,\n undefined,\n placeholderWorkspacePath ? { workspacePathForNewThread: placeholderWorkspacePath } : undefined,\n );\n resetTemplate();\n usePlaceholderStore.getState().clearAll();\n setInput('');\n setPendingChatInsert(null);\n setInspirationDraftWorkspacePath(null);\n return true;\n }\n return false;\n }\n const didSend = handleSendBase();\n if (didSend) {\n resetQueueEditState();\n }\n return didSend;\n }, [\n isTemplate,\n parsed,\n mentionOptions,\n buildSendContent,\n onSend,\n handleSendBase,\n resetQueueEditState,\n resetTemplate,\n setPendingChatInsert,\n effectivePlaceholderWorkspacePath,\n ]);\n\n const { closeMenus } = useCloseMenusCoordinator({\n closeMenusBase,\n clearSearchFilters,\n setWorkspaceFilter,\n });\n\n const handleWorkspaceMenuSelect = useCallback(\n (item: WorkspaceMenuItem) => {\n selectWorkspaceMenuItem(item);\n closeMenus();\n },\n [closeMenus, selectWorkspaceMenuItem],\n );\n\n const { updateMentionMenuPosition, insertMention, insertSkill } = useMentionSkillActions({\n showMentions,\n mentionStart,\n mentionEnd,\n input,\n textareaRef,\n menuRef,\n skillInsertAnchorRef,\n setInput,\n setShowMentions,\n setShowSkillMenu,\n setMentionStart,\n setMentionEnd,\n setMentionMenuStyle,\n clearMentionFilter,\n clearSkillFilter,\n onMentionRefInserted: appendMentionRef,\n });\n\n const { handleChange } = useChatInputInputFlow({\n setInput,\n setShowMentions,\n setShowSkillMenu,\n setMentionStart,\n setMentionEnd,\n setMentionFilterValue,\n clearMentionFilter,\n clearSkillFilter,\n closeMenus,\n setSelectedIdx,\n skillInsertAnchorRef,\n });\n\n useEffect(() => {\n if (!threadId) return;\n const typedMentionIds = deriveTargetAgentIds(input, mentionRefs, mentionOptions);\n replaceThreadTargetAgents(threadId, typedMentionIds);\n }, [input, mentionOptions, mentionRefs, replaceThreadTargetAgents, threadId]);\n\n const handleHistorySelect = useCallback(\n (text: string) => {\n setInput(text);\n clearMentionRefs();\n setShowHistorySearch(false);\n ghostRef.current = null;\n setGhostSuggestion(null);\n closeMenus();\n clearMentionFilter();\n setTimeout(() => textareaRef.current?.focus(), 0);\n },\n [clearMentionRefs, closeMenus],\n );\n const { handleKeyDown } = useChatInputKeyboard({\n input,\n hasActiveInvocation,\n activeMenu,\n activeOptionsCount,\n selectedIdx,\n setSelectedIdx,\n filteredAgentOptions,\n filteredSkillOptions,\n workspaceMenuItems,\n textareaRef,\n setInput,\n closeMenus,\n clearMentionFilter,\n clearSkillFilter,\n setMentionStart,\n setMentionEnd,\n insertMention,\n insertSkill,\n handleWorkspaceMenuSelect,\n handleSend,\n handleQueueSend,\n setGhostSuggestion,\n ghostRef,\n setShowHistorySearch,\n pathCompletion,\n });\n\n const resizeTextarea = useCallback(() => {\n const ta = textareaRef.current?.getElement();\n if (!ta) return;\n const prevScrollTop = ta.scrollTop;\n const prevClientHeight = ta.clientHeight;\n const prevScrollHeight = ta.scrollHeight;\n const wasNearBottom = prevScrollTop + prevClientHeight >= prevScrollHeight - 2;\n ta.style.height = 'auto';\n const contentHeight = ta.scrollHeight;\n const nextHeight = Math.max(TEXTAREA_MIN_HEIGHT, Math.min(contentHeight, TEXTAREA_MAX_HEIGHT));\n const nextOverflowY = contentHeight > TEXTAREA_MAX_HEIGHT ? 'auto' : 'hidden';\n const nextHeightCss = `${nextHeight}px`;\n if (ta.style.height !== nextHeightCss) ta.style.height = nextHeightCss;\n if (ta.style.overflowY !== nextOverflowY) ta.style.overflowY = nextOverflowY;\n if (nextOverflowY === 'auto') {\n if (wasNearBottom) ta.scrollTop = ta.scrollHeight;\n else ta.scrollTop = prevScrollTop;\n } else {\n ta.scrollTop = 0;\n }\n }, []);\n\n useLayoutEffect(() => {\n resizeTextarea();\n }, [input, resizeTextarea]);\n\n useMentionMenuPositioning({\n showMentions,\n input,\n mentionFilter,\n updateMentionMenuPosition,\n });\n\n const handleSkillClick = useCallback(() => {\n const ta = textareaRef.current;\n const start = ta?.getSelectionStart() ?? input.length;\n const end = ta?.getSelectionEnd() ?? input.length;\n skillInsertAnchorRef.current = { start, end };\n toggleSkillMenu(() => loadSkillOptions(true));\n setTimeout(() => textareaRef.current?.focus(), 0);\n }, [input, loadSkillOptions, toggleSkillMenu]);\n\n const handleWorkspaceClick = useCallback(() => {\n toggleWorkspaceMenu();\n }, [toggleWorkspaceMenu]);\n\n const handleStyleTemplateClick = useCallback(() => {\n toggleStyleTemplatePopover();\n }, [toggleStyleTemplatePopover]);\n\n const { onTemplateSelectChange, onTemplatePopoverClose } = useChatInputTemplateFlow({\n showStyleTemplatePopover,\n styleTemplatePopoverRef,\n styleTemplateBtnRef,\n setShowStyleTemplatePopover,\n selectedQuickActionLabel: selectedQuickAction?.label,\n setSelectedTemplate,\n });\n\n usePendingChatInsertSync({\n pendingChatInsert,\n setPendingChatInsert,\n threadId,\n quickActionTokenPrefix: QUICK_ACTION_TOKEN_PREFIX,\n consumedRef: consumedPendingChatInsertRef,\n textareaRef,\n setInput,\n onExternalQuickActionInsert,\n onExternalMentionInsert: (filter, start) => {\n setShowMentions(true);\n setMentionStart(start);\n setMentionEnd(start + filter.length + 1);\n setMentionFilterValue(filter);\n setSelectedIdx(0);\n },\n onMentionRefsChanged: replaceMentionRefs,\n onMentionRefsCleared: clearMentionRefs,\n });\n\n useDraftSync({ threadId, input, threadDrafts });\n\n useLayoutEffect(() => {\n if (prevThreadIdRef.current !== threadId) {\n clearMentionRefs();\n prevThreadIdRef.current = threadId;\n }\n }, [clearMentionRefs, threadId]);\n\n useHistorySuggestionSync({\n input,\n findHistoryMatch,\n ghostRef,\n setGhostSuggestion,\n });\n\n useEffect(() => {\n if (!activeMenu) return;\n const handler = (e: MouseEvent) => {\n const target = e.target as Node;\n // React 18 may flush state synchronously during event bubbling,\n // detaching the original target (e.g. layer 1 unmounts when drilling\n // into layer 2). A detached target is not a genuine outside click.\n if (!target.isConnected) return;\n const activeTrigger =\n activeMenu === 'skill' ? skillBtnRef.current : activeMenu === 'workspace' ? folderBtnRef.current : null;\n if (menuRef.current && !menuRef.current.contains(target) && !activeTrigger?.contains(target)) {\n closeMenus();\n }\n };\n document.addEventListener('mousedown', handler);\n return () => document.removeEventListener('mousedown', handler);\n }, [activeMenu, closeMenus]);\n\n useEffect(() => {\n const explicitScope = dragDropScopeRef?.current ?? null;\n if (explicitScope) {\n setResolvedDragDropScope(explicitScope);\n setDragOverlayHost(explicitScope);\n return;\n }\n const fallbackScope =\n typeof document !== 'undefined'\n ? (document.querySelector('[data-chat-drop-scope=\"true\"]') as HTMLElement | null)\n : null;\n setResolvedDragDropScope(fallbackScope);\n setDragOverlayHost(fallbackScope);\n }, [dragDropScopeRef, threadId]);\n\n useEffect(() => {\n if (threadId === '__new__') {\n usePlaceholderStore.getState().clearAll();\n }\n }, [threadId]);\n\n useEffect(() => {\n usePlaceholderStore.getState().setWorkspacePath(effectivePlaceholderWorkspacePath);\n }, [effectivePlaceholderWorkspacePath]);\n\n return (\n <ChatInputLayout\n hasActiveInvocation={hasActiveInvocation}\n activeMenu={activeMenu}\n pathCompletion={pathCompletion}\n setInput={setInput}\n textareaRef={textareaRef}\n mentionDataVersion={mentionDataVersion}\n filteredAgentOptions={filteredAgentOptions}\n showMentions={showMentions}\n mentionFilter={mentionFilter}\n onMentionSearchChange={onMentionSearchChange}\n closeMenus={closeMenus}\n setMentionStart={setMentionStart}\n setMentionEnd={setMentionEnd}\n clearMentionFilter={clearMentionFilter}\n selectedIdx={selectedIdx}\n setSelectedIdx={setSelectedIdx}\n insertMention={insertMention}\n menuRef={menuRef}\n mentionMenuStyle={mentionMenuStyle}\n imageLifecycleStatus={imageLifecycleStatus}\n uploadError={uploadError}\n fileInputRef={fileInputRef}\n handleFileSelect={handleFileSelect}\n showQuickPrompts={showQuickPrompts}\n quickActionsExpanded={quickActionsExpanded}\n quickActionsOverflowing={quickActionsOverflowing}\n visibleQuickActions={visibleQuickActions}\n selectedQuickAction={selectedQuickAction}\n queueAwareDisabled={queueAwareDisabled}\n quickActionsContainerRef={quickActionsContainerRef}\n quickActionsRowRef={quickActionsRowRef}\n handleQuickAction={handleQuickAction}\n handleQuickPrompt={handleQuickPrompt}\n handleExpertCardClick={handleExpertCardClick}\n setQuickActionsExpanded={setQuickActionsExpanded}\n queueCount={queueCount}\n queuedEntries={queuedEntries}\n queueAttachmentNamesByEntryId={queueAttachmentNamesByEntryId}\n queueExpanded={queueExpanded}\n queueBusy={queueBusy}\n queueHighlightedEntryId={queueHighlightedEntryId}\n queueListRef={queueListRef}\n setQueueExpanded={setQueueExpanded}\n handleQueueClear={handleQueueClearSafe}\n handleQueuePinToTop={handleQueuePinToTop}\n handleQueueDelete={handleQueueDeleteSafe}\n handleQueueEdit={handleQueueEdit}\n showStyleTemplatePopover={showStyleTemplatePopover}\n styleTemplatePopoverRef={styleTemplatePopoverRef}\n selectedTemplate={selectedTemplate}\n onTemplateSelectChange={onTemplateSelectChange}\n onTemplatePopoverClose={onTemplatePopoverClose}\n images={images}\n handleRemoveImage={handleRemoveImage}\n isDraggingFiles={isDraggingFiles}\n input={input}\n handleChange={handleChange}\n setIsComposing={setIsComposing}\n resizeTextarea={resizeTextarea}\n handleKeyDown={handleKeyDown}\n handlePaste={handlePaste}\n handleDragEnter={handleDragEnter}\n handleDragOver={handleDragOver}\n handleDragLeave={handleDragLeave}\n handleDrop={handleDrop}\n skillOptionsData={skillOptionsData}\n quickActionOptions={quickActionOptions}\n ghostSuggestion={ghostSuggestion}\n isComposing={isComposing}\n skillInsertAnchorRef={skillInsertAnchorRef}\n routerPush={navigate}\n skillBtnRef={skillBtnRef}\n styleTemplateBtnRef={styleTemplateBtnRef}\n handleSkillClick={handleSkillClick}\n guidedModeEnabled={guidedModeEnabled}\n onToggleGuidedMode={onToggleGuidedMode}\n hasPptSkillInInput={hasPptSkillInInput}\n handleStyleTemplateClick={handleStyleTemplateClick}\n onClearSelectedTemplate={onClearSelectedTemplate}\n showSkillMenu={showSkillMenu}\n skillFilter={skillFilter}\n onSkillSearchChange={onSkillSearchChange}\n filteredSkillOptions={filteredSkillOptions}\n skillOptionsLoading={skillOptionsLoading}\n skillOptionRefs={skillOptionRefs}\n insertSkill={insertSkill}\n setWorkspaceFilter={setWorkspaceFilter}\n folderSelectionEnabled={folderSelectionEnabled}\n selectedFolderTitle={selectedFolderTitle}\n folderButtonLabel={folderButtonLabel}\n shouldShowFolderTooltip={shouldShowFolderTooltip}\n folderBtnRef={folderBtnRef}\n workspaceSearchInputRef={workspaceSearchInputRef}\n workspaceFilter={workspaceFilter}\n showWorkspaceMenu={showWorkspaceMenu}\n workspaceMenuItems={workspaceMenuItems}\n workspaceOptionRefs={workspaceOptionRefs}\n isFolderButtonDisabled={isFolderButtonDisabled}\n sendTemporarilyDisabled={sendTemporarilyDisabled}\n queueSendDisabled={queueSendDisabled}\n handleWorkspaceClick={handleWorkspaceClick}\n handleWorkspaceMenuSelect={handleWorkspaceMenuSelect}\n handleTranscript={handleTranscript}\n handleSend={handleSend}\n onStop={onStop}\n handleQueueSend={handleQueueSend}\n dragOverlayHost={dragOverlayHost}\n showHistorySearch={showHistorySearch}\n handleHistorySelect={handleHistorySelect}\n setShowHistorySearch={setShowHistorySearch}\n isTemplate={isTemplate}\n parsed={parsed}\n activePlaceholderId={activePlaceholderId}\n handlePlaceholderFocus={handlePlaceholderFocus}\n handlePlaceholderBlur={handlePlaceholderBlur}\n handlePlaceholderDelete={handlePlaceholderDelete}\n handlePlaceholderTabNext={handlePlaceholderTabNext}\n />\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { getCachedAgents } from '@/hooks/useAgentData';\n\ntype WebViewBridge = {\n postMessage(message: string): void;\n};\n\ntype WebKitMessageHandler = {\n postMessage(message: string): void;\n};\n\ntype DesktopWindow = Window & {\n chrome?: {\n webview?: WebViewBridge;\n };\n webkit?: {\n messageHandlers?: {\n officeClawDesktop?: WebKitMessageHandler;\n };\n };\n};\n\nfunction getNativeBridge(): WebViewBridge | WebKitMessageHandler | null {\n if (typeof window === 'undefined') {\n return null;\n }\n const desktopWindow = window as DesktopWindow;\n return desktopWindow.chrome?.webview ?? desktopWindow.webkit?.messageHandlers?.officeClawDesktop ?? null;\n}\n\nexport interface DesktopNotificationOptions {\n title: string;\n body: string;\n type?: 'success' | 'error' | 'info';\n threadId?: string;\n}\n\nexport interface ToolApprovalNotificationOptions {\n requestId: string;\n threadId: string;\n /** Legacy field name; carries the current agentId. */\n catId: string;\n action: string;\n reason: string;\n}\n\nconst notifiedToolApprovalRequestIds = new Set<string>();\nconst pendingToolApprovalNotificationIds = new Set<string>();\nconst activeToolApprovalTitleFlashes = new Map<string, () => void>();\n\nfunction focusThread(threadId: string | undefined): void {\n if (typeof window === 'undefined') return;\n window.focus();\n if (!threadId) return;\n\n const targetPath = `/thread/${encodeURIComponent(threadId)}`;\n if (window.location.pathname !== targetPath) {\n window.history.pushState(null, '', targetPath);\n window.dispatchEvent(typeof PopStateEvent === 'function' ? new PopStateEvent('popstate') : new Event('popstate'));\n }\n}\n\nexport function requestNotificationPermission(): void {\n if (typeof window === 'undefined' || !('Notification' in window)) return;\n if (Notification.permission === 'default') {\n Notification.requestPermission();\n }\n}\n\nexport function showBrowserNotification(options: DesktopNotificationOptions): Notification | null {\n if (typeof window === 'undefined' || !('Notification' in window)) return null;\n\n if (Notification.permission !== 'granted') {\n requestNotificationPermission();\n return null;\n }\n\n return createBrowserNotification(options);\n}\n\nfunction createBrowserNotification(options: DesktopNotificationOptions): Notification {\n const notification = new Notification(options.title, {\n body: options.body,\n icon: '/favicon.ico',\n });\n\n notification.onclick = () => {\n focusThread(options.threadId);\n notification.close();\n };\n\n return notification;\n}\n\nfunction sendDesktopNotificationRequest(options: DesktopNotificationOptions): boolean {\n const bridge = getNativeBridge();\n if (!bridge) return false;\n\n const payload = JSON.stringify({\n type: 'desktop.notification',\n title: options.title,\n body: options.body,\n notificationType: options.type ?? 'info',\n threadId: options.threadId ?? null,\n });\n\n bridge.postMessage(payload);\n return true;\n}\n\nfunction startToolApprovalTitleFlash(requestId: string, agentLabel: string): void {\n if (typeof document === 'undefined' || typeof window === 'undefined') return;\n if (!document.hidden || activeToolApprovalTitleFlashes.has(requestId)) return;\n\n const originalTitle = document.title;\n const alertTitle = `🔐 ${agentLabel} 等你批准!`;\n let showAlert = true;\n\n const tick = () => {\n document.title = showAlert ? alertTitle : originalTitle;\n showAlert = !showAlert;\n };\n const intervalId = window.setInterval(tick, 1000);\n tick();\n\n const onVisibilityChange = () => {\n if (!document.hidden) stop();\n };\n\n const stop = () => {\n window.clearInterval(intervalId);\n activeToolApprovalTitleFlashes.delete(requestId);\n document.removeEventListener('visibilitychange', onVisibilityChange);\n document.title = originalTitle;\n };\n\n activeToolApprovalTitleFlashes.set(requestId, stop);\n document.addEventListener('visibilitychange', onVisibilityChange);\n}\n\nfunction resolveAgentDisplayLabel(agentId: string): string {\n if (!agentId || agentId === '智能体') return '智能体';\n return getCachedAgents().find((row) => row.id === agentId)?.displayName ?? agentId;\n}\n\nexport function notifyOnTaskComplete(options: DesktopNotificationOptions): void {\n requestNotificationPermission();\n showBrowserNotification(options);\n sendDesktopNotificationRequest(options);\n}\n\nexport function notifyToolApprovalRequest(options: ToolApprovalNotificationOptions): void {\n if (\n !options.requestId ||\n notifiedToolApprovalRequestIds.has(options.requestId) ||\n pendingToolApprovalNotificationIds.has(options.requestId)\n ) {\n return;\n }\n\n const agentLabel = resolveAgentDisplayLabel(options.catId);\n const notification: DesktopNotificationOptions = {\n title: `${agentLabel} 需要权限`,\n body: `${options.reason}`,\n type: 'info',\n threadId: options.threadId,\n };\n\n startToolApprovalTitleFlash(options.requestId, agentLabel);\n\n if (sendDesktopNotificationRequest(notification)) {\n notifiedToolApprovalRequestIds.add(options.requestId);\n return;\n }\n\n if (typeof document !== 'undefined' && document.hidden) {\n if (typeof window === 'undefined' || !('Notification' in window)) {\n return;\n }\n\n if (Notification.permission === 'granted') {\n const browserNotification = showBrowserNotification(notification);\n if (browserNotification) {\n notifiedToolApprovalRequestIds.add(options.requestId);\n }\n return;\n }\n\n if (Notification.permission !== 'default') {\n return;\n }\n\n pendingToolApprovalNotificationIds.add(options.requestId);\n void Notification.requestPermission()\n .then((permission) => {\n pendingToolApprovalNotificationIds.delete(options.requestId);\n if (permission !== 'granted' || notifiedToolApprovalRequestIds.has(options.requestId)) {\n return;\n }\n createBrowserNotification(notification);\n notifiedToolApprovalRequestIds.add(options.requestId);\n })\n .catch(() => {\n pendingToolApprovalNotificationIds.delete(options.requestId);\n });\n }\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport const THREAD_LIVE_REFRESH_EVENT = 'office-claw:thread-live-refresh';\n\nexport type ThreadLiveRefreshScope = 'all' | 'messages' | 'panels';\n\nexport interface ThreadLiveRefreshDetail {\n threadId: string;\n scope: ThreadLiveRefreshScope;\n reason?: string;\n}\n\nexport function requestThreadLiveRefresh(\n threadId: string,\n scope: ThreadLiveRefreshScope = 'all',\n reason?: string,\n) {\n if (typeof window === 'undefined' || !threadId) return;\n window.dispatchEvent(\n new CustomEvent<ThreadLiveRefreshDetail>(THREAD_LIVE_REFRESH_EVENT, {\n detail: { threadId, scope, reason },\n }),\n );\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport {\n APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE,\n MODEL_ARTS_RATE_LIMIT_ERROR_CODE,\n MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE,\n getDailyQuotaExhaustedMessage,\n getFriendlyAgentErrorMessage as getSharedFriendlyAgentErrorMessage,\n getRateLimitMessage,\n isDailyQuotaExhaustedError as isSharedDailyQuotaExhaustedError,\n isRateLimitError as isSharedRateLimitError,\n isSensitiveInputError as isSharedSensitiveInputError,\n type ErrorLike as SharedErrorLike,\n} from '@hualinge/relay-shared';\n\nexport { APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE, MODEL_ARTS_RATE_LIMIT_ERROR_CODE, MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE };\n\nexport type ErrorLike = SharedErrorLike & {\n agentDisplayName?: string;\n};\n\nexport function isRateLimitError(msg: ErrorLike): boolean {\n return isSharedRateLimitError(msg);\n}\n\nexport function getRateLimitChatMessage(): string {\n return getRateLimitMessage();\n}\n\nexport function isDailyQuotaExhaustedAgentError(msg: ErrorLike): boolean {\n return isSharedDailyQuotaExhaustedError(msg);\n}\n\nexport function getDailyQuotaExhaustedChatMessage(): string {\n return getDailyQuotaExhaustedMessage();\n}\n\nexport function isSensitiveInputAgentError(msg: ErrorLike): boolean {\n return isSharedSensitiveInputError(msg);\n}\n\nexport function getSensitiveInputErrorToastContent(): { title: string; message: string } {\n return {\n title: '检测到敏感词',\n message: '当前对话触发了敏感词校验,请重新打开一个新会话后再试。',\n };\n}\n\nconst ERROR_SUBTYPE_LABELS: Record<string, string> = {\n error_max_turns: '超出 turn 限制',\n error_max_budget_usd: '预算用尽',\n error_during_execution: '运行时错误',\n error_max_structured_output_retries: '结构化输出重试超限',\n};\n\nexport function getFriendlyAgentErrorMessage(msg: ErrorLike): string {\n return getSharedFriendlyAgentErrorMessage(msg);\n}\n\nfunction getErrorSubtypeLabel(rawContent?: string): string | null {\n if (!rawContent) return null;\n try {\n const parsed = JSON.parse(rawContent) as { errorSubtype?: unknown };\n if (typeof parsed.errorSubtype !== 'string') return null;\n return ERROR_SUBTYPE_LABELS[parsed.errorSubtype] ?? null;\n } catch {\n return null;\n }\n}\n\nexport function getAgentErrorToastContent(msg: ErrorLike & { content?: string }): { title: string; message: string } {\n if (isSensitiveInputAgentError(msg)) {\n return getSensitiveInputErrorToastContent();\n }\n\n const subtypeLabel = getErrorSubtypeLabel(msg.content);\n const baseMessage = getFriendlyAgentErrorMessage(msg);\n const agentLabel = msg.agentDisplayName?.trim() || msg.agentId?.trim();\n\n return {\n title: agentLabel ? `${agentLabel} 出错` : '智能体出错',\n message: subtypeLabel ? `${baseMessage} (${subtypeLabel})` : baseMessage,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport function isSchedulerPlaceholderMessage(msg: {\n agentId?: string | null;\n origin?: string | null;\n source?: { connector?: string | null } | null;\n}): boolean {\n return msg.origin === 'callback' && msg.agentId === 'system' && msg.source?.connector === 'scheduler';\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nexport type PptStudioStatus = 'generating' | 'editable' | 'exporting' | 'error';\n\nexport interface PptStudioSlide {\n slideId: string;\n pageNumber: number;\n htmlPath: string;\n title: string | null;\n blockCount: number | null;\n updatedAt: number | null;\n url?: string | null;\n sha256?: string | null;\n}\n\nexport interface PptStudioSlideInput {\n slideId: string;\n pageNumber: number;\n htmlPath: string;\n title?: string | null;\n blockCount?: number | null;\n updatedAt?: number | null;\n url?: string | null;\n sha256?: string | null;\n}\n\nexport interface PptMessageContext {\n projectRoot?: string;\n pagesDir: string;\n deckTitle?: string;\n}\n\nexport interface PptStudioSession {\n threadId: string;\n /** Thread project path — required for PPT API path resolution after workspace sunset (F143). */\n projectRoot: string | null;\n pagesDir: string;\n deckTitle: string;\n expectedSlideCount?: number;\n status: PptStudioStatus;\n slides: PptStudioSlide[];\n activeSlideId: string | null;\n}\n\nexport interface PptStudioSlidesUpdate {\n projectRoot?: string | null;\n pagesDir: string;\n deckTitle?: string;\n expectedSlideCount?: number;\n status?: PptStudioStatus;\n slides: PptStudioSlideInput[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction getNullableString(value: unknown): string | null | undefined {\n if (value === null) return null;\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction getNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getPagesDirFromHtmlPath(htmlPath: string): string | undefined {\n const lastSlash = htmlPath.lastIndexOf('/');\n if (lastSlash <= 0) return undefined;\n return htmlPath.slice(0, lastSlash);\n}\n\nfunction inferPageNumberFromHtmlPath(htmlPath: string): number | undefined {\n const match = htmlPath.match(/page-(\\d+)\\.pptx\\.html$/i);\n if (!match) return undefined;\n return Number(match[1]);\n}\n\nfunction coercePptStudioSlide(value: unknown): PptStudioSlideInput | null {\n if (!isRecord(value)) return null;\n\n const htmlPath = typeof value.htmlPath === 'string' ? value.htmlPath : undefined;\n const pageNumber = getNumber(value.pageNumber) ?? (htmlPath ? inferPageNumberFromHtmlPath(htmlPath) : undefined);\n const slideId =\n typeof value.slideId === 'string'\n ? value.slideId\n : pageNumber !== undefined\n ? `slide-${pageNumber}`\n : undefined;\n\n if (!htmlPath || pageNumber === undefined || !slideId) return null;\n\n return {\n slideId,\n pageNumber,\n htmlPath,\n ...(getNullableString(value.title) !== undefined ? { title: getNullableString(value.title) } : {}),\n ...(value.blockCount === null || getNumber(value.blockCount) !== undefined\n ? { blockCount: getNumber(value.blockCount) ?? null }\n : {}),\n ...(value.updatedAt === null || getNumber(value.updatedAt) !== undefined\n ? { updatedAt: getNumber(value.updatedAt) ?? null }\n : {}),\n ...(getNullableString(value.url) !== undefined ? { url: getNullableString(value.url) } : {}),\n ...(getNullableString(value.sha256) !== undefined ? { sha256: getNullableString(value.sha256) } : {}),\n };\n}\n\nexport function coercePptStudioStatus(value: unknown): PptStudioStatus | null {\n return value === 'generating' || value === 'editable' || value === 'exporting' || value === 'error' ? value : null;\n}\n\nexport function coercePptStudioSlidesUpdate(raw: Record<string, unknown>): PptStudioSlidesUpdate | null {\n const source = isRecord(raw.session) ? raw.session : raw;\n\n const slides =\n Array.isArray(source.slides) && source.slides.length > 0\n ? source.slides.map(coercePptStudioSlide).filter((slide): slide is PptStudioSlideInput => slide !== null)\n : [];\n\n if (slides.length === 0) {\n const singleSlide = coercePptStudioSlide(source);\n if (singleSlide) slides.push(singleSlide);\n }\n\n const pagesDir =\n (typeof source.pagesDir === 'string' ? source.pagesDir : undefined) ??\n (slides[0] ? getPagesDirFromHtmlPath(slides[0].htmlPath) : null);\n\n if (!pagesDir) return null;\n\n const status = coercePptStudioStatus(source.status);\n\n return {\n pagesDir,\n ...(typeof source.deckTitle === 'string' ? { deckTitle: source.deckTitle } : {}),\n ...(getNumber(source.expectedSlideCount) !== undefined ? { expectedSlideCount: getNumber(source.expectedSlideCount) } : {}),\n ...(status ? { status } : {}),\n slides,\n };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\ntype ParsedSystemInfo = Record<string, unknown>;\n\nfunction stripWrappedValue(value: string): string {\n const trimmed = value.trim().replace(/^[{]\\s*/, '').replace(/\\s*[}]$/, '').trim();\n if (\n (trimmed.startsWith('\"') && trimmed.endsWith('\"')) ||\n (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) ||\n (trimmed.startsWith('`') && trimmed.endsWith('`'))\n ) {\n return trimmed.slice(1, -1);\n }\n return trimmed;\n}\n\nfunction extractPseudoField(raw: string, key: string): string | undefined {\n const re = new RegExp(String.raw`(?:^|[,{]\\s*)${key}\\s*:\\s*(\"[^\"]*\"|'[^']*'|` + '`[^`]*`' + String.raw`|[^,}]+)`, 'i');\n const match = raw.match(re);\n return match?.[1] ? stripWrappedValue(match[1]) : undefined;\n}\n\nfunction extractPseudoTrailingField(raw: string, key: string): string | undefined {\n const re = new RegExp(String.raw`\\b${key}\\s*:\\s*(.+)$`, 'is');\n const match = raw.match(re);\n return match?.[1] ? stripWrappedValue(match[1]) : undefined;\n}\n\nexport function parseSystemInfoContent(raw: string): ParsedSystemInfo | null {\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === 'object') return parsed as ParsedSystemInfo;\n } catch {\n // Fall through to tolerate pseudo-object diagnostics from provider streams,\n // for example: type: thinking, agentId: office, text: 流程\n }\n\n const type = extractPseudoField(raw, 'type');\n if (!type) return null;\n\n if (type === 'thinking') {\n const text = extractPseudoTrailingField(raw, 'text');\n if (!text) return null;\n const agentId = extractPseudoField(raw, 'agentId');\n const mergeStrategy = extractPseudoField(raw, 'mergeStrategy');\n return {\n type,\n ...(agentId ? { agentId } : {}),\n ...(mergeStrategy ? { mergeStrategy } : {}),\n text,\n };\n }\n\n if (type === 'processing_status') {\n const status = extractPseudoField(raw, 'status');\n if (!status) return null;\n return { type, status };\n }\n\n return null;\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { coercePptStudioSlidesUpdate, coercePptStudioStatus } from '@/components/ppt-studio/ppt-studio-types';\nimport type { TaskProgressItem } from '@/stores/chat-types';\nimport type {\n BackgroundAgentMessage,\n BackgroundStreamRef,\n HandleBackgroundMessageOptions,\n} from './useSocket-background.types';\nimport { parseSystemInfoContent } from './parse-system-info';\n\ninterface SystemInfoConsumeResult {\n consumed: boolean;\n content: string;\n variant: 'info' | 'warning' | 'a2a_followup';\n}\n\nfunction recoverBackgroundStreamingMessage(\n msg: BackgroundAgentMessage,\n options: HandleBackgroundMessageOptions,\n): string | undefined {\n const streamKey = `${msg.threadId}::${msg.agentId}`;\n const threadMessages = options.store.getThreadState(msg.threadId).messages;\n for (let i = threadMessages.length - 1; i >= 0; i--) {\n const message = threadMessages[i];\n if (message.type === 'assistant' && message.agentId === msg.agentId && message.isStreaming) {\n options.bgStreamRefs.set(streamKey, { id: message.id, threadId: msg.threadId, agentId: msg.agentId });\n if (msg.metadata) {\n options.store.setThreadMessageMetadata(msg.threadId, message.id, msg.metadata);\n }\n return message.id;\n }\n }\n return undefined;\n}\n\nexport function consumeBackgroundSystemInfo(\n msg: BackgroundAgentMessage,\n existingRef: BackgroundStreamRef | undefined,\n options: HandleBackgroundMessageOptions,\n): SystemInfoConsumeResult {\n let sysContent = msg.content ?? '';\n let sysVariant: 'info' | 'warning' | 'a2a_followup' = 'info';\n let consumed = false;\n\n try {\n const parsed = parseSystemInfoContent(sysContent);\n if (!parsed) throw new Error('not parseable system_info');\n if (parsed?.type === 'ppt_studio_page') {\n const sessionUpdate = coercePptStudioSlidesUpdate(parsed);\n if (sessionUpdate) {\n options.store.upsertPptStudioSlides(msg.threadId, sessionUpdate);\n consumed = true;\n }\n } else if (parsed?.type === 'ppt_studio_export') {\n const status = coercePptStudioStatus(parsed.status);\n if (status) {\n options.store.setPptStudioStatus(msg.threadId, status);\n consumed = true;\n }\n } else if (parsed?.type === 'invocation_created') {\n const targetCatId = parsed.agentId ?? msg.agentId;\n const invocationId = typeof parsed.invocationId === 'string' ? parsed.invocationId : undefined;\n // #586: Clear stale finalizedBgRef so previous invocation's finalized bubble\n // can't be overwritten by the next invocation's callback.\n const bgStreamKey = `${msg.threadId}::${targetCatId}`;\n options.finalizedBgRefs.delete(bgStreamKey);\n if (targetCatId && invocationId) {\n options.store.setThreadLoading(msg.threadId, true);\n options.store.addThreadActiveInvocation(msg.threadId, invocationId, targetCatId, 'execute');\n options.store.updateThreadAgentStatus(msg.threadId, targetCatId, 'streaming');\n options.store.setThreadAgentInvocation(msg.threadId, targetCatId, {\n invocationId,\n startedAt: Date.now(),\n taskProgress: {\n tasks: [],\n lastUpdate: Date.now(),\n snapshotStatus: 'running',\n lastInvocationId: invocationId,\n },\n });\n const targetId = existingRef?.id ?? recoverBackgroundStreamingMessage(msg, options);\n if (targetId) {\n options.store.setThreadMessageStreamInvocation(msg.threadId, targetId, invocationId);\n }\n consumed = true;\n }\n } else if (parsed?.type === 'invocation_metrics') {\n if (parsed.kind === 'session_started') {\n options.store.setThreadAgentInvocation(msg.threadId, msg.agentId, {\n sessionId: parsed.sessionId,\n invocationId: parsed.invocationId,\n startedAt: Date.now(),\n taskProgress: { tasks: [], lastUpdate: 0 },\n ...(parsed.sessionSeq !== undefined ? { sessionSeq: parsed.sessionSeq, sessionSealed: false } : {}),\n });\n } else if (parsed.kind === 'invocation_complete') {\n const completeInvId = typeof parsed.invocationId === 'string' ? parsed.invocationId : undefined;\n const dur =\n typeof parsed.durationMs === 'number' && Number.isFinite(parsed.durationMs) ? parsed.durationMs : undefined;\n options.store.setThreadAgentInvocation(msg.threadId, msg.agentId, {\n ...(dur !== undefined ? { durationMs: dur } : {}),\n sessionId: parsed.sessionId,\n });\n if (dur !== undefined && dur >= 0 && completeInvId) {\n const threadMsgs = options.store.getThreadState(msg.threadId).messages;\n const hit = threadMsgs.find(\n (m) =>\n m.type === 'assistant' &&\n m.agentId === msg.agentId &&\n m.extra?.stream?.invocationId === completeInvId,\n );\n if (hit) {\n options.store.setThreadMessageStreamExecutionDuration(msg.threadId, hit.id, dur);\n }\n }\n }\n consumed = true;\n } else if (parsed?.type === 'invocation_usage') {\n options.store.setThreadAgentInvocation(msg.threadId, msg.agentId, {\n usage: parsed.usage,\n });\n if (existingRef?.id) {\n options.store.setThreadMessageUsage(msg.threadId, existingRef.id, parsed.usage);\n }\n consumed = true;\n } else if (parsed?.type === 'context_health') {\n const targetCatId = parsed.agentId ?? msg.agentId;\n options.store.setThreadAgentInvocation(msg.threadId, targetCatId, {\n contextHealth: parsed.health,\n });\n consumed = true;\n } else if (parsed?.type === 'rate_limit') {\n const targetCatId = parsed.agentId ?? msg.agentId;\n options.store.setThreadAgentInvocation(msg.threadId, targetCatId, {\n rateLimit: {\n ...(typeof parsed.utilization === 'number' ? { utilization: parsed.utilization } : {}),\n ...(typeof parsed.resetsAt === 'string' ? { resetsAt: parsed.resetsAt } : {}),\n },\n });\n consumed = true;\n } else if (parsed?.type === 'compact_boundary') {\n const targetCatId = parsed.agentId ?? msg.agentId;\n options.store.setThreadAgentInvocation(msg.threadId, targetCatId, {\n compactBoundary: {\n ...(typeof parsed.preTokens === 'number' ? { preTokens: parsed.preTokens } : {}),\n },\n });\n consumed = true;\n } else if (parsed?.type === 'task_progress') {\n const targetCatId = parsed.agentId ?? msg.agentId;\n const currentInvocationId =\n typeof parsed.invocationId === 'string'\n ? parsed.invocationId\n : options.store.getThreadState(msg.threadId).agentInvocations[targetCatId]?.invocationId;\n const tasks = (parsed.tasks ?? []) as TaskProgressItem[];\n options.store.setThreadAgentInvocation(msg.threadId, targetCatId, {\n taskProgress: {\n tasks,\n lastUpdate: Date.now(),\n snapshotStatus: 'running',\n ...(currentInvocationId ? { lastInvocationId: currentInvocationId } : {}),\n },\n });\n consumed = true;\n } else if (parsed?.type === 'web_search') {\n // F045: web_search tool event (privacy: no query, count only) — render as ToolEvent, not raw JSON\n const count = typeof parsed.count === 'number' ? parsed.count : 1;\n let targetId = existingRef?.id;\n if (!targetId) {\n targetId = recoverBackgroundStreamingMessage(msg, options);\n }\n if (!targetId) {\n // Create placeholder assistant bubble if needed (mirrors thinking path)\n const streamKey = `${msg.threadId}::${msg.agentId}`;\n targetId = `bg-web-${Date.now()}-${msg.agentId}-${options.nextBgSeq()}`;\n const invocationId = options.store.getThreadState(msg.threadId).agentInvocations[msg.agentId]?.invocationId;\n options.bgStreamRefs.set(streamKey, { id: targetId, threadId: msg.threadId, agentId: msg.agentId });\n options.store.addMessageToThread(msg.threadId, {\n id: targetId,\n type: 'assistant',\n agentId: msg.agentId,\n content: '',\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(invocationId ? { extra: { stream: { invocationId } } } : {}),\n timestamp: msg.timestamp,\n isStreaming: true,\n origin: 'stream',\n });\n }\n\n options.store.appendToolEventToThread(msg.threadId, targetId, {\n id: `bg-web-search-${msg.timestamp}-${options.nextBgSeq()}`,\n type: 'tool_use',\n label: `${msg.agentId} → web_search${count > 1 ? ` x${count}` : ''}`,\n timestamp: msg.timestamp,\n });\n consumed = true;\n } else if (parsed?.type === 'rich_block') {\n // F22: Append rich block — mirror foreground path (useAgentMessages.ts)\n let targetId: string | undefined;\n\n // Prefer messageId correlation from callback post-message path\n if (parsed.messageId) {\n const found = options.store\n .getThreadState(msg.threadId)\n .messages.find((m: { id: string }) => m.id === parsed.messageId);\n if (found) targetId = found.id;\n }\n\n // Fallback: most recent callback message from this cat\n if (!targetId) {\n const threadMessages = options.store.getThreadState(msg.threadId).messages;\n for (let i = threadMessages.length - 1; i >= 0; i--) {\n const m = threadMessages[i];\n if (m.type !== 'assistant' || m.agentId !== msg.agentId) continue;\n if (m.origin === 'stream' && m.isStreaming) break;\n if (m.origin === 'callback') {\n targetId = m.id;\n break;\n }\n }\n }\n\n // Final fallback: recover active stream bubble or create placeholder\n if (!targetId) {\n targetId = existingRef?.id ?? recoverBackgroundStreamingMessage(msg, options);\n }\n if (!targetId) {\n // No existing bubble — create placeholder (mirrors foreground ensureActiveAssistantMessage)\n const streamKey = `${msg.threadId}::${msg.agentId}`;\n targetId = `bg-rich-${Date.now()}-${msg.agentId}-${options.nextBgSeq()}`;\n const invocationId = options.store.getThreadState(msg.threadId).agentInvocations[msg.agentId]?.invocationId;\n options.bgStreamRefs.set(streamKey, { id: targetId, threadId: msg.threadId, agentId: msg.agentId });\n options.store.addMessageToThread(msg.threadId, {\n id: targetId,\n type: 'assistant',\n agentId: msg.agentId,\n content: '',\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(invocationId ? { extra: { stream: { invocationId } } } : {}),\n timestamp: msg.timestamp,\n isStreaming: true,\n origin: 'stream',\n });\n }\n\n if (parsed.block) {\n options.store.appendRichBlockToThread(msg.threadId, targetId, parsed.block);\n }\n consumed = true;\n } else if (parsed?.type === 'liveness_warning') {\n // F118 Phase C: Liveness warning — update cat status + invocation snapshot (mirror foreground)\n const level = parsed.level as 'alive_but_silent' | 'suspected_stall';\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, level);\n options.store.setThreadAgentInvocation(msg.threadId, msg.agentId, {\n livenessWarning: {\n level,\n state: parsed.state as 'active' | 'busy-silent' | 'idle-silent' | 'dead',\n silenceDurationMs: parsed.silenceDurationMs as number,\n cpuTimeMs: typeof parsed.cpuTimeMs === 'number' ? parsed.cpuTimeMs : undefined,\n processAlive: parsed.processAlive as boolean,\n receivedAt: Date.now(),\n },\n });\n consumed = true;\n } else if (parsed?.type === 'timeout_diagnostics') {\n // F118 AC-C3: Timeout diagnostics — consume silently in background threads.\n // Foreground uses pendingTimeoutDiagRef (React ref) to attach to error messages;\n // background threads don't have that mechanism, so we just suppress the raw JSON.\n consumed = true;\n } else if (parsed?.type === 'warning') {\n // F045: item-level warning — render as readable system message (mirror foreground)\n const warningText = typeof parsed.message === 'string' ? parsed.message : '';\n sysContent = warningText ? `⚠️ ${warningText}` : '⚠️ Warning';\n sysVariant = 'warning';\n } else if (parsed?.type === 'processing_status') {\n // RelayClaw processing heartbeat — keep background cat status fresh without a raw JSON bubble.\n const processingStatus = parsed.status as string;\n if (processingStatus !== 'idle') {\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'streaming');\n }\n consumed = true;\n } else if (parsed?.type === 'strategy_allow_compress' || parsed?.type === 'resume_failure_stats') {\n // Internal telemetry — suppress to avoid raw JSON bubbles in background threads\n consumed = true;\n } else if (parsed?.type === 'session_seal_requested') {\n if (parsed.agentId) {\n options.store.setThreadAgentInvocation(msg.threadId, parsed.agentId, {\n sessionSeq: parsed.sessionSeq,\n sessionSealed: true,\n });\n const pct = parsed.healthSnapshot?.fillRatio ? Math.round(parsed.healthSnapshot.fillRatio * 100) : '?';\n sysContent = `${parsed.agentId} 的会话 #${parsed.sessionSeq} 已封存(上下文 ${pct}%),下次调用将自动创建新会话`;\n }\n } else if (parsed?.type === 'a2a_followup_available') {\n const mentions = parsed.mentions as Array<{ agentId: string; mentionedBy: string }>;\n if (Array.isArray(mentions) && mentions.length > 0) {\n sysContent = mentions.map((m) => `${m.mentionedBy} @了 ${m.agentId}`).join('、');\n sysVariant = 'a2a_followup';\n }\n } else if (parsed?.type === 'mode_switch_proposal') {\n const by = parsed.proposedBy ?? '智能体';\n sysContent = `${by} 提议切换到 ${parsed.proposedMode} 模式。`;\n } else if (parsed?.type === 'silent_completion') {\n // Bugfix: silent-exit — cat ran tools but produced no text response\n const detail = typeof parsed.detail === 'string' ? parsed.detail : '';\n sysContent = detail || `${msg.agentId} completed without a text response.`;\n } else if (parsed?.type === 'invocation_preempted') {\n // Bugfix: silent-exit — invocation was superseded by a newer request\n sysContent = 'This response was superseded by a newer request.';\n } else if (parsed?.type === 'thinking') {\n // F045: Embed thinking into the assistant bubble (matches foreground path)\n const thinkingText = parsed.text ?? '';\n if (thinkingText) {\n let targetId = existingRef?.id;\n if (!targetId) {\n targetId = recoverBackgroundStreamingMessage(msg, options);\n }\n if (!targetId) {\n // Thinking arrived before any text/tool chunk — create placeholder assistant bubble\n const streamKey = `${msg.threadId}::${msg.agentId}`;\n targetId = `bg-think-${Date.now()}-${msg.agentId}-${options.nextBgSeq()}`;\n const invocationId = options.store.getThreadState(msg.threadId).agentInvocations[msg.agentId]?.invocationId;\n options.bgStreamRefs.set(streamKey, { id: targetId, threadId: msg.threadId, agentId: msg.agentId });\n options.store.addMessageToThread(msg.threadId, {\n id: targetId,\n type: 'assistant',\n agentId: msg.agentId,\n content: '',\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(invocationId ? { extra: { stream: { invocationId } } } : {}),\n timestamp: msg.timestamp,\n isStreaming: true,\n origin: 'stream',\n });\n }\n options.store.setThreadMessageThinking(msg.threadId, targetId, thinkingText);\n }\n consumed = true;\n }\n } catch {\n // Not JSON; keep original content as user-facing system info.\n }\n\n return { consumed, content: sysContent, variant: sysVariant };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport { recordDebugEvent } from '@/debug/invocationEventDebug';\nimport { getAgentErrorToastContent } from '@/hooks/agent-error-fallback';\nimport { getCachedAgents } from '@/hooks/useAgentData';\nimport type { AgentStatusType } from '@/stores/chat-types';\nimport type {\n ActiveRoutedAgentMessage,\n BackgroundAgentMessage,\n BackgroundStreamRef,\n HandleBackgroundMessageOptions,\n} from './useSocket-background.types';\nimport { isSchedulerPlaceholderMessage } from './scheduler-placeholder';\nimport { consumeBackgroundSystemInfo } from './useSocket-background-system-info';\n\nexport type {\n ActiveRoutedAgentMessage,\n BackgroundAgentMessage,\n BackgroundStoreLike,\n BackgroundStreamRef,\n BackgroundToastInput,\n HandleBackgroundMessageOptions,\n} from './useSocket-background.types';\n\nconst STATUS_MAP: Record<string, AgentStatusType> = {\n streaming: 'streaming',\n thinking: 'pending',\n done: 'done',\n};\n\nfunction getStreamKey(msg: Pick<BackgroundAgentMessage, 'threadId' | 'agentId'>): string {\n return `${msg.threadId}::${msg.agentId}`;\n}\n\nfunction resolveAgentDisplayLabel(agentId: string): string {\n return getCachedAgents().find((row) => row.id === agentId)?.displayName ?? agentId;\n}\n\nfunction buildMessageExtra(\n msg: Pick<BackgroundAgentMessage, 'extra'>,\n invocationId?: string | null,\n): NonNullable<import('@/stores/chat-types').ChatMessage['extra']> | undefined {\n const extra = {\n ...(msg.extra?.crossPost ? { crossPost: msg.extra.crossPost } : {}),\n ...(msg.extra?.errorFallback ? { errorFallback: msg.extra.errorFallback } : {}),\n ...(invocationId ? { stream: { invocationId } } : {}),\n };\n return Object.keys(extra).length > 0 ? extra : undefined;\n}\n\nfunction getErrorFallback(\n msg: Pick<BackgroundAgentMessage, 'extra'>,\n finalMessage?: { extra?: { errorFallback?: { rawError?: string } } },\n): { rawError: string } | null {\n const fb = msg.extra?.errorFallback ?? finalMessage?.extra?.errorFallback;\n if (!fb?.rawError) return null;\n return { rawError: fb.rawError };\n}\n\nfunction findLatestActiveInvocationIdForAgent(\n activeInvocations: Record<string, { agentId: string; mode: string }> | undefined,\n agentId: string,\n): string | undefined {\n if (!activeInvocations) return undefined;\n const entries = Object.entries(activeInvocations);\n for (let i = entries.length - 1; i >= 0; i--) {\n const [invocationId, info] = entries[i]!;\n if (info.agentId === agentId) return invocationId;\n }\n return undefined;\n}\n\nfunction shouldClearBackgroundRefOnActiveEvent(msg: ActiveRoutedAgentMessage): boolean {\n if (!msg.threadId) return false;\n if (msg.type === 'done') return true;\n if (msg.type === 'error') return msg.isFinal === true;\n if (msg.type === 'text' && msg.isFinal) return true;\n return false;\n}\n\nfunction getThreadInvocationId(\n msg: Pick<BackgroundAgentMessage, 'threadId' | 'agentId'>,\n options: HandleBackgroundMessageOptions,\n): string | undefined {\n const threadState = options.store.getThreadState(msg.threadId);\n return (\n threadState.agentInvocations[msg.agentId]?.invocationId ??\n findLatestActiveInvocationIdForAgent(threadState.activeInvocations, msg.agentId)\n );\n}\n\nexport function clearBackgroundStreamRefForActiveEvent(\n msg: ActiveRoutedAgentMessage,\n bgStreamRefs: Map<string, BackgroundStreamRef>,\n): void {\n if (!shouldClearBackgroundRefOnActiveEvent(msg) || !msg.threadId) return;\n bgStreamRefs.delete(`${msg.threadId}::${msg.agentId}`);\n}\n\nfunction stopTrackedStream(\n streamKey: string,\n msg: BackgroundAgentMessage,\n options: HandleBackgroundMessageOptions,\n): BackgroundStreamRef | undefined {\n const existing = options.bgStreamRefs.get(streamKey);\n if (!existing) return undefined;\n options.store.setThreadMessageStreaming(msg.threadId, existing.id, false);\n // #586 follow-up: Record finalized bubble ID so callback can find it\n // after bgStreamRefs is cleared and isStreaming is false.\n options.finalizedBgRefs.set(streamKey, existing.id);\n options.bgStreamRefs.delete(streamKey);\n return existing;\n}\n\nfunction markBackgroundErrorToastShown(streamKey: string, options: HandleBackgroundMessageOptions): void {\n options.backgroundErrorToastsShown.add(streamKey);\n}\n\nfunction hasShownBackgroundErrorToast(streamKey: string, options: HandleBackgroundMessageOptions): boolean {\n return options.backgroundErrorToastsShown.has(streamKey);\n}\n\nfunction truncate(text: string, maxLength: number): string {\n if (text.length <= maxLength) return text;\n return `${text.slice(0, maxLength)}...`;\n}\n\nfunction safeJsonPreview(value: unknown, maxLength: number): string {\n try {\n return truncate(JSON.stringify(value), maxLength);\n } catch {\n return '[unserializable input]';\n }\n}\n\nfunction toolUseDetail(toolName: string | undefined, toolInput: unknown): string | undefined {\n if (toolInput === null || toolInput === undefined) return undefined;\n if (toolName === 'send_file_to_user') {\n try {\n return JSON.stringify(toolInput);\n } catch {\n return safeJsonPreview(toolInput, 200);\n }\n }\n return safeJsonPreview(toolInput, 200);\n}\n\nfunction addBackgroundSystemMessage(\n msg: BackgroundAgentMessage,\n options: HandleBackgroundMessageOptions,\n content: string,\n variant: 'info' | 'warning' | 'a2a_followup' = 'info',\n): void {\n options.store.addMessageToThread(msg.threadId, {\n id: `bg-sys-${msg.timestamp}-${msg.agentId}-${options.nextBgSeq()}`,\n type: 'system',\n variant,\n agentId: msg.agentId,\n content,\n timestamp: msg.timestamp,\n });\n}\n\n/**\n * Recover an existing streaming assistant message from the thread state.\n * This handles the active→background transition: when the user switches threads,\n * activeRefs are cleared but the streaming message still exists in the store.\n * Instead of creating a duplicate bubble, we adopt the existing one into bgStreamRefs.\n */\nfunction recoverStreamingMessage(\n msg: BackgroundAgentMessage,\n streamKey: string,\n options: HandleBackgroundMessageOptions,\n): string | undefined {\n const threadMessages = options.store.getThreadState(msg.threadId).messages;\n for (let i = threadMessages.length - 1; i >= 0; i--) {\n const m = threadMessages[i];\n if (m.type === 'assistant' && m.agentId === msg.agentId && m.isStreaming) {\n options.bgStreamRefs.set(streamKey, { id: m.id, threadId: msg.threadId, agentId: msg.agentId });\n recordDebugEvent({\n event: 'bubble_lifecycle',\n threadId: msg.threadId,\n timestamp: msg.timestamp,\n action: 'recover',\n reason: 'background_ref_lost',\n agentId: msg.agentId,\n messageId: m.id,\n invocationId: m.extra?.stream?.invocationId,\n origin: 'stream',\n });\n return m.id;\n }\n }\n return undefined;\n}\n\nfunction findBackgroundCallbackReplacementTarget(\n msg: BackgroundAgentMessage,\n options: HandleBackgroundMessageOptions,\n): { id: string; invocationId: string | null } | null {\n const invocationId = msg.invocationId ?? getThreadInvocationId(msg, options);\n\n const threadMessages = options.store.getThreadState(msg.threadId).messages;\n\n // Try invocationId-based match first\n if (invocationId) {\n for (let i = threadMessages.length - 1; i >= 0; i -= 1) {\n const m = threadMessages[i];\n if (\n m?.type === 'assistant' &&\n m.agentId === msg.agentId &&\n m.origin === 'stream' &&\n m.extra?.stream?.invocationId === invocationId\n ) {\n return { id: m.id, invocationId };\n }\n }\n }\n\n // #586 Bug 1: Fallback — find invocationless stream placeholder from the same agent.\n // Background system-info creates bg-rich/bg-think placeholders without invocationId;\n // without this fallback, callback creates a duplicate bubble alongside the placeholder.\n // #586 P1-2 fix: Return real invocationId (may be null) — callers must guard\n // against null before writing to replacedInvocations. Using a pseudo ID would\n // cause shouldSuppressLateBackgroundStreamChunk to permanently drop future\n // invocationless stream chunks.\n // First pass: actively-streaming invocationless placeholder\n for (let i = threadMessages.length - 1; i >= 0; i -= 1) {\n const m = threadMessages[i];\n if (\n m?.type === 'assistant' &&\n m.agentId === msg.agentId &&\n m.origin === 'stream' &&\n m.isStreaming &&\n !m.extra?.stream?.invocationId\n ) {\n return { id: m.id, invocationId: invocationId ?? null };\n }\n }\n // #586 follow-up: Check finalizedBgRefs — the done handler records the exact\n // message ID of the just-finalized stream bubble. This avoids the greedy scan\n // that could match arbitrary historical messages (P1 from review).\n const streamKey = `${msg.threadId}::${msg.agentId}`;\n const finalizedId = options.finalizedBgRefs.get(streamKey);\n if (finalizedId) {\n const finalized = threadMessages.find(\n (m) => m.id === finalizedId && m.type === 'assistant' && m.agentId === msg.agentId && m.origin === 'stream',\n );\n if (finalized) {\n return { id: finalized.id, invocationId: invocationId ?? null };\n }\n }\n\n return null;\n}\n\nfunction shouldSuppressLateBackgroundStreamChunk(\n msg: BackgroundAgentMessage,\n streamKey: string,\n options: HandleBackgroundMessageOptions,\n): boolean {\n const replacedInvocationId = options.replacedInvocations.get(streamKey);\n if (!replacedInvocationId) return false;\n\n const currentInvocationId = msg.invocationId ?? getThreadInvocationId(msg, options);\n if (currentInvocationId && currentInvocationId !== replacedInvocationId) {\n options.replacedInvocations.delete(streamKey);\n return false;\n }\n\n recordDebugEvent({\n event: 'bubble_lifecycle',\n threadId: msg.threadId,\n timestamp: msg.timestamp,\n action: 'drop',\n reason: 'late_stream_after_callback_replace',\n agentId: msg.agentId,\n invocationId: replacedInvocationId,\n origin: 'stream',\n });\n return true;\n}\n\nfunction ensureBackgroundAssistantMessage(\n msg: BackgroundAgentMessage,\n streamKey: string,\n existing: BackgroundStreamRef | undefined,\n options: HandleBackgroundMessageOptions,\n): string {\n if (existing?.id) {\n if (msg.metadata) {\n options.store.setThreadMessageMetadata(msg.threadId, existing.id, msg.metadata);\n }\n return existing.id;\n }\n\n // Active→background transition recovery: find existing streaming bubble\n const recoveredId = recoverStreamingMessage(msg, streamKey, options);\n if (recoveredId) {\n if (msg.metadata) {\n options.store.setThreadMessageMetadata(msg.threadId, recoveredId, msg.metadata);\n }\n return recoveredId;\n }\n\n const messageId = `bg-tool-${msg.timestamp}-${msg.agentId}-${options.nextBgSeq()}`;\n const invocationId = getThreadInvocationId(msg, options);\n options.bgStreamRefs.set(streamKey, { id: messageId, threadId: msg.threadId, agentId: msg.agentId });\n options.store.addMessageToThread(msg.threadId, {\n id: messageId,\n type: 'assistant',\n agentId: msg.agentId,\n content: '',\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(invocationId ? { extra: { stream: { invocationId } } } : {}),\n timestamp: msg.timestamp,\n isStreaming: true,\n origin: 'stream',\n });\n return messageId;\n}\n\nfunction markThreadInvocationActive(msg: BackgroundAgentMessage, options: HandleBackgroundMessageOptions): void {\n const threadState = options.store.getThreadState(msg.threadId);\n if (!threadState.isLoading) {\n options.store.setThreadLoading(msg.threadId, true);\n }\n // F108: slot-aware — register specific invocation if ID available\n if (msg.invocationId) {\n options.store.addThreadActiveInvocation(msg.threadId, msg.invocationId, msg.agentId, 'execute');\n } else if (!threadState.hasActiveInvocation) {\n options.store.setThreadHasActiveInvocation(msg.threadId, true);\n }\n}\n\nfunction markThreadInvocationComplete(msg: BackgroundAgentMessage, options: HandleBackgroundMessageOptions): void {\n options.store.setThreadLoading(msg.threadId, false);\n options.store.setThreadAgentInvocation(msg.threadId, msg.agentId, { invocationId: undefined });\n // F108: slot-aware — remove specific invocation if ID available.\n // Cancel fallback: find and remove only this agent's latest active slot to avoid\n // clearing other agents' slots during concurrent dispatch.\n if (msg.invocationId) {\n options.store.removeThreadActiveInvocation(msg.threadId, msg.invocationId);\n } else {\n const threadState = options.store.getThreadState(msg.threadId);\n const activeInvocationSlot = findLatestActiveInvocationIdForAgent(threadState.activeInvocations, msg.agentId);\n if (activeInvocationSlot) {\n options.store.removeThreadActiveInvocation(msg.threadId, activeInvocationSlot);\n } else {\n options.store.setThreadHasActiveInvocation(msg.threadId, false);\n }\n }\n}\n\nexport function handleBackgroundAgentMessage(\n msg: BackgroundAgentMessage,\n options: HandleBackgroundMessageOptions,\n): void {\n if (isSchedulerPlaceholderMessage(msg)) {\n return;\n }\n\n const streamKey = getStreamKey(msg);\n const existing = options.bgStreamRefs.get(streamKey);\n\n if (msg.type === 'text' && msg.content) {\n const isCallbackText = msg.origin === 'callback';\n if (!isCallbackText) {\n markThreadInvocationActive(msg, options);\n }\n // Track the final message ID for toast preview (must capture before deleting bgStreamRefs)\n let finalMsgId: string | undefined;\n\n if (msg.origin === 'callback') {\n const replacementTarget = findBackgroundCallbackReplacementTarget(msg, options);\n if (replacementTarget) {\n const cbId = msg.messageId ?? replacementTarget.id;\n if (cbId !== replacementTarget.id) {\n options.store.replaceThreadMessageId(msg.threadId, replacementTarget.id, cbId);\n }\n options.store.patchThreadMessage(msg.threadId, cbId, {\n content: msg.content,\n origin: 'callback',\n isStreaming: false,\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(buildMessageExtra(msg, replacementTarget.invocationId)\n ? { extra: buildMessageExtra(msg, replacementTarget.invocationId) }\n : {}),\n ...(msg.mentionsUser ? { mentionsUser: true } : {}),\n ...(msg.replyTo ? { replyTo: msg.replyTo } : {}),\n ...(msg.replyPreview ? { replyPreview: msg.replyPreview } : {}),\n });\n options.bgStreamRefs.delete(streamKey);\n // Consume finalized ref — callback successfully replaced\n options.finalizedBgRefs.delete(streamKey);\n // #586 P1-2 fix: Only set replacedInvocations when we have a real invocationId.\n // Fallback matches return null — writing a pseudo ID would permanently suppress\n // future invocationless stream chunks via shouldSuppressLateBackgroundStreamChunk.\n if (replacementTarget.invocationId) {\n options.replacedInvocations.set(streamKey, replacementTarget.invocationId);\n }\n finalMsgId = cbId;\n } else {\n const cbId = msg.messageId ?? `bg-cb-${msg.timestamp}-${msg.agentId}-${options.nextBgSeq()}`;\n const bgInvocationId = msg.invocationId ?? getThreadInvocationId(msg, options);\n options.store.addMessageToThread(msg.threadId, {\n id: cbId,\n type: 'assistant',\n agentId: msg.agentId,\n content: msg.content,\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(buildMessageExtra(msg, bgInvocationId) ? { extra: buildMessageExtra(msg, bgInvocationId) } : {}),\n ...(msg.mentionsUser ? { mentionsUser: true } : {}),\n ...(msg.replyTo ? { replyTo: msg.replyTo } : {}),\n ...(msg.replyPreview ? { replyPreview: msg.replyPreview } : {}),\n timestamp: msg.timestamp,\n origin: 'callback',\n });\n // #586 Bug 1 (TD112): Callback created new bubble without finding a stream\n // placeholder. Mark invocation as replaced so late background stream chunks\n // are suppressed instead of spawning a duplicate bubble.\n if (bgInvocationId) {\n options.replacedInvocations.set(streamKey, bgInvocationId);\n }\n finalMsgId = cbId;\n }\n } else {\n if (shouldSuppressLateBackgroundStreamChunk(msg, streamKey, options)) {\n return;\n }\n // CLI stream text (thinking): merge into existing stream bubble\n let messageId = existing?.id;\n // Active→background transition recovery: find existing streaming bubble\n if (!messageId) {\n messageId = recoverStreamingMessage(msg, streamKey, options);\n }\n if (messageId) {\n const errorFallback = getErrorFallback(msg);\n // HOT PATH: batch content + metadata + streaming + catStatus into ONE set()\n // to prevent React update-depth overflow during high-frequency streaming.\n options.store.batchStreamChunkUpdate({\n threadId: msg.threadId,\n messageId,\n agentId: msg.agentId,\n content: msg.content,\n metadata: msg.metadata,\n streaming: !msg.isFinal,\n nextAgentStatus: errorFallback ? 'error' : msg.isFinal ? 'done' : 'streaming',\n });\n if (msg.replyTo || msg.replyPreview || errorFallback) {\n options.store.patchThreadMessage(msg.threadId, messageId, {\n ...(buildMessageExtra(msg) ? { extra: buildMessageExtra(msg) } : {}),\n ...(msg.replyTo ? { replyTo: msg.replyTo } : {}),\n ...(msg.replyPreview ? { replyPreview: msg.replyPreview } : {}),\n });\n }\n if (msg.isFinal) {\n options.bgStreamRefs.delete(streamKey);\n }\n } else {\n messageId = `bg-${msg.timestamp}-${msg.agentId}-${options.nextBgSeq()}`;\n const invocationId = getThreadInvocationId(msg, options);\n options.bgStreamRefs.set(streamKey, { id: messageId, threadId: msg.threadId, agentId: msg.agentId });\n options.store.addMessageToThread(msg.threadId, {\n id: messageId,\n type: 'assistant',\n agentId: msg.agentId,\n content: msg.content,\n ...(msg.metadata ? { metadata: msg.metadata } : {}),\n ...(buildMessageExtra(msg, invocationId) ? { extra: buildMessageExtra(msg, invocationId) } : {}),\n ...(msg.replyTo ? { replyTo: msg.replyTo } : {}),\n ...(msg.replyPreview ? { replyPreview: msg.replyPreview } : {}),\n timestamp: msg.timestamp,\n isStreaming: !msg.isFinal,\n origin: 'stream',\n });\n // Cat status for new message (not batched — fires once per stream start)\n options.store.updateThreadAgentStatus(\n msg.threadId,\n msg.agentId,\n msg.extra?.errorFallback ? 'error' : msg.isFinal ? 'done' : 'streaming',\n );\n if (msg.isFinal) {\n options.bgStreamRefs.delete(streamKey);\n }\n }\n\n finalMsgId = messageId;\n }\n\n // Callback-only: update agent status on isFinal (non-callback handled by batch/new-message above)\n const errorFallback = getErrorFallback(msg);\n if (isCallbackText && msg.isFinal) {\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, errorFallback ? 'error' : 'done');\n }\n if (msg.isFinal) {\n // #80 fix-C: Clear timeout guard for text(isFinal) path\n options.clearDoneTimeout?.(msg.threadId);\n const finalMessage = finalMsgId\n ? options.store.getThreadState(msg.threadId).messages.find((m) => m.id === finalMsgId)\n : undefined;\n const preview = finalMessage?.content ?? msg.content;\n const agentLabel = resolveAgentDisplayLabel(msg.agentId);\n markThreadInvocationComplete(msg, options);\n\n // 任务完成通知(C#侧判断窗口状态)\n const notificationType = errorFallback ? 'error' : 'success';\n const notificationTitle = errorFallback ? `${agentLabel} 出错` : `${agentLabel} 完成`;\n const notificationBody = preview.slice(0, 80) + (preview.length > 80 ? '...' : '');\n options.notifyTaskComplete?.(notificationTitle, notificationBody, notificationType, msg.threadId);\n\n if (errorFallback) {\n const toast = getAgentErrorToastContent({\n agentId: msg.agentId,\n agentDisplayName: agentLabel,\n error: errorFallback.rawError,\n errorCode: msg.errorCode,\n });\n options.addToast({\n type: 'error',\n title: toast.title,\n message: preview || toast.message,\n threadId: msg.threadId,\n threadTitle: options.getThreadTitle?.(msg.threadId) ?? undefined,\n duration: 8000,\n });\n markBackgroundErrorToastShown(streamKey, options);\n return;\n }\n options.addToast({\n type: 'success',\n title: `${agentLabel} 完成`,\n message: preview.slice(0, 80) + (preview.length > 80 ? '...' : ''),\n threadId: msg.threadId,\n threadTitle: options.getThreadTitle?.(msg.threadId) ?? undefined,\n duration: 5000,\n });\n }\n return;\n }\n\n if (msg.type === 'error') {\n console.warn('[useSocket-background] Received raw error event in background:', {\n agentId: msg.agentId,\n threadId: msg.threadId,\n });\n\n markThreadInvocationActive(msg, options);\n stopTrackedStream(streamKey, msg, options);\n\n recordDebugEvent({\n event: 'agent_message',\n threadId: msg.threadId,\n timestamp: msg.timestamp,\n agentId: msg.agentId,\n invocationId: msg.invocationId,\n reason: msg.error ?? 'Unknown error',\n action: 'error_fallback_background_degradation',\n origin: msg.origin,\n });\n\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'error');\n\n if (msg.isFinal) {\n options.clearDoneTimeout?.(msg.threadId);\n markThreadInvocationComplete(msg, options);\n const agentLabel = resolveAgentDisplayLabel(msg.agentId);\n options.notifyTaskComplete?.(`${agentLabel} 出错`, msg.error ?? 'Unknown error', 'error', msg.threadId);\n }\n\n // Toast 通知(降级)\n const toast = getAgentErrorToastContent({\n ...msg,\n agentDisplayName: resolveAgentDisplayLabel(msg.agentId),\n });\n options.addToast({\n type: 'error',\n title: toast.title,\n message: toast.message,\n threadId: msg.threadId,\n threadTitle: options.getThreadTitle?.(msg.threadId) ?? undefined,\n duration: 8000,\n });\n markBackgroundErrorToastShown(streamKey, options);\n return;\n }\n\n if (msg.type === 'done') {\n stopTrackedStream(streamKey, msg, options);\n const currentStatus = options.store.getThreadState(msg.threadId).agentStatuses[msg.agentId];\n const latestAssistantMessage = options.store\n .getThreadState(msg.threadId)\n .messages.filter((m) => m.type === 'assistant' && m.agentId === msg.agentId)\n .at(-1);\n const messageErrorFallback = latestAssistantMessage?.extra?.errorFallback;\n const agentLabel = resolveAgentDisplayLabel(msg.agentId);\n\n if (String(currentStatus) === 'error' || messageErrorFallback) {\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'error');\n options.notifyTaskComplete?.(\n `${agentLabel} 出错`,\n latestAssistantMessage?.content ?? 'Unknown error',\n 'error',\n msg.threadId,\n );\n if (String(currentStatus) !== 'error' && messageErrorFallback && !hasShownBackgroundErrorToast(streamKey, options)) {\n const toast = getAgentErrorToastContent({\n agentId: msg.agentId,\n agentDisplayName: agentLabel,\n error: messageErrorFallback.rawError,\n errorCode: msg.errorCode,\n });\n options.addToast({\n type: 'error',\n title: toast.title,\n message: latestAssistantMessage?.content || toast.message,\n threadId: msg.threadId,\n threadTitle: options.getThreadTitle?.(msg.threadId) ?? undefined,\n duration: 8000,\n });\n markBackgroundErrorToastShown(streamKey, options);\n }\n options.backgroundErrorToastsShown.delete(streamKey);\n if (msg.isFinal) {\n options.clearDoneTimeout?.(msg.threadId);\n markThreadInvocationComplete(msg, options);\n }\n return;\n }\n if (String(currentStatus) !== 'error') {\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'done');\n options.notifyTaskComplete?.(`${agentLabel} 完成`, `${agentLabel} 已完成处理`, 'success', msg.threadId);\n options.addToast({\n type: 'success',\n title: `${agentLabel} 完成`,\n message: `${agentLabel} 已完成处理`,\n threadId: msg.threadId,\n threadTitle: options.getThreadTitle?.(msg.threadId) ?? undefined,\n duration: 5000,\n });\n }\n options.backgroundErrorToastsShown.delete(streamKey);\n if (msg.isFinal) {\n options.clearDoneTimeout?.(msg.threadId);\n markThreadInvocationComplete(msg, options);\n }\n return;\n }\n\n if (msg.type === 'status') {\n const mapped = STATUS_MAP[msg.content ?? ''] ?? 'streaming';\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, mapped);\n return;\n }\n\n if (msg.type === 'tool_use') {\n markThreadInvocationActive(msg, options);\n const toolName = msg.toolName ?? 'unknown';\n const detail = toolUseDetail(toolName, msg.toolInput);\n const messageId = ensureBackgroundAssistantMessage(msg, streamKey, existing, options);\n options.store.appendToolEventToThread(msg.threadId, messageId, {\n id: msg.toolCallId ?? `bg-tool-use-${msg.timestamp}-${options.nextBgSeq()}`,\n type: 'tool_use',\n label: `${msg.agentId} → ${toolName}`,\n ...(detail ? { detail } : {}),\n ...(msg.toolCallId ? { toolCallId: msg.toolCallId } : {}),\n timestamp: msg.timestamp,\n });\n options.store.setThreadMessageStreaming(msg.threadId, messageId, true);\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'streaming');\n return;\n }\n\n if (msg.type === 'tool_result') {\n markThreadInvocationActive(msg, options);\n const messageId = ensureBackgroundAssistantMessage(msg, streamKey, existing, options);\n options.store.appendToolEventToThread(msg.threadId, messageId, {\n id: msg.toolCallId ?? `bg-tool-result-${msg.timestamp}-${options.nextBgSeq()}`,\n type: 'tool_result',\n label: `${msg.agentId} ← result`,\n detail: msg.content ?? '',\n ...(msg.toolCallId ? { toolCallId: msg.toolCallId } : {}),\n timestamp: msg.timestamp,\n });\n options.store.setThreadMessageStreaming(msg.threadId, messageId, true);\n options.store.updateThreadAgentStatus(msg.threadId, msg.agentId, 'streaming');\n return;\n }\n\n if (msg.type === 'system_info') {\n if (!msg.content) return;\n\n const result = consumeBackgroundSystemInfo(msg, existing, options);\n if (!result.consumed) {\n addBackgroundSystemMessage(msg, options, result.content, result.variant);\n }\n }\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nfunction joinedRoomsPrimaryKey(userId: string): string {\n const normalizedUserId = userId.trim() || 'anonymous';\n return `office-claw:ws:joined-rooms:v1:${normalizedUserId}`;\n}\n\nfunction joinedRoomsLegacyKey(userId: string): string {\n const normalizedUserId = userId.trim() || 'anonymous';\n return `cat-cafe:ws:joined-rooms:v1:${normalizedUserId}`;\n}\n\nfunction isThreadRoom(room: unknown): room is string {\n return typeof room === 'string' && room.startsWith('thread:');\n}\n\nexport function loadJoinedRoomsFromSession(userId: string): Set<string> {\n if (typeof window === 'undefined') return new Set();\n const primary = joinedRoomsPrimaryKey(userId);\n const legacy = joinedRoomsLegacyKey(userId);\n let raw = window.sessionStorage.getItem(primary);\n if (!raw) raw = window.sessionStorage.getItem(legacy);\n if (!raw) return new Set();\n\n try {\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return new Set();\n const rooms = new Set(parsed.filter(isThreadRoom));\n if (window.sessionStorage.getItem(primary) === null && window.sessionStorage.getItem(legacy) !== null) {\n try {\n window.sessionStorage.setItem(primary, JSON.stringify([...rooms]));\n window.sessionStorage.removeItem(legacy);\n } catch {\n /* ignore */\n }\n }\n return rooms;\n } catch (error) {\n console.warn('[ws] Failed to parse persisted rooms, resetting cache', { error });\n try {\n window.sessionStorage.removeItem(primary);\n window.sessionStorage.removeItem(legacy);\n } catch {\n /* ignore */\n }\n return new Set();\n }\n}\n\nexport function saveJoinedRoomsToSession(userId: string, rooms: Set<string>): void {\n if (typeof window === 'undefined') return;\n const primary = joinedRoomsPrimaryKey(userId);\n const legacy = joinedRoomsLegacyKey(userId);\n try {\n window.sessionStorage.setItem(primary, JSON.stringify([...rooms]));\n try {\n window.sessionStorage.removeItem(legacy);\n } catch {\n /* ignore */\n }\n } catch {\n /* ignore */\n }\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\nimport type { VoiceChunkEvent, VoiceStreamEndEvent, VoiceStreamStartEvent } from '@hualinge/relay-shared';\n\nexport type PlaybackManagerState = 'idle' | 'playing' | 'paused';\n\nexport interface PlaybackManagerCallbacks {\n onStateChange: (state: PlaybackManagerState) => void;\n /** Called each time a queued item finishes, with the 0-based index of the completed item within a batch. */\n onItemEnd?: (index: number) => void;\n}\n\nlet domAudio: HTMLAudioElement | null = null;\n\nfunction getDomAudio(): HTMLAudioElement {\n if (domAudio) return domAudio;\n const el = document.createElement('audio');\n el.id = 'voice-stream-audio';\n el.style.display = 'none';\n el.preload = 'auto';\n document.body.appendChild(el);\n domAudio = el;\n return el;\n}\n\nexport class PlaybackManager {\n private queue: string[] = [];\n private blobUrls: string[] = [];\n private state: PlaybackManagerState = 'idle';\n private activeInvocationId: string | null = null;\n private streamDone = false;\n private firstChunkPlayed = false;\n private callbacks: PlaybackManagerCallbacks;\n /** Track completed items within a batch (for podcast progress tracking). */\n private batchItemIndex = 0;\n private batchMode = false;\n /** Monotonically increasing ID to invalidate in-flight fetches after interrupt/new batch. */\n private batchId = 0;\n\n constructor(callbacks: PlaybackManagerCallbacks) {\n this.callbacks = callbacks;\n }\n\n handleStreamStart(event: VoiceStreamStartEvent): void {\n if (this.activeInvocationId && this.activeInvocationId !== event.invocationId) {\n this.interrupt();\n }\n this.activeInvocationId = event.invocationId;\n this.streamDone = false;\n this.firstChunkPlayed = false;\n this.batchMode = false;\n }\n\n handleChunk(event: VoiceChunkEvent): void {\n if (event.invocationId !== this.activeInvocationId) return;\n\n const mimeType = event.format === 'mp3' ? 'audio/mpeg' : 'audio/wav';\n const binary = atob(event.audioBase64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: mimeType });\n const blobUrl = URL.createObjectURL(blob);\n this.blobUrls.push(blobUrl);\n\n if (!this.firstChunkPlayed && this.state !== 'paused') {\n this.firstChunkPlayed = true;\n this.playUrl(blobUrl);\n } else if (this.state === 'idle') {\n this.playUrl(blobUrl);\n } else {\n this.queue.push(blobUrl);\n const audio = getDomAudio();\n if (audio.ended && this.state === 'playing') {\n this.playNext();\n }\n }\n }\n\n handleStreamEnd(event: VoiceStreamEndEvent): void {\n if (event.invocationId !== this.activeInvocationId) return;\n this.streamDone = true;\n\n if (event.totalChunks === -1) {\n this.interrupt();\n return;\n }\n\n const audio = getDomAudio();\n if (this.queue.length === 0 && (!this.firstChunkPlayed || audio.ended)) {\n this.setState('idle');\n }\n }\n\n /**\n * Enqueue a remote audio URL for playback (e.g. podcast segment).\n * Fetches the URL, creates a blob URL, and adds to the playback queue.\n * The returned promise resolves when the URL is fetched and enqueued (not when playback finishes).\n * @param fetchFn - Fetch function that returns a Response (allows passing auth-aware fetchers like apiFetch).\n */\n async enqueueUrl(url: string, fetchFn: (url: string) => Promise<Response> = fetch): Promise<void> {\n const capturedBatchId = this.batchId;\n let res: Response;\n try {\n res = await fetchFn(url);\n } catch (err) {\n console.error('[PlaybackManager] enqueueUrl fetch rejected:', err);\n return;\n }\n if (this.batchId !== capturedBatchId) return;\n if (!res.ok) {\n console.error(`[PlaybackManager] enqueueUrl fetch failed: ${res.status}`);\n return;\n }\n let blob: Blob;\n try {\n blob = await res.blob();\n } catch (err) {\n console.error('[PlaybackManager] enqueueUrl blob() rejected:', err);\n return;\n }\n if (this.batchId !== capturedBatchId) return;\n const blobUrl = URL.createObjectURL(blob);\n this.blobUrls.push(blobUrl);\n\n const audio = getDomAudio();\n if (this.state === 'idle' || (this.state === 'playing' && audio.ended)) {\n this.playUrl(blobUrl);\n } else {\n this.queue.push(blobUrl);\n }\n }\n\n /**\n * Start a batch playback session (e.g. podcast \"play all\").\n * Interrupts any ongoing playback, enters batch mode, then enqueues URLs sequentially.\n * @param urls - Audio URLs to play in order.\n * @param fetchFn - Auth-aware fetch function.\n * @returns A promise that resolves when all URLs are enqueued (playback may still be ongoing).\n */\n async startBatch(urls: string[], fetchFn: (url: string) => Promise<Response> = fetch): Promise<void> {\n this.interrupt();\n this.batchId++;\n const capturedBatchId = this.batchId;\n this.batchMode = true;\n this.batchItemIndex = 0;\n this.streamDone = false;\n for (const url of urls) {\n if (this.batchId !== capturedBatchId) return;\n await this.enqueueUrl(url, fetchFn);\n }\n if (this.batchId !== capturedBatchId) return;\n this.streamDone = true;\n const audio = getDomAudio();\n if (this.queue.length === 0 && audio.ended && this.state === 'playing') {\n this.setState('idle');\n }\n }\n\n /** Whether a batch playback is currently active. */\n isBatchActive(): boolean {\n return this.batchMode && this.state !== 'idle';\n }\n\n /** Register a temporary onItemEnd callback (returns unsubscribe fn). */\n onItemEnd(fn: (index: number) => void): () => void {\n const prev = this.callbacks.onItemEnd;\n this.callbacks.onItemEnd = (index: number) => {\n prev?.(index);\n fn(index);\n };\n return () => {\n this.callbacks.onItemEnd = prev;\n };\n }\n\n /** Register a temporary onStateChange wrapper (returns unsubscribe fn). */\n onStateIdle(fn: () => void): () => void {\n const orig = this.callbacks.onStateChange;\n this.callbacks.onStateChange = (state) => {\n orig(state);\n if (state === 'idle') fn();\n };\n return () => {\n this.callbacks.onStateChange = orig;\n };\n }\n\n /** Mark the current queue as complete (no more items will be enqueued). */\n markDone(): void {\n this.streamDone = true;\n }\n\n pause(): void {\n if (this.state !== 'playing') return;\n const audio = getDomAudio();\n audio.pause();\n this.setState('paused');\n }\n\n resume(): void {\n if (this.state !== 'paused') return;\n const audio = getDomAudio();\n if (audio.src) {\n audio.play().catch(() => this.setState('idle'));\n this.setState('playing');\n } else if (this.queue.length > 0) {\n this.playNext();\n } else {\n this.setState('idle');\n }\n }\n\n skip(): void {\n const audio = getDomAudio();\n audio.pause();\n audio.removeAttribute('src');\n audio.onended = null;\n if (this.queue.length > 0) {\n this.playNext();\n } else if (this.streamDone) {\n this.setState('idle');\n } else {\n // Stream still going, no next chunk yet — enter idle to wait.\n // handleChunk() will auto-resume when a new chunk arrives.\n this.setState('idle');\n }\n }\n\n interrupt(): void {\n this.batchId++;\n const audio = getDomAudio();\n audio.pause();\n audio.removeAttribute('src');\n audio.onended = null;\n audio.onerror = null;\n this.queue = [];\n this.cleanupBlobUrls();\n this.activeInvocationId = null;\n this.streamDone = false;\n this.firstChunkPlayed = false;\n this.batchMode = false;\n this.batchItemIndex = 0;\n this.setState('idle');\n }\n\n destroy(): void {\n this.interrupt();\n }\n\n getState(): PlaybackManagerState {\n return this.state;\n }\n\n getActiveInvocationId(): string | null {\n return this.activeInvocationId;\n }\n\n private playUrl(url: string): void {\n const audio = getDomAudio();\n audio.src = url;\n audio.onended = () => {\n if (this.batchMode) {\n this.callbacks.onItemEnd?.(this.batchItemIndex);\n this.batchItemIndex++;\n }\n this.playNext();\n };\n audio.onerror = () => {\n console.error('[PlaybackManager] Audio playback error');\n if (this.batchMode) {\n this.batchItemIndex++;\n }\n this.playNext();\n };\n this.setState('playing');\n audio.play().catch(() => {\n console.error('[PlaybackManager] play() rejected');\n this.setState('idle');\n });\n }\n\n private playNext(): void {\n const next = this.queue.shift();\n if (next) {\n this.playUrl(next);\n } else if (this.streamDone) {\n if (this.batchMode) {\n this.batchMode = false;\n this.batchItemIndex = 0;\n }\n this.setState('idle');\n }\n }\n\n private setState(newState: PlaybackManagerState): void {\n if (this.state === newState) return;\n this.state = newState;\n this.callbacks.onStateChange(newState);\n }\n\n private cleanupBlobUrls(): void {\n for (const url of this.blobUrls) {\n URL.revokeObjectURL(url);\n }\n this.blobUrls = [];\n }\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { create } from 'zustand';\nimport { apiFetch } from '@/utils/api-client';\n\n/**\n * F092: Voice Companion Session — manages voice mode state.\n *\n * VoiceSession is ephemeral (memory only, no persistence).\n * Closing the page ends the session.\n *\n * P0 scope: one thread, one cat, auto-play, PTT.\n */\n\nexport type PlaybackState = 'idle' | 'playing' | 'paused';\n\nexport interface VoiceSession {\n sessionId: string;\n boundThreadId: string;\n activeCatId: string;\n voiceMode: boolean;\n /** Whether user gesture has unlocked browser autoplay */\n autoplayUnlocked: boolean;\n playbackState: PlaybackState;\n /** Track which audio block IDs have been auto-played (avoid replays on re-render) */\n playedBlockIds: Set<string>;\n /** True when a live voice stream is active (suppresses fallback auto-play) */\n liveStreamActive: boolean;\n /** Invocation IDs that had live streaming (their audio blocks skip fallback) */\n liveStreamedInvocationIds: Set<string>;\n}\n\n/** Fire-and-forget: notify backend about voice mode toggle for prompt injection. */\nfunction syncVoiceModeToBackend(threadId: string, voiceMode: boolean): void {\n apiFetch(`/api/threads/${threadId}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ voiceMode }),\n }).catch(() => {\n // Best-effort — voice mode prompt injection is non-critical path\n });\n}\n\ninterface VoiceSessionActions {\n session: VoiceSession | null;\n start: (threadId: string, agentId: string, autoplayUnlocked: boolean) => void;\n stop: () => void;\n setPlaybackState: (state: PlaybackState) => void;\n confirmAutoplayUnlocked: () => void;\n markPlayed: (blockId: string) => void;\n hasPlayed: (blockId: string) => boolean;\n setLiveStreamActive: (active: boolean, invocationId?: string) => void;\n isLiveStreamedInvocation: (invocationId: string) => boolean;\n /**\n * F112-C: Register a stop callback so VAD can interrupt any active playback path.\n * Both PlaybackManager (live stream) and useVoiceAutoPlay (fallback) register here.\n * Returns an unregister function.\n */\n registerStopCallback: (id: string, fn: () => void) => () => void;\n /** F112-C: Invoke all registered stop callbacks (called by VAD on speech detection). */\n stopAllAudio: () => void;\n}\n\nlet sessionCounter = 0;\nconst stopCallbacks = new Map<string, () => void>();\n\nexport const useVoiceSessionStore = create<VoiceSessionActions>((set, get) => ({\n session: null,\n\n start: (threadId, agentId, autoplayUnlocked) => {\n sessionCounter++;\n set({\n session: {\n sessionId: `vs-${Date.now()}-${sessionCounter}`,\n boundThreadId: threadId,\n activeCatId: agentId,\n voiceMode: true,\n autoplayUnlocked,\n playbackState: 'idle',\n playedBlockIds: new Set(),\n liveStreamActive: false,\n liveStreamedInvocationIds: new Set(),\n },\n });\n syncVoiceModeToBackend(threadId, true);\n },\n\n stop: () => {\n const { session } = get();\n set({ session: null });\n if (session?.boundThreadId) {\n syncVoiceModeToBackend(session.boundThreadId, false);\n }\n },\n\n confirmAutoplayUnlocked: () => {\n const { session } = get();\n if (!session) return;\n set({ session: { ...session, autoplayUnlocked: true } });\n },\n\n setPlaybackState: (playbackState) => {\n const { session } = get();\n if (!session) return;\n set({ session: { ...session, playbackState } });\n },\n\n markPlayed: (blockId) => {\n const { session } = get();\n if (!session) return;\n const next = new Set(session.playedBlockIds);\n next.add(blockId);\n set({ session: { ...session, playedBlockIds: next } });\n },\n\n hasPlayed: (blockId) => {\n const { session } = get();\n return session?.playedBlockIds.has(blockId) ?? false;\n },\n\n setLiveStreamActive: (active, invocationId) => {\n const { session } = get();\n if (!session) return;\n const nextIds = new Set(session.liveStreamedInvocationIds);\n if (active && invocationId) {\n nextIds.add(invocationId);\n }\n set({ session: { ...session, liveStreamActive: active, liveStreamedInvocationIds: nextIds } });\n },\n\n isLiveStreamedInvocation: (invocationId) => {\n const { session } = get();\n return session?.liveStreamedInvocationIds.has(invocationId) ?? false;\n },\n\n registerStopCallback: (id, fn) => {\n stopCallbacks.set(id, fn);\n return () => {\n stopCallbacks.delete(id);\n };\n },\n\n stopAllAudio: () => {\n for (const fn of stopCallbacks.values()) {\n fn();\n }\n },\n}));\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport type { VoiceChunkEvent, VoiceStreamEndEvent, VoiceStreamStartEvent } from '@hualinge/relay-shared';\nimport { useCallback, useEffect } from 'react';\nimport { PlaybackManager } from '@/services/PlaybackManager';\nimport { useVoiceSessionStore } from '@/stores/voiceSessionStore';\n\nlet managerInstance: PlaybackManager | null = null;\n\nfunction getOrCreateManager(): PlaybackManager {\n if (managerInstance) return managerInstance;\n managerInstance = new PlaybackManager({\n onStateChange: (state) => {\n const voiceStore = useVoiceSessionStore.getState();\n if (state === 'idle') {\n voiceStore.setPlaybackState('idle');\n } else if (state === 'playing') {\n voiceStore.setPlaybackState('playing');\n } else if (state === 'paused') {\n voiceStore.setPlaybackState('paused');\n }\n },\n });\n useVoiceSessionStore.getState().registerStopCallback('playback-manager', () => {\n managerInstance?.interrupt();\n });\n return managerInstance;\n}\n\n/** Get the shared PlaybackManager instance (creates if needed). Usable outside React. */\nexport function getPlaybackManager(): PlaybackManager {\n return getOrCreateManager();\n}\n\nfunction matchesActiveSession(event: { threadId: string; agentId: string }): boolean {\n const { session } = useVoiceSessionStore.getState();\n if (!session?.voiceMode) return false;\n if (session.boundThreadId !== event.threadId) return false;\n if (session.activeCatId !== event.agentId) return false;\n return true;\n}\n\nexport function handleVoiceStreamStart(event: VoiceStreamStartEvent): void {\n if (!matchesActiveSession(event)) return;\n useVoiceSessionStore.getState().setLiveStreamActive(true, event.invocationId);\n getOrCreateManager().handleStreamStart(event);\n}\n\nexport function handleVoiceChunk(event: VoiceChunkEvent): void {\n if (!matchesActiveSession(event)) return;\n const manager = getOrCreateManager();\n manager.handleChunk(event);\n useVoiceSessionStore.getState().confirmAutoplayUnlocked();\n}\n\nexport function handleVoiceStreamEnd(event: VoiceStreamEndEvent): void {\n if (!matchesActiveSession(event)) return;\n getOrCreateManager().handleStreamEnd(event);\n useVoiceSessionStore.getState().setLiveStreamActive(false);\n}\n\nexport function useVoiceStream(): {\n pause: () => void;\n resume: () => void;\n skip: () => void;\n} {\n const session = useVoiceSessionStore((s) => s.session);\n\n useEffect(() => {\n if (!session?.voiceMode) {\n managerInstance?.interrupt();\n }\n return () => {\n managerInstance?.destroy();\n managerInstance = null;\n };\n }, [session?.voiceMode]);\n\n const pause = useCallback(() => managerInstance?.pause(), []);\n const resume = useCallback(() => managerInstance?.resume(), []);\n const skip = useCallback(() => managerInstance?.skip(), []);\n\n return { pause, resume, skip };\n}\n","/*\n * *\n * * Copyright (C) Huawei Technologies Co., Ltd. 2026. All rights reserved.\n *\n */\n\n'use client';\n\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { io, Socket } from 'socket.io-client';\nimport {\n bootstrapDebugFromStorage,\n ensureWindowDebugApi,\n isDebugEnabled,\n recordDebugEvent,\n} from '@/debug/invocationEventDebug';\nimport { useAuthorizationPendingStore } from '@/stores/authorizationPendingStore';\nimport type { PendingAskUserQuestion } from '@/stores/chat-types';\nimport { useChatStore } from '@/stores/chatStore';\nimport { useToastStore } from '@/stores/toastStore';\nimport { API_URL, apiFetch } from '@/utils/api-client';\nimport { notifyOnTaskComplete, notifyToolApprovalRequest } from '@/utils/desktop-notification';\nimport { notifySkillOptionsChanged } from '@/utils/skill-options-cache';\nimport { getUserId } from '@/utils/userId';\nimport { requestThreadLiveRefresh } from './thread-live-refresh';\nimport {\n type BackgroundAgentMessage,\n clearBackgroundStreamRefForActiveEvent,\n handleBackgroundAgentMessage,\n} from './useSocket-background';\nimport { loadJoinedRoomsFromSession, saveJoinedRoomsToSession } from './useSocket-persistence';\nimport { handleVoiceChunk, handleVoiceStreamEnd, handleVoiceStreamStart } from './useVoiceStream';\n\ninterface AgentMessage {\n type: string;\n agentId: string;\n threadId?: string;\n content?: string;\n sessionId?: string;\n toolName?: string;\n toolInput?: Record<string, unknown>;\n error?: string;\n errorCode?: string;\n isFinal?: boolean;\n metadata?: { provider: string; model: string; sessionId?: string; usage?: import('../stores/chat-types').TokenUsage };\n /** Message origin: stream = CLI stdout (thinking), callback = MCP post_message (speech) */\n origin?: 'stream' | 'callback';\n /** F121: ID of the message this message is replying to */\n replyTo?: string;\n /** F121: Hydrated preview of the replied-to message */\n replyPreview?: { senderAgentId: string | null; content: string; deleted?: true };\n /** F108: Invocation ID — distinguishes messages from concurrent invocations */\n invocationId?: string;\n timestamp: number;\n taskContext?: { id: string; title?: string; index?: number; total?: number };\n taskPhase?: 'start' | 'complete';\n}\n\ninterface ConnectorMessageEvent {\n threadId: string;\n message: {\n id: string;\n type: 'connector';\n content: string;\n source?: import('../stores/chat-types').ConnectorSourceData;\n extra?: Record<string, unknown>;\n timestamp: number;\n };\n}\n\nconst USER_CHANNEL_CONNECTORS = new Set(['weixin', 'xiaoyi', 'feishu', 'dingtalk']);\n\nfunction isUserChannelConnector(connectorId?: string): boolean {\n return typeof connectorId === 'string' && USER_CHANNEL_CONNECTORS.has(connectorId);\n}\n\nfunction readStringField(value: unknown): string | null {\n return typeof value === 'string' ? value : null;\n}\n\nfunction registerAndNotifyAuthorizationRequest(data: Record<string, unknown>): void {\n const requestId = readStringField(data.requestId);\n const threadId = readStringField(data.threadId);\n if (!requestId || !threadId) return;\n\n useAuthorizationPendingStore.getState().registerPending(threadId, requestId);\n notifyToolApprovalRequest({\n requestId,\n threadId,\n catId: readStringField(data.agentId) ?? readStringField(data.catId) ?? '智能体',\n action: readStringField(data.action) ?? '工具调用',\n reason: readStringField(data.reason) ?? '需要你的审批',\n });\n}\n\ninterface SocketIoTransportLike {\n name?: string;\n ws?: WebSocket;\n}\n\ninterface SocketIoEngineLike {\n transport?: SocketIoTransportLike;\n on: (event: string, listener: (...args: unknown[]) => void) => void;\n}\n\ntype DebugWebSocket = WebSocket & { __catCafeCloseLoggerAttached?: boolean };\ntype JoinRoomAwaitStatus = 'joined' | 'timed_out' | 'socket_unavailable';\n\nconst ROOM_JOIN_ACK_TIMEOUT_MS = 500;\nconst ROOM_JOIN_POLL_INTERVAL_MS = 25;\nconst ROOM_JOIN_SETTLE_MS = 80;\nconst MISSING_THREAD_ID_RECOVERY_THROTTLE_MS = 1200;\nconst MISSING_THREAD_ID_BUFFER_TIMEOUT_MS = 700;\n\nexport interface SocketCallbacks {\n onMessage: (msg: AgentMessage) => void;\n onThreadCreated?: (data: { threadId: string; source?: string }) => void;\n onThreadUpdated?: (data: { threadId: string; title: string }) => void;\n onIntentMode?: (data: { threadId: string; mode: string; targetAgents: string[] }) => void;\n onTaskCreated?: (task: Record<string, unknown>) => void;\n onTaskUpdated?: (task: Record<string, unknown>) => void;\n onHeartbeat?: (data: { threadId: string; timestamp: number }) => void;\n onMessageDeleted?: (data: { messageId: string; threadId: string; deletedBy: string }) => void;\n onMessageRestored?: (data: { messageId: string; threadId: string }) => void;\n onThreadBranched?: (data: { sourceThreadId: string; newThreadId: string; fromMessageId: string }) => void;\n onAuthorizationRequest?: (data: {\n requestId: string;\n agentId: string;\n threadId: string;\n action: string;\n reason: string;\n context?: string;\n createdAt: number;\n }) => void;\n onAuthorizationResponse?: (data: { requestId: string; status: string; scope?: string; reason?: string }) => void;\n onAskUserQuestionRequest?: (data: PendingAskUserQuestion) => void;\n onAskUserQuestionResponse?: (data: { requestId: string; status: string }) => void;\n /** F101: Game state update */\n onGameStateUpdate?: (data: { gameId: string; view: unknown; timestamp: number }) => void;\n /** F101 Phase D: Independent game thread created */\n onGameThreadCreated?: (data: {\n gameThreadId: string;\n gameTitle: string;\n initiatorUserId: string;\n timestamp: number;\n }) => void;\n /** #80 fix-C: Clear the done-timeout guard (called when background thread completes) */\n clearDoneTimeout?: (threadId?: string) => void;\n /** F39: Queue updated */\n onQueueUpdated?: (data: {\n threadId: string;\n queue: import('../stores/chat-types').QueueEntry[];\n action: string;\n }) => void;\n /** F39: Queue paused */\n onQueuePaused?: (data: {\n threadId: string;\n reason: 'canceled' | 'failed';\n queue: import('../stores/chat-types').QueueEntry[];\n }) => void;\n}\n\nconst RECONNECT_RECONCILE_DELAY_MS = 2000;\n\n/** Generation counter: each reconnect increments, stale callbacks discard themselves. */\nlet reconcileGeneration = 0;\n\n/**\n * After socket reconnect, bidirectionally reconcile invocation state with server.\n * Socket disconnect can lose done(isFinal) events (UI stuck in \"replying\") or\n * cause local state to drift from server truth. Fetches the queue endpoint and:\n * - Server has active cats → re-hydrate local slots to match (fixes ID mismatches)\n * - Server has no active cats → clear stale local invocation state\n */\nfunction reconcileInvocationStateOnReconnect(activeThreadId: string | null): void {\n const generation = ++reconcileGeneration;\n const state = useChatStore.getState();\n\n // Collect threads to reconcile: always check the active thread (server might\n // still be processing even if local cleared state during disconnect), plus\n // any background threads that look busy (active invocation) or still have a\n // stuck streaming assistant bubble (isStreaming) — the latter can happen when\n // e.g. the client missed a terminal error on reconnect and hasActiveInvocation\n // is already false.\n const threadsToCheckSet = new Set<string>();\n if (activeThreadId) {\n threadsToCheckSet.add(activeThreadId);\n }\n for (const [threadId, ts] of Object.entries(state.threadStates ?? {})) {\n if (threadId === activeThreadId) continue;\n if (ts.hasActiveInvocation) {\n threadsToCheckSet.add(threadId);\n } else if (ts.messages?.some((m) => m.type === 'assistant' && m.isStreaming)) {\n threadsToCheckSet.add(threadId);\n }\n }\n const threadsToCheck = [...threadsToCheckSet];\n if (threadsToCheck.length === 0) return;\n\n // Small delay: let any buffered socket events arrive first\n setTimeout(async () => {\n // Discard if a newer reconnect has started its own reconciliation\n if (generation !== reconcileGeneration) return;\n for (const threadId of threadsToCheck) {\n if (generation !== reconcileGeneration) return;\n try {\n const res = await apiFetch(`/api/threads/${threadId}/queue`);\n if (generation !== reconcileGeneration) return; // stale after await\n if (!res.ok) continue;\n const data = (await res.json()) as {\n activeInvocations?: string[];\n queue?: import('../stores/chat-types').QueueEntry[];\n paused?: boolean;\n pauseReason?: 'canceled' | 'failed';\n };\n if (generation !== reconcileGeneration) return; // stale after await\n const store = useChatStore.getState();\n const serverActiveAgentIds =\n data.activeInvocations && data.activeInvocations.length > 0 ? data.activeInvocations : null;\n const isActiveThread = store.currentThreadId === threadId;\n\n if (serverActiveAgentIds) {\n // Server still processing — re-hydrate local slots to match server truth.\n // Stale hydrated/mismatched invocationIds get replaced so done(isFinal)\n // cleanup works correctly when the response finishes.\n store.clearThreadActiveInvocation(threadId);\n store.replaceThreadTargetAgents(threadId, serverActiveAgentIds);\n for (const agentId of serverActiveAgentIds) {\n store.updateThreadAgentStatus(threadId, agentId, 'streaming');\n const syntheticId = `hydrated-${threadId}-${agentId}`;\n if (isActiveThread) {\n store.addActiveInvocation(syntheticId, agentId, 'execute');\n } else {\n store.addThreadActiveInvocation(threadId, syntheticId, agentId, 'execute');\n }\n }\n console.log('[ws] Reconnect reconciliation: re-hydrated active slots from server', {\n threadId,\n agentIds: serverActiveAgentIds,\n });\n // Also sync queue state from server\n if (data.queue !== undefined) {\n store.setQueue(threadId, data.queue);\n if (data.paused !== undefined) {\n store.setQueuePaused(threadId, data.paused, data.pauseReason);\n }\n }\n continue;\n }\n\n if (isActiveThread) {\n const hadStuckStreamBubble = store.messages.some((m) => m.type === 'assistant' && m.isStreaming);\n if (store.hasActiveInvocation) {\n store.clearAllActiveInvocations();\n store.setLoading(false);\n store.setIntentMode(null);\n store.clearAgentStatuses();\n console.log('[ws] Reconnect reconciliation: cleared stale active-thread invocation state', { threadId });\n } else if (hadStuckStreamBubble) {\n store.clearAgentStatuses();\n console.log('[ws] Reconnect reconciliation: finalized stuck stream bubbles (server idle)', { threadId });\n }\n for (const msg of store.messages) {\n if (msg.type === 'assistant' && msg.isStreaming) {\n store.setStreaming(msg.id, false);\n }\n }\n // Sync queue state from server even when idle\n if (data.queue !== undefined) {\n store.setQueue(threadId, data.queue);\n if (data.paused !== undefined) {\n store.setQueuePaused(threadId, data.paused, data.pauseReason);\n }\n }\n } else {\n const ts = store.getThreadState(threadId);\n const hadStuckStreamBubble = ts.messages.some((m) => m.type === 'assistant' && m.isStreaming);\n if (ts.hasActiveInvocation) {\n store.clearThreadActiveInvocation(threadId);\n store.setThreadLoading(threadId, false);\n console.log('[ws] Reconnect reconciliation: cleared stale background-thread invocation state', {\n threadId,\n });\n } else if (hadStuckStreamBubble) {\n console.log('[ws] Reconnect reconciliation: finalized stuck background stream bubbles (server idle)', {\n threadId,\n });\n }\n for (const msg of ts.messages) {\n if (msg.type === 'assistant' && msg.isStreaming) {\n store.setThreadMessageStreaming(threadId, msg.id, false);\n }\n }\n }\n } catch {\n // Non-critical — don't break reconnect flow\n }\n }\n }, RECONNECT_RECONCILE_DELAY_MS);\n}\n\nexport function useSocket(callbacks: SocketCallbacks, threadId?: string, watchedThreadIds: string[] = []) {\n const socketRef = useRef<Socket | null>(null);\n const joinedRoomsRef = useRef<Set<string>>(new Set());\n const bgStreamRefsRef = useRef<Map<string, { id: string; threadId: string; agentId: string }>>(new Map());\n const bgReplacedInvocationsRef = useRef<Map<string, string>>(new Map());\n const bgErrorToastsShownRef = useRef<Set<string>>(new Set());\n const bgFinalizedRefsRef = useRef<Map<string, string>>(new Map());\n const bgSeqRef = useRef(0);\n const userIdRef = useRef(getUserId());\n const threadIdRef = useRef(threadId);\n const missingThreadRecoveryAtRef = useRef<Map<string, number>>(new Map());\n const invocationThreadMapRef = useRef<Map<string, string>>(new Map());\n const missingThreadBufferRef = useRef<Map<string, AgentMessage[]>>(new Map());\n const missingThreadBufferTimerRef = useRef<Map<string, ReturnType<typeof setTimeout>>>(new Map());\n const queueAutoContinueInFlightRef = useRef<Set<string>>(new Set());\n const callbacksRef = useRef(callbacks);\n callbacksRef.current = callbacks;\n\n const persistJoinedRooms = useCallback(() => {\n saveJoinedRoomsToSession(userIdRef.current, joinedRoomsRef.current);\n }, []);\n\n const normalizedWatchedThreadIds = useMemo(() => {\n const seen = new Set<string>();\n const ids: string[] = [];\n for (const rawId of watchedThreadIds) {\n if (typeof rawId !== 'string') continue;\n const id = rawId.trim();\n if (!id || seen.has(id)) continue;\n seen.add(id);\n ids.push(id);\n }\n return ids;\n }, [watchedThreadIds]);\n\n threadIdRef.current = threadId;\n\n useEffect(() => {\n userIdRef.current = getUserId();\n joinedRoomsRef.current = loadJoinedRoomsFromSession(userIdRef.current);\n if (threadIdRef.current) {\n joinedRoomsRef.current.add(`thread:${threadIdRef.current}`);\n }\n persistJoinedRooms();\n bootstrapDebugFromStorage();\n ensureWindowDebugApi();\n\n const recordInvocationEvent = (event: Parameters<typeof recordDebugEvent>[0]) => {\n if (!isDebugEnabled()) return;\n const store = useChatStore.getState();\n const traceThreadId = event.threadId;\n const threadState = traceThreadId ? store.getThreadState(traceThreadId) : null;\n recordDebugEvent({\n ...event,\n timestamp: event.timestamp ?? Date.now(),\n routeThreadId: event.routeThreadId ?? threadIdRef.current,\n storeThreadId: event.storeThreadId ?? store.currentThreadId,\n queuePaused: event.queuePaused ?? threadState?.queuePaused,\n hasActiveInvocation: event.hasActiveInvocation ?? threadState?.hasActiveInvocation,\n });\n };\n\n const socket = io(API_URL, {\n transports: ['websocket', 'polling'],\n auth: {\n userId: userIdRef.current,\n },\n });\n\n const getTransportName = () => {\n const engine = socket.io.engine as unknown as SocketIoEngineLike | undefined;\n return engine?.transport?.name ?? 'unknown';\n };\n\n const attachNativeCloseLogger = () => {\n const engine = socket.io.engine as unknown as SocketIoEngineLike | undefined;\n const transport = engine?.transport;\n if (!transport || transport.name !== 'websocket' || !transport.ws) return;\n const ws = transport.ws as DebugWebSocket;\n if (ws.__catCafeCloseLoggerAttached) return;\n ws.__catCafeCloseLoggerAttached = true;\n ws.addEventListener('close', (event) => {\n console.warn('[ws] Native close', {\n code: event.code,\n reason: event.reason,\n wasClean: event.wasClean,\n });\n });\n };\n\n socket.on('connect', () => {\n console.log('[ws] Connected', {\n socketId: socket.id,\n transport: getTransportName(),\n threadId: threadIdRef.current ?? null,\n rooms: [...joinedRoomsRef.current],\n });\n attachNativeCloseLogger();\n\n // Rejoin all tracked rooms on reconnect\n const rejoinedRooms: string[] = [];\n for (const room of joinedRoomsRef.current) {\n socket.emit('join_room', room);\n rejoinedRooms.push(room);\n }\n // Ensure active thread room is joined\n const tid = threadIdRef.current;\n if (tid) {\n const room = `thread:${tid}`;\n if (!joinedRoomsRef.current.has(room)) {\n socket.emit('join_room', room);\n joinedRoomsRef.current.add(room);\n rejoinedRooms.push(room);\n }\n }\n persistJoinedRooms();\n console.log('[ws] Rejoined rooms', {\n count: rejoinedRooms.length,\n rooms: rejoinedRooms,\n });\n recordInvocationEvent({\n event: 'connect',\n threadId: tid ?? undefined,\n action: getTransportName(),\n });\n recordInvocationEvent({\n event: 'rejoin_rooms',\n threadId: tid ?? undefined,\n queueLength: rejoinedRooms.length,\n });\n\n // Reconnect can miss in-flight stream chunks while the socket is down.\n // Trigger a lightweight message refresh so server-side draft rows rehydrate.\n if (tid) {\n requestThreadLiveRefresh(tid, 'messages', 'socket-reconnect');\n }\n\n // Reconnect reconciliation: verify invocation state against server truth.\n // Socket disconnect can lose done(isFinal) events, leaving stale \"replying\" UI.\n // Delay slightly so any buffered events arrive first.\n reconcileInvocationStateOnReconnect(tid ?? null);\n });\n\n const requestMissingThreadCatchUp = (reason: string, sourceMsg: AgentMessage) => {\n const refreshThreadId = threadIdRef.current ?? useChatStore.getState().currentThreadId;\n const now = Date.now();\n recordInvocationEvent({\n event: sourceMsg.type === 'done' ? 'done' : 'agent_message',\n action: reason,\n threadId: undefined,\n isFinal: sourceMsg.isFinal === true,\n });\n if (refreshThreadId) {\n const lastRecoveryAt = missingThreadRecoveryAtRef.current.get(refreshThreadId) ?? 0;\n if (now - lastRecoveryAt >= MISSING_THREAD_ID_RECOVERY_THROTTLE_MS) {\n missingThreadRecoveryAtRef.current.set(refreshThreadId, now);\n requestThreadLiveRefresh(refreshThreadId, 'messages', reason);\n useChatStore.getState().requestStreamCatchUp?.(refreshThreadId);\n }\n }\n console.warn('[ws] Dropping agent_message without threadId to prevent cross-thread contamination', {\n type: sourceMsg.type,\n agentId: sourceMsg.agentId,\n invocationId: sourceMsg.invocationId,\n refreshThreadId: refreshThreadId ?? null,\n reason,\n });\n };\n\n const flushBufferedInvocationMessages = (invocationId: string, resolvedThreadId: string) => {\n const buffered = missingThreadBufferRef.current.get(invocationId);\n if (!buffered || buffered.length === 0) return;\n const timer = missingThreadBufferTimerRef.current.get(invocationId);\n if (timer) {\n clearTimeout(timer);\n missingThreadBufferTimerRef.current.delete(invocationId);\n }\n missingThreadBufferRef.current.delete(invocationId);\n for (const bufferedMsg of buffered) {\n routeAgentMessage({ ...bufferedMsg, threadId: resolvedThreadId }, bufferedMsg, true);\n }\n };\n\n const routeAgentMessage = (routedMsg: AgentMessage, originalMsg: AgentMessage, recoveredFromBuffer = false) => {\n if (routedMsg.threadId && routedMsg.invocationId) {\n invocationThreadMapRef.current.set(routedMsg.invocationId, routedMsg.threadId);\n flushBufferedInvocationMessages(routedMsg.invocationId, routedMsg.threadId);\n }\n const routeThread = threadIdRef.current;\n const storeThread = useChatStore.getState().currentThreadId;\n\n // Active thread requires BOTH route-level and store-level agreement.\n // This blocks a switch-window race where route already points to thread-B\n // but flat store still belongs to thread-A.\n const isActiveThreadMessage = Boolean(\n routedMsg.threadId &&\n routeThread &&\n storeThread &&\n routedMsg.threadId === routeThread &&\n routedMsg.threadId === storeThread,\n );\n // If either pointer is temporarily unavailable during thread switch,\n // route thread-tagged events to background to avoid mutating stale flat state.\n recordInvocationEvent({\n event: routedMsg.type === 'done' ? 'done' : 'agent_message',\n threadId: routedMsg.threadId,\n action:\n recoveredFromBuffer || routedMsg.threadId !== originalMsg.threadId\n ? 'recover_missing_thread_id'\n : routedMsg.type,\n isFinal: routedMsg.isFinal === true,\n });\n\n // Safety-first: never route threadless payloads to active chat state.\n // Doing so can leak content into the wrong thread during rapid switches.\n // We drop and rely on thread-scoped history refresh for eventual consistency.\n if (!routedMsg.threadId) {\n if (routedMsg.invocationId) {\n const invocationId = routedMsg.invocationId;\n const existing = missingThreadBufferRef.current.get(invocationId);\n if (existing) {\n existing.push(routedMsg);\n } else {\n missingThreadBufferRef.current.set(invocationId, [routedMsg]);\n const timeoutId = setTimeout(() => {\n const pending = missingThreadBufferRef.current.get(invocationId);\n missingThreadBufferRef.current.delete(invocationId);\n missingThreadBufferTimerRef.current.delete(invocationId);\n if (!pending || pending.length === 0) return;\n for (const pendingMsg of pending) {\n requestMissingThreadCatchUp('drop_missing_thread_id_timeout', pendingMsg);\n }\n }, MISSING_THREAD_ID_BUFFER_TIMEOUT_MS);\n missingThreadBufferTimerRef.current.set(invocationId, timeoutId);\n }\n recordInvocationEvent({\n event: routedMsg.type === 'done' ? 'done' : 'agent_message',\n action: 'buffer_missing_thread_id',\n threadId: undefined,\n isFinal: routedMsg.isFinal === true,\n });\n return;\n }\n requestMissingThreadCatchUp('drop_missing_thread_id', routedMsg);\n return;\n }\n\n // Active thread → full processing via onMessage (streaming, tool events, etc.)\n if (isActiveThreadMessage) {\n callbacksRef.current.onMessage(routedMsg);\n clearBackgroundStreamRefForActiveEvent(routedMsg, bgStreamRefsRef.current);\n if (routedMsg.isFinal && routedMsg.invocationId) {\n invocationThreadMapRef.current.delete(routedMsg.invocationId);\n const timer = missingThreadBufferTimerRef.current.get(routedMsg.invocationId);\n if (timer) {\n clearTimeout(timer);\n missingThreadBufferTimerRef.current.delete(routedMsg.invocationId);\n }\n missingThreadBufferRef.current.delete(routedMsg.invocationId);\n }\n return;\n }\n\n // Background thread → delegated handler\n handleBackgroundAgentMessage(routedMsg as BackgroundAgentMessage, {\n store: useChatStore.getState(),\n bgStreamRefs: bgStreamRefsRef.current,\n finalizedBgRefs: bgFinalizedRefsRef.current,\n replacedInvocations: bgReplacedInvocationsRef.current,\n backgroundErrorToastsShown: bgErrorToastsShownRef.current,\n nextBgSeq: () => bgSeqRef.current++,\n addToast: (toast) => useToastStore.getState().addToast(toast),\n getThreadTitle: (threadId) => useChatStore.getState().threads.find((t) => t.id === threadId)?.title,\n clearDoneTimeout: callbacksRef.current.clearDoneTimeout,\n notifyTaskComplete: (title, body, type, threadId) => notifyOnTaskComplete({ title, body, type, threadId }),\n });\n if (routedMsg.isFinal && routedMsg.invocationId) {\n invocationThreadMapRef.current.delete(routedMsg.invocationId);\n const timer = missingThreadBufferTimerRef.current.get(routedMsg.invocationId);\n if (timer) {\n clearTimeout(timer);\n missingThreadBufferTimerRef.current.delete(routedMsg.invocationId);\n }\n missingThreadBufferRef.current.delete(routedMsg.invocationId);\n }\n };\n\n socket.on('agent_message', (msg: AgentMessage) => {\n let resolvedThreadId = msg.threadId;\n if (!resolvedThreadId && msg.invocationId) {\n resolvedThreadId = invocationThreadMapRef.current.get(msg.invocationId);\n }\n const routedMsg: AgentMessage =\n resolvedThreadId && resolvedThreadId !== msg.threadId ? { ...msg, threadId: resolvedThreadId } : msg;\n routeAgentMessage(routedMsg, msg);\n });\n\n socket.on('thread_updated', (data: { threadId: string; title: string }) => {\n callbacksRef.current.onThreadUpdated?.(data);\n });\n socket.on('thread_created', (data: { threadId: string; source?: string }) => {\n callbacksRef.current.onThreadCreated?.(data);\n });\n socket.on('skill_options_changed', () => {\n notifySkillOptionsChanged();\n });\n\n socket.on(\n 'intent_mode',\n (data: { threadId: string; mode: string; targetAgents: string[]; invocationId?: string }) => {\n const routeThread = threadIdRef.current;\n const storeThread = useChatStore.getState().currentThreadId;\n recordInvocationEvent({\n event: 'intent_mode',\n threadId: data.threadId,\n mode: data.mode,\n });\n if (data.threadId && data.invocationId) {\n invocationThreadMapRef.current.set(data.invocationId, data.threadId);\n flushBufferedInvocationMessages(data.invocationId, data.threadId);\n }\n\n // Dual-pointer guard: both route and store must agree for active-thread processing.\n // Mirrors agent_message pattern — blocks switch-window race where route already\n // points to thread-B but flat store still belongs to thread-A.\n const isActiveThread = Boolean(\n data.threadId && routeThread && storeThread && data.threadId === routeThread && data.threadId === storeThread,\n );\n\n if (isActiveThread) {\n callbacksRef.current.onIntentMode?.(data);\n // F108: Register invocation slot in active thread store\n if (data.invocationId) {\n const primaryCat = data.targetAgents?.[0] ?? 'unknown';\n useChatStore.getState().addActiveInvocation(data.invocationId, primaryCat, data.mode);\n }\n return;\n }\n\n // Background thread (split-pane) or switch-window: write directly to thread-scoped state\n if (data.threadId) {\n const store = useChatStore.getState();\n store.setThreadLoading(data.threadId, true);\n // F108: slot-aware — register specific invocation if ID available\n if (data.invocationId) {\n const primaryCat = data.targetAgents?.[0] ?? 'unknown';\n store.addThreadActiveInvocation(data.threadId, data.invocationId, primaryCat, data.mode);\n } else {\n store.setThreadHasActiveInvocation(data.threadId, true);\n }\n store.setThreadIntentMode(data.threadId, data.mode as 'execute' | 'ideate');\n store.setThreadTargetAgents(data.threadId, data.targetAgents ?? []);\n }\n },\n );\n\n socket.on('task_created', (task: Record<string, unknown>) => {\n callbacksRef.current.onTaskCreated?.(task);\n });\n\n socket.on('task_updated', (task: Record<string, unknown>) => {\n callbacksRef.current.onTaskUpdated?.(task);\n });\n\n\n socket.on('heartbeat', (data: { threadId: string; timestamp: number }) => {\n callbacksRef.current.onHeartbeat?.(data);\n });\n\n socket.on('message_deleted', (data: { messageId: string; threadId: string; deletedBy: string }) => {\n callbacksRef.current.onMessageDeleted?.(data);\n });\n socket.on('message_hard_deleted', (data: { messageId: string; threadId: string; deletedBy: string }) => {\n callbacksRef.current.onMessageDeleted?.(data);\n });\n socket.on('message_restored', (data: { messageId: string; threadId: string }) => {\n callbacksRef.current.onMessageRestored?.(data);\n });\n socket.on('thread_branched', (data: { sourceThreadId: string; newThreadId: string; fromMessageId: string }) => {\n callbacksRef.current.onThreadBranched?.(data);\n });\n\n socket.on('authorization:request', (data: Record<string, unknown>) => {\n registerAndNotifyAuthorizationRequest(data);\n const currentThread = threadIdRef.current;\n if (data.threadId && currentThread && data.threadId !== currentThread) return;\n callbacksRef.current.onAuthorizationRequest?.(\n data as Parameters<NonNullable<SocketCallbacks['onAuthorizationRequest']>>[0],\n );\n });\n socket.on('authorization:response', (data: Record<string, unknown>) => {\n const requestId = typeof data.requestId === 'string' ? data.requestId : null;\n if (requestId) {\n useAuthorizationPendingStore.getState().resolvePending(requestId);\n }\n callbacksRef.current.onAuthorizationResponse?.(\n data as Parameters<NonNullable<SocketCallbacks['onAuthorizationResponse']>>[0],\n );\n });\n socket.on('ask_user_question:request', (data: Record<string, unknown>) => {\n const currentThread = threadIdRef.current;\n if (data.threadId && currentThread && data.threadId !== currentThread) return;\n callbacksRef.current.onAskUserQuestionRequest?.(\n data as unknown as Parameters<NonNullable<SocketCallbacks['onAskUserQuestionRequest']>>[0],\n );\n });\n socket.on('ask_user_question:response', (data: Record<string, unknown>) => {\n callbacksRef.current.onAskUserQuestionResponse?.(\n data as Parameters<NonNullable<SocketCallbacks['onAskUserQuestionResponse']>>[0],\n );\n });\n\n const normalizeQueueForDebug = (queue: unknown): unknown[] => (Array.isArray(queue) ? queue : []);\n const getQueueStatusesForDebug = (queue: unknown) =>\n normalizeQueueForDebug(queue).map((entry) => {\n if (!entry || typeof entry !== 'object') return 'unknown';\n const status = (entry as { status?: unknown }).status;\n return typeof status === 'string' ? status : 'unknown';\n });\n\n // F39: Queue events — always write via store (no dual-pointer guard needed, queue is thread-scoped)\n socket.on('queue_updated', (data: { threadId: string; queue: unknown[]; action: string }) => {\n const store = useChatStore.getState();\n store.setQueue(data.threadId, data.queue as import('../stores/chat-types').QueueEntry[]);\n const normalizedQueue = normalizeQueueForDebug(data.queue);\n // Queue processor started executing an entry: restore active invocation marker\n // so ChatInput can show \"正在回复中\" and Stop/queue controls after thread switches/F5.\n if (data.action === 'processing') {\n store.setThreadHasActiveInvocation(data.threadId, true);\n }\n // P1 fix: 'processing' means continue/auto-dequeue resumed the queue — clear paused state\n if (data.action === 'processing' || data.action === 'cleared') {\n store.setQueuePaused(data.threadId, false);\n }\n // If queue execution completed but done(isFinal) was missed, local active state\n // can stay stale. Trigger panel reconciliation against server truth.\n if (data.action === 'completed') {\n const hasProcessingEntry = normalizedQueue.some((entry) => {\n if (!entry || typeof entry !== 'object') return false;\n return (entry as { status?: unknown }).status === 'processing';\n });\n if (!hasProcessingEntry) {\n requestThreadLiveRefresh(data.threadId, 'panels', 'queue_completed');\n }\n }\n if (isDebugEnabled()) {\n const stateAfterUpdate = store.getThreadState(data.threadId);\n recordInvocationEvent({\n event: 'queue_updated',\n threadId: data.threadId,\n action: data.action,\n queueLength: normalizedQueue.length,\n queueStatuses: getQueueStatusesForDebug(data.queue),\n hasActiveInvocation: data.action === 'processing' ? true : stateAfterUpdate?.hasActiveInvocation,\n queuePaused:\n data.action === 'processing' || data.action === 'cleared' ? false : stateAfterUpdate?.queuePaused,\n });\n }\n });\n // F098-D + F117: Messages delivered — update deliveredAt + insert user bubbles for queue sends\n socket.on(\n 'messages_delivered',\n (data: {\n threadId: string;\n messageIds: string[];\n deliveredAt: number;\n messages?: Array<{\n id: string;\n content: string;\n agentId: string | null;\n timestamp: number;\n mentions: readonly string[];\n userId: string;\n contentBlocks?: readonly unknown[];\n }>;\n }) => {\n useChatStore.getState().markMessagesDelivered(data.threadId, data.messageIds, data.deliveredAt, data.messages);\n },\n );\n\n socket.on('queue_paused', (data: { threadId: string; reason: 'canceled' | 'failed'; queue: unknown[] }) => {\n const store = useChatStore.getState();\n store.setQueue(data.threadId, data.queue as import('../stores/chat-types').QueueEntry[]);\n store.setQueuePaused(data.threadId, true, data.reason);\n if (isDebugEnabled()) {\n recordInvocationEvent({\n event: 'queue_paused',\n threadId: data.threadId,\n reason: data.reason,\n queueLength: normalizeQueueForDebug(data.queue).length,\n queueStatuses: getQueueStatusesForDebug(data.queue),\n });\n }\n\n const normalizedQueue = normalizeQueueForDebug(data.queue);\n const hasQueuedEntry = normalizedQueue.some((entry) => {\n if (!entry || typeof entry !== 'object') return false;\n const status = (entry as { status?: unknown }).status;\n return status === 'queued';\n });\n if (!hasQueuedEntry) return;\n if (queueAutoContinueInFlightRef.current.has(data.threadId)) return;\n\n queueAutoContinueInFlightRef.current.add(data.threadId);\n void (async () => {\n try {\n const res = await apiFetch(`/api/threads/${data.threadId}/queue/next`, { method: 'POST' });\n if (!res.ok) {\n if (isDebugEnabled()) {\n recordInvocationEvent({\n event: 'queue_paused',\n threadId: data.threadId,\n action: 'auto_continue_failed',\n reason: data.reason,\n });\n }\n return;\n }\n if (isDebugEnabled()) {\n recordInvocationEvent({\n event: 'queue_paused',\n threadId: data.threadId,\n action: 'auto_continue_next',\n reason: data.reason,\n });\n }\n } catch {\n if (isDebugEnabled()) {\n recordInvocationEvent({\n event: 'queue_paused',\n threadId: data.threadId,\n action: 'auto_continue_error',\n reason: data.reason,\n });\n }\n } finally {\n queueAutoContinueInFlightRef.current.delete(data.threadId);\n }\n })();\n });\n socket.on('queue_full_warning', (data: { threadId: string; source: 'user' | 'connector'; queue: unknown[] }) => {\n const store = useChatStore.getState();\n store.setQueue(data.threadId, data.queue as import('../stores/chat-types').QueueEntry[]);\n store.setQueueFull(data.threadId, data.source);\n useToastStore.getState().addToast({\n type: 'info',\n title: '队列已满',\n message: '消息队列已达上限,请管理队列后再发送',\n threadId: data.threadId,\n duration: 5000,\n });\n });\n\n socket.on('connector_message', (data: ConnectorMessageEvent) => {\n if (!data?.threadId || !data?.message?.id) return;\n const store = useChatStore.getState();\n const shouldTreatAsUser = isUserChannelConnector(data.message.source?.connector);\n store.addMessageToThread(data.threadId, {\n id: data.message.id,\n type: shouldTreatAsUser ? 'user' : 'connector',\n content: data.message.content ?? '',\n ...(data.message.source ? { source: data.message.source } : {}),\n ...(data.message.extra ? { extra: data.message.extra } : {}),\n timestamp: data.message.timestamp ?? Date.now(),\n });\n });\n\n // F101: Game state updates (per-seat scoped views)\n socket.on('game:state_update', (data: { gameId: string; view: unknown; timestamp: number }) => {\n callbacksRef.current.onGameStateUpdate?.(data);\n });\n\n // F101 Phase I: Narrator narrative messages (e.g. \"🐺 狼人请睁眼\")\n socket.on(\n 'game:narrative',\n (data: { threadId: string; message: { id: string; type: string; content: string; timestamp: number } }) => {\n if (!data?.threadId || !data?.message?.id) return;\n useChatStore.getState().addMessageToThread(data.threadId, {\n id: data.message.id,\n type: 'system',\n content: data.message.content,\n timestamp: data.message.timestamp,\n });\n },\n );\n\n // F101 Phase D: Independent game thread created\n socket.on(\n 'game:thread_created',\n (data: { gameThreadId: string; gameTitle: string; initiatorUserId: string; timestamp: number }) => {\n callbacksRef.current.onGameThreadCreated?.(data);\n },\n );\n\n // F111 Phase B + F112 Phase A: Real-time voice stream events\n socket.on('voice_stream_start', handleVoiceStreamStart);\n socket.on('voice_chunk', handleVoiceChunk);\n socket.on('voice_stream_end', handleVoiceStreamEnd);\n\n socket.on('connect_error', (error: Error & { description?: unknown; context?: unknown }) => {\n console.error('[ws] connect_error', {\n message: error.message,\n name: error.name,\n transport: getTransportName(),\n description: error.description ?? null,\n context: error.context ?? null,\n });\n });\n\n socket.on('disconnect', (...args: unknown[]) => {\n const [reason, details] = args;\n console.warn('[ws] Disconnected', {\n reason: typeof reason === 'string' ? reason : String(reason),\n transport: getTransportName(),\n details: details ?? null,\n });\n recordInvocationEvent({\n event: 'disconnect',\n threadId: threadIdRef.current,\n reason: typeof reason === 'string' ? reason : String(reason),\n });\n });\n\n const engine = socket.io.engine as unknown as SocketIoEngineLike | undefined;\n engine?.on('upgrade', () => {\n attachNativeCloseLogger();\n console.log('[ws] Transport upgraded', { transport: getTransportName() });\n });\n engine?.on('close', (...args: unknown[]) => {\n const [reason] = args;\n console.warn('[ws] Engine close', {\n reason: typeof reason === 'string' ? reason : String(reason),\n transport: getTransportName(),\n });\n recordInvocationEvent({\n event: 'engine_close',\n threadId: threadIdRef.current,\n reason: typeof reason === 'string' ? reason : String(reason),\n });\n });\n\n socketRef.current = socket;\n\n // Handle page visibility change: refresh thread messages when page becomes visible\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'visible') {\n const currentThreadId = threadIdRef.current || useChatStore.getState().currentThreadId;\n if (currentThreadId) {\n console.log('[ws] Page became visible, refreshing thread:', currentThreadId);\n requestThreadLiveRefresh(currentThreadId, 'messages', 'visibility-change');\n }\n }\n };\n\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n return () => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n socket.disconnect();\n joinedRoomsRef.current.clear();\n for (const timeoutId of missingThreadBufferTimerRef.current.values()) {\n clearTimeout(timeoutId);\n }\n missingThreadBufferTimerRef.current.clear();\n missingThreadBufferRef.current.clear();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps -- callbacks accessed via callbacksRef\n }, [persistJoinedRooms]);\n\n /** Join a single room (additive — does not leave other rooms) */\n const joinRoom = useCallback(\n (roomThreadId: string) => {\n const socket = socketRef.current;\n if (!socket) return;\n const room = `thread:${roomThreadId}`;\n if (joinedRoomsRef.current.has(room)) return;\n socket.emit('join_room', room);\n joinedRoomsRef.current.add(room);\n persistJoinedRooms();\n },\n [persistJoinedRooms],\n );\n\n /**\n * Best-effort server-side join confirmation for race-sensitive flows.\n * Falls back to the legacy fire-and-forget behavior on timeout/unavailable socket.\n */\n const awaitThreadRoom = useCallback(\n async (roomThreadId: string, timeoutMs = ROOM_JOIN_ACK_TIMEOUT_MS): Promise<JoinRoomAwaitStatus> => {\n const room = `thread:${roomThreadId}`;\n joinedRoomsRef.current.add(room);\n persistJoinedRooms();\n\n const deadline = Date.now() + Math.max(timeoutMs, 0);\n let socket = socketRef.current;\n\n while ((!socket || !socket.connected) && Date.now() < deadline) {\n const remaining = deadline - Date.now();\n await new Promise((resolve) => setTimeout(resolve, Math.min(ROOM_JOIN_POLL_INTERVAL_MS, remaining)));\n socket = socketRef.current;\n }\n\n if (!socket) {\n return 'socket_unavailable';\n }\n\n if (!socket.connected) {\n socket.emit('join_room', room);\n return 'timed_out';\n }\n\n // Frontend-only guard: re-emit room join after the socket is confirmed up,\n // then leave a tiny settle window for the server to process the membership.\n socket.emit('join_room', room);\n\n const remaining = deadline - Date.now();\n if (remaining > 0) {\n await new Promise((resolve) => setTimeout(resolve, Math.min(ROOM_JOIN_SETTLE_MS, remaining)));\n }\n\n return socket.connected ? 'joined' : 'timed_out';\n },\n [persistJoinedRooms],\n );\n\n /** Leave a single room */\n const leaveRoom = useCallback(\n (roomThreadId: string) => {\n const socket = socketRef.current;\n if (!socket) return;\n const room = `thread:${roomThreadId}`;\n if (!joinedRoomsRef.current.has(room)) return;\n socket.emit('leave_room', room);\n joinedRoomsRef.current.delete(room);\n persistJoinedRooms();\n },\n [persistJoinedRooms],\n );\n\n /** Sync joined rooms to exactly the given set of thread IDs */\n const syncRooms = useCallback(\n (threadIds: string[]) => {\n const socket = socketRef.current;\n if (!socket) return;\n\n const targetRooms = new Set(threadIds.map((id) => `thread:${id}`));\n\n // Leave rooms no longer needed\n for (const room of joinedRoomsRef.current) {\n if (!targetRooms.has(room)) {\n socket.emit('leave_room', room);\n joinedRoomsRef.current.delete(room);\n }\n }\n\n // Join new rooms\n for (const room of targetRooms) {\n if (!joinedRoomsRef.current.has(room)) {\n socket.emit('join_room', room);\n joinedRoomsRef.current.add(room);\n }\n }\n persistJoinedRooms();\n },\n [persistJoinedRooms],\n );\n\n // Add the active thread plus any background threads whose updates must be\n // reflected in the UI (e.g. unread badges). This stays additive on purpose:\n // persisted room memberships still help during refresh/reconnect windows.\n useEffect(() => {\n if (threadId) {\n joinRoom(threadId);\n }\n for (const watchedThreadId of normalizedWatchedThreadIds) {\n joinRoom(watchedThreadId);\n }\n }, [threadId, normalizedWatchedThreadIds, joinRoom]);\n\n const cancelInvocation = useCallback((tid: string) => {\n socketRef.current?.emit('cancel_invocation', { threadId: tid });\n }, []);\n\n return { socketRef, joinRoom, awaitThreadRoom, leaveRoom, syncRooms, cancelInvocation };\n}\n"],"names":["MODEL_ARTS_SENSITIVE_INPUT_ERROR_CODE","MODEL_ARTS_RATE_LIMIT_ERROR_CODE","APIG_DAILY_QUOTA_EXHAUSTED_ERROR_CODE","MODEL_ARTS_SENSITIVE_INPUT_MESSAGE_FRAGMENT","MODEL_ARTS_RATE_LIMIT_MESSAGE","INSUFFICIENT_QUOTA_MESSAGE","CONTEXT_LENGTH_MESSAGE","AUTH_ERROR_MESSAGE","SERVICE_UNAVAILABLE_MESSAGE","DAILY_QUOTA_EXHAUSTED_MESSAGE","STREAM_CONNECTION_ERROR_MESSAGE","STREAM_ERROR_PATTERNS","normalizeQuotedText","rawError","matchesGenericRateLimit","normalizedError","isSensitiveInputError","msg","normalized","_a","isRateLimitError","isDailyQuotaExhaustedError","isTimeoutError","isAbruptExitError","isConnectionError","isStreamConnectionError","p","isMaxIterationsReachedError","isInsufficientQuotaError","isContextLengthError","isAuthError","isServiceUnavailableError","CONFIGURATION_MATCHES","isConfigurationError","pattern","getConfigurationErrorMessage","matched","getRateLimitMessage","getDailyQuotaExhaustedMessage","getFriendlyAgentErrorMessage","serial","MAX_RAW_ERROR_LENGTH","message","PLACEHOLDER_REGEX","placeholderCounter","generatePlaceholderId","parsePromptTemplate","template","blocks","placeholderIds","lastIndex","match","matchStart","defaultText","fileType","formatsStr","id","formats","f","heroCards","ChatEmptyState","onAgentsClick","onChannelsClick","fillAvailableHeight","sectionClassName","contentClassName","handleCardClick","cardId","jsx","jsxs","card","MAIN_PANEL_MIN_WIDTH","MENTION_RIGHT_WHITESPACE_RE","SKILL_TOKEN_PREFIX","SKILL_TOKEN_SUFFIX","QUICK_ACTION_TOKEN_PREFIX","QUICK_ACTION_TOKEN_SUFFIX","isVisuallyEmptyRichTextareaValue","value","createSkillToken","name","token","iconUrl","createQuickActionToken","label","icon","buildRichTextareaSegments","skillOptions","quickActionOptions","options","allowTerminalMention","skillOptionByName","item","quickActionIconByLabel","mentionToAgentId","getMentionToAgentId","mentionAliases","a","b","segments","textBuffer","cursor","flushText","end","skill","prev","alias","raw","next","serializeRichTextareaNode","node","el","out","child","serializeRichTextareaNodeSignature","appendRichTextareaSegment","frag","segment","span","createMaskIconElement","fallback","remove","src","className","renderRichTextareaSegments","root","usePlaceholderStore","create","set","get","state","file","path","workspacePath","fileEntries","fileValues","buildInspirationUploadPath","newFileValues","newTextValues","buildPendingTemplateInput","currentInput","pendingText","separator","normalizeDeletedTemplateInput","buildSendContentFromPromptRoot","text","files","placeholderId","fileValue","textValue","buildInputFromParsedPrompt","parsed","textValues","resultText","block","placeholder","syncFixedBlocksFromPromptRoot","index","fixedElement","useInspirationTemplate","input","setInput","textareaRef","pendingChatInsert","useChatStore","s","setPendingChatInsert","activePlaceholderId","setActivePlaceholderId","useState","bumpParsedVersion","consumedRef","useRef","pendingRef","parsedPersistRef","commitParsedPrompt","useCallback","nextParsed","current","version","useEffect","templateText","insertedTemplateText","inputIsTemplate","isTemplateCandidate","newParsed","parseSource","currentParsed","isTemplate","rootValue","setActivePlaceholder","handlePlaceholderFocus","handlePlaceholderBlur","handlePlaceholderTabNext","currentId","currentIdx","syncInputFromTemplate","resetTemplate","handlePlaceholderDelete","persistedParsed","blockIndex","newBlocks","_","idx","newPlaceholderIds","pid","nextInput","buildSendContent","PATH_PATTERN","DEBOUNCE_MS","usePathCompletion","entries","setEntries","isOpen","setIsOpen","selectedIdx","setSelectedIdx","timerRef","abortRef","lastPrefixRef","cwd","detectPath","isOpenRef","close","selectEntry","entry","beforePath","completedName","pathPrefix","lastSlash","parentPart","newText","newPathMatch","_b","controller","cwdParam","res","apiFetch","data","items","STORAGE_KEY","LEGACY_STORAGE_KEY","MAX_ENTRIES","loadEntries","saveEntries","useInputHistoryStore","trimmed","filtered","e","prefix","lower","query","useInvitedExpertsForThread","threadId","invitedExperts","setInvitedExperts","isLoading","setIsLoading","cancelled","fetchInvitedExperts","response","err","ChatDragUploadOverlay","isVisible","host","createPortal","useBottomLeftControls","skillInsertAnchorRef","closeMenus","routerPush","onSkillMouseDown","ta","start","onOpenSkillManager","useSkillMenuInput","filteredSkillOptions","onInsertSkill","onClose","onSkillFilterChange","handleSkillFilterChange","handleSkillFilterKeyDown","SKILL_MENU_CLASS","SKILL_MENU_ITEM_CLASS","getSkillInitial","initial","SkillOptionIcon","SkillMenuPanel","menuRef","skillFilter","skillOptionsLoading","skillOptionRefs","i","OverflowTooltip","GuidedModeIcon","ChatInputSkillControls","skillBtnRef","styleTemplateBtnRef","onSkillClick","selectedQuickAction","guidedModeEnabled","onToggleGuidedMode","hasPptSkillInInput","selectedTemplate","onStyleTemplateClick","onClearSelectedTemplate","showSkillMenu","onCloseMenus","SKILL_TRIGGER_BUTTON_CLASS","MaskIcon","Fragment","ChatInputBottomLeft","rest","DEFAULT_SETTINGS","VALID_LANGUAGES","isValidTerm","normalizeSettings","obj","customTerms","customPrompt","language","loadFromStorage","settings","saveToStorage","useVoiceSettingsStore","from","to","terms","prompt","DESKTOP_MESSAGE_EVENT","getDesktopBridge","desktopWindow","_c","parseDesktopPayload","useVoiceInput","mergedEntries","useMemo","mergeTermEntries","setState","transcript","setTranscript","partialTranscript","setPartialTranscript","error","setError","duration","setDuration","desktopSessionRef","desktopListenerRef","desktopCustomEventRef","startTimeRef","versionRef","entriesRef","clearTimers","detachDesktopListeners","webview","startRecording","bridge","sessionId","myVersion","handlePayload","payload","correctTranscription","webviewListener","event","customEventListener","detail","stopRecording","LoadingIcon","MicIcon","RotatingBorderStopIcon","SendIcon","StopRecordingIcon","ChatInputActionButton","onTranscript","onSend","onQueueSend","onStop","disabled","sendDisabled","hideIdleMic","hasActiveInvocation","hasText","queueLimitReached","showQueueTooltip","voice","visibleError","setVisibleError","isSendDisabled","timer","voiceState","handleKeydown","handleToggleVoice","isQueueMode","showIdleMic","queueTooltip","useBottomRightActions","fileInputRef","workspaceMenuItems","setWorkspaceFilter","selectWorkspaceMenuItem","handleAttachClick","handleWorkspaceFilterChange","handleWorkspaceSearchKeyDown","ChatInputBottomRight","folderSelectionEnabled","selectedFolderTitle","folderButtonLabel","shouldShowFolderTooltip","folderBtnRef","workspaceSearchInputRef","workspaceFilter","showWorkspaceMenu","workspaceOptionRefs","isFolderButtonDisabled","queueAwareDisabled","sendTemporarilyDisabled","imagesCount","inputTrimmed","queueSendDisabled","queueCount","onWorkspaceClick","onWorkspaceSelect","isVoiceRecording","setIsVoiceRecording","handleVoiceState","tooltipContent","MAX_ATTACHMENT_FILES","ICON_BUTTON_CLASS","useMentionMenuInput","agentOptions","onSelectIdx","onInsertMention","onCloseMentionMenu","onMentionFilterChange","handleMentionFilterChange","handleMentionFilterKeyDown","opt","catInitial","renderMentionAvatar","avatar","ChatInputMenus","showMentions","mentionFilter","mentionMenuStyle","scrollRef","canScrollDown","setCanScrollDown","selectedRef","check","QUICK_ACTIONS_SORTED","QUICK_ACTIONS","isWhitespaceBoundary","length","extractQueueInlineTokens","content","tokens","mentionRe","getMentionRe","mentionLabelMap","getMentionLabel","skillNameSet","getCachedSkillOptions","mentionMatch","full","skillPhraseRe","skillMatch","skillName","quickByIndex","action","at","quickTokenFrom","matchedAction","skillTokenFrom","buildQueueInlineSegments","copyImageToClipboard","url","blob","fetchProtectedResourceBlob","CopyButton","copied","setCopied","handleCopy","Lightbox","alt","caption","handleKey","resolveAttachmentIconByFileName","fileName","ext","ImagePreview","onRemove","lightboxIdx","setLightboxIdx","formatFileSize","bytes","kb","mb","getFileExt","parts","getFileBaseName","lastDot","urls","QueueEditIcon","props","QueueTopIcon","QueueDeleteIcon","CLEAR_CONFIRM_WIDTH","CLEAR_CONFIRM_GAP","VIEWPORT_PADDING","renderQueueSegment","key","clamp","min","max","ChatInputQueuePanel","queuedEntries","attachmentNamesByEntryId","queueExpanded","queueBusy","queueHighlightedEntryId","listRef","onToggleExpanded","onClear","onPinToTop","onEdit","onDelete","showClearConfirm","setShowClearConfirm","confirmPosition","setConfirmPosition","clearConfirmAnchorRef","clearConfirmRef","useLayoutEffect","updatePosition","anchor","panel","anchorRect","panelHeight","maxLeft","preferredLeft","left","preferredTop","top","anchorCenterX","arrowLeft","handlePointerDown","target","handleKeyDown","IconButton","Button","inlineSegments","attachmentNames","segIndex","attachmentIndex","HistorySearchModal","onSelect","setQuery","inputRef","search","results","PathCompletionMenu","QuickActionExpandIcon","expanded","renderExpertCardPreview","mentions","mention","QuickActionsPanel","showQuickPrompts","quickActionsExpanded","quickActionsOverflowing","visibleQuickActions","quickActionsContainerRef","quickActionsRowRef","onQuickAction","onQuickPrompt","onExpertCardClick","QUICK_ACTION_BUTTON_CLASS","QUICK_ACTION_EXPAND_BUTTON_CLASS","EXPERT_CARD_BUTTON_CLASS","QUICK_PROMPT_BUTTON_CLASS","isEditableTextPlaceholder","element","findPlaceholderControl","container","findFixedBlock","placeCaretInFixedBlock","edge","onBlur","fixedBlock","selection","range","focusPlaceholder","onFocus","control","caret","placeCaretInEditableElement","placeCaretAtContainerEdge","moveToBlockBoundary","moveFromBlock","direction","targetIndex","getPlaceholderBlockIndex","hasTrailingCaretTarget","nextBlock","getFixedBlockIndexFromRange","startNode","startElement","getCaretTextOffset","beforeCaret","isCaretAtBoundary","caretOffset","isFixedCaretAtBoundary","getActivePlaceholderControl","activeElement","shouldMoveFromTextInput","selectionStart","selectionEnd","getEditableTextNode","walker","candidate","textNode","shouldMoveFromEditableText","shouldMoveFromPlaceholderControl","usePromptBlockKeyboardNavigation","containerRef","activePlaceholderControl","fixedBlockIndex","placeholderIndex","targetBlock","resolveDefaultWorkspacePath","workspaceRoot","buildDefaultInspirationWorkspacePath","usePlaceholderFileUpload","setFileValue","removeFileValue","setWorkspacePath","uploadFile","resolvedWorkspacePath","storedPath","deleteFile","FilePlaceholderBlock","isActive","onTabNext","isHovered","setIsHovered","hasFile","handleIconClick","handleClick","handleFocus","handleBlur","getFileTypeIcon","TextPlaceholderBlock","textRef","isComposingRef","userInput","setTextValue","hasRichTokens","segmentSignature","currentText","currentSignature","activeSelection","getSelectionOffsetsWithinElement","setSelectionOffsetsWithinElement","handleInput","handleCompositionStart","handleCompositionEnd","isEmpty","startRange","endRange","serializeSelectionRange","fragment","serialized","nodes","offset","walk","pick","parent","placeCaretFromClick","pos","RichPromptFixedBlock","isTerminalCaretTarget","blockRef","RichTextareaPromptBlocks","forwardRef","onInput","onKeyDown","onPaste","onScroll","style","ref","useImperativeHandle","handleDelete","handleTabNext","HISTORY_STACK_LIMIT","HISTORY_GROUP_WINDOW_MS","serializeChildren","n","collectPromptEditableSegments","isFixedBlock","isTextPlaceholder","getStringDiff","currentEnd","nextEnd","findPromptEditableSegment","active","activeSegment","boundaryPlaceholder","findFallbackPromptTextSegment","dispatchProgrammaticInput","inserted","renderPromptSegmentContent","applyPromptBlockProgrammaticChange","nextValue","setSelectionOffset","diff","nextStart","localStart","localEnd","nextSegmentText","collectTextNodes","getSelectionOffset","atEnd","sel","clampWithSelection","maxLength","clampedValue","forceSyncPlainText","resolvePositionAtOffset","textLength","getClientRectAtOffset","rect","isTextInsertionKey","cloneSnapshot","snapshot","isSameSnapshot","right","normalizeGroupedHistoryAction","inputType","RichTextarea","onValueChange","mentionDataVersion","onCompositionStateChange","promptBlocks","rootRef","isPromptBlockMode","pendingSelectionRef","shouldScrollToBottomRef","currentSnapshotRef","undoStackRef","redoStackRef","pendingInternalValueSyncRef","historyInputGuardRef","previousPromptBlockModeRef","historyGroupRef","showPlaceholder","setShowPlaceholder","seg","commitChange","resetHistoryGroup","pushHistorySnapshot","stack","copy","last","applySnapshot","groupedAction","now","applyUndo","previous","applyRedo","armHistoryInputGuard","type","pendingSelection","prevScrollTop","prevClientHeight","prevScrollHeight","wasNearBottom","wasPromptBlockMode","rawNext","rawStart","rawEnd","nextState","resolveEventElement","handlePromptInput","removeButton","tokenValue","native","selectedLength","insertedLength","isUndo","isRedo","plain","rawCaret","currentRoot","Dropdown","trigger","align","menuClassName","menuWidth","menuItemClassName","focusedIndex","setFocusedIndex","activeSubMenu","setActiveSubMenu","dropdownRef","triggerRef","itemRefs","navigableOptions","handleClickOutside","handleOptionClick","option","getSubMenuPosition","menuRect","triggerEl","renderMenuItem","globalIndex","isDisabled","isFocused","hasChildren","isSubMenuOpen","defaultItemClass","childIndex","menu","PromptDialog","open","title","inputValue","inputPlaceholder","confirmLabel","cancelLabel","confirmDisabled","modalTestId","onConfirm","onCancel","onInputChange","localValue","setLocalValue","handleConfirm","ALLOWED_EXTENSIONS","PPT_UPLOAD_FORMAT_MESSAGE","PPT_UPLOAD_SIZE_MESSAGE","MAX_PPT_TEMPLATE_NAME_LENGTH","PPT_UPLOAD_NAME_LENGTH_MESSAGE","mapApiTemplate","isValidPptFile","PlusIcon","styles","TemplateCard","onMakeSame","onRename","isSelected","renderMoreMenu","MemoizedTemplateCard","memo","UploadCard","isDragOverProp","isUploading","isGenerating","onFileSelect","isFull","dragOver","setDragOver","addToast","useToastStore","isDragOver","handleDragOver","handleDragLeave","handleDrop","handleInputChange","LoadingCard","_name","FailedCard","TAB_ITEMS","TemplatePicker","selectedTemplateId","onSelectChange","showCloseButton","activeTab","setActiveTab","presetTemplates","setPresetTemplates","myTemplates","setMyTemplates","searchKeyword","setSearchKeyword","setIsUploading","pollingIds","setPollingIds","renameDialogTemplate","setRenameDialogTemplate","renameDialogValue","setRenameDialogValue","failedTemplateIdsRef","confirm","useConfirm","refreshTemplates","mapped","failedTemplates","nextFailedIds","failedTemplate","handleTabChange","handleSearchChange","handleSearchClear","filteredMyTemplates","t","templates","handleMakeSame","handleRename","handleRenameConfirm","nextName","normalizedName","normalizeTemplateName","isValidTemplateName","getTemplateNameValidationMessage","handleFileSelect","MAX_PPT_TEMPLATE_FILE_SIZE","uploadBaseName","tempId","newTemplate","formData","uploadedTemplate","refreshedTemplates","renderGrid","Tab","SearchInput","PPT_TEMPLATE_NAME_PATTERN","ChatInputLayout","activeMenu","pathCompletion","filteredAgentOptions","onMentionSearchChange","setMentionStart","setMentionEnd","clearMentionFilter","insertMention","imageLifecycleStatus","uploadError","handleQuickAction","handleQuickPrompt","handleExpertCardClick","setQuickActionsExpanded","queueAttachmentNamesByEntryId","queueListRef","setQueueExpanded","handleQueueClear","handleQueuePinToTop","handleQueueDelete","handleQueueEdit","showStyleTemplatePopover","styleTemplatePopoverRef","onTemplateSelectChange","onTemplatePopoverClose","images","handleRemoveImage","isDraggingFiles","handleChange","setIsComposing","resizeTextarea","handlePaste","handleDragEnter","skillOptionsData","ghostSuggestion","isComposing","handleSkillClick","handleStyleTemplateClick","onSkillSearchChange","insertSkill","handleWorkspaceClick","handleWorkspaceMenuSelect","handleTranscript","handleSend","handleQueueSend","dragOverlayHost","showHistorySearch","handleHistorySelect","setShowHistorySearch","ghostDisplayInput","normalizeSkillsForSend","normalizeQuickActionsForSend","ghostDisplaySuggestion","ghostDisplaySuffix","hasQuickActionToken","ACCEPTED_TYPES","entryId","MAX_INPUT_LENGTH","deriveImageLifecycleStatus","isPreparingImages","uploadStatus","isImageLifecycleBlockingSend","status","useAttachmentManager","dropScope","setImages","setIsDraggingFiles","imagesRef","dragDepthRef","dragHideTimerRef","onFilesAccepted","supportedFiles","hasUnsupported","hasOversizedFile","hasOversizedImage","isSupportedAttachmentFile","isImage","maxSize","MAX_IMAGE_SIZE","MAX_FILE_SIZE","UNSUPPORTED_FILE_TYPE_MESSAGE","FILE_SIZE_EXCEEDED_MESSAGE","IMAGE_SIZE_EXCEEDED_MESSAGE","result","mergeFilesByName","pastedFiles","hasDraggedFiles","dataTransfer","types","droppedFiles","scope","clearHideTimer","clearDragging","scheduleHideDragging","isInDropScope","shouldHandleNativeEvent","onNativeDragEnter","onNativeDragOver","onNativeDragLeave","onNativeDrop","useChatInputInputFlow","setShowMentions","setShowSkillMenu","setMentionFilterValue","clearSkillFilter","val","clampInputLength","normalizedSelectionStart","normalizedSelectionEnd","detectMenuTrigger","isOpenHistoryShortcut","isInsertNewlineShortcut","useChatInputKeyboard","activeOptionsCount","setGhostSuggestion","ghostRef","closeAllMenus","handleMenuNavigation","handlePathCompletionNavigation","handleHistoryGhostAccept","currentVal","cursorAtEnd","restoredMatch","restoreSkillTokensFromSendText","useChatInputMenus","setShowWorkspaceMenu","setShowStyleTemplatePopover","toggleSkillMenu","onOpen","toggleWorkspaceMenu","toggleStyleTemplatePopover","stripExpertCardMentionPrefix","displayNames","displayPrefix","getQuickActionToken","output","useQuickActions","agents","applyProgrammaticInput","onQuickActionSelected","onExpertCardClicked","onMentionRefsChanged","onMentionRefsCleared","setSelectedQuickAction","setShowQuickPrompts","pendingQuickPromptExpand","setPendingQuickPromptExpand","setQuickActionsOverflowing","expertCardClickedRef","startIdx","endIdx","tokenEndExclusive","before","after","joiner","leftJoiner","rightJoiner","mentionTargets","row","mentionText","buildResolvedMention","mentionRefs","agent","body","fullText","measureQuickActionsOverflow","actionButtons","gap","singleLineWidth","total","button","availableWidth","observer","frameId","handleResize","hasMatchedPrompt","onExternalQuickActionInsert","resetQuickActions","useChatInputSendFlow","mentionOptions","selectedQuickActionLabel","addHistoryEntry","setSelectedTemplate","clearMentionRefs","resolveQueueSendOptions","doSend","deliveryMode","normalizeMentionsForSend","sendOptions","useChatInputTemplateFlow","handler","useCloseMenusCoordinator","closeMenusBase","clearSearchFilters","useDraftSync","params","threadDrafts","useHistorySuggestionSync","findHistoryMatch","useMentionMenuPositioning","updateMentionMenuPosition","onWindowChange","useMentionSkillActions","mentionStart","mentionEnd","setMentionMenuStyle","onMentionRefInserted","menuHeight","viewportPadding","desiredLeft","desiredTop","maxTop","normalizedAfter","cursorPos","textarea","triggerText","getSkillToken","usePanelMenuCoordinator","filteredAgentOptionsLength","filteredSkillOptionsLength","usePanelSearchFill","setMentionFilterState","setSkillFilterState","usePendingChatInsertSync","quickActionTokenPrefix","onExternalMentionInsert","stripTrailingMentionTrigger","isQuickActionInsert","shouldReplaceTrailingMentionTrigger","shouldReplaceAll","shouldKeepForInspirationTemplate","filter","base","queueEditDraftCache","QUEUE_EDIT_DRAFT_DB","QUEUE_EDIT_DRAFT_DB_VERSION","QUEUE_EDIT_DRAFT_STORE","QUEUE_EDIT_PENDING_STORE","QUEUE_EDIT_PENDING_TTL_MS","QUEUE_EDIT_PENDING_MATCH_TIMEOUT_MS","buildQueueEditDraftKey","createClientDraftId","randomHex","queueEditDraftDbPromise","openQueueEditDraftDb","resolve","request","db","persistQueueEditDraft","draft","tx","loadQueueEditDraft","req","clearQueueEditDraft","persistPendingQueueEditDraft","record","loadPendingQueueEditDrafts","all","clearPendingQueueEditDraft","recordId","clearPendingQueueEditDraftsByThread","readReq","targetIds","writeTx","store","useQueueEditDraftManager","activeQueueThreadId","skillNames","handleQueueExtractForEdit","handleQueueMoveToIndex","queueEditDraftRef","previousQueuedIdsRef","pendingDraftByIdRef","queueSendOptionsRef","pendingQueueReinsert","setPendingQueueReinsert","pendingDrafts","pendingByDraftId","pending","matchedPendingIds","runtimeDraft","previousIds","currentIds","previousIdSet","addedEntries","newestAdded","previousIndex","nextIndex","entryIndex","previousEntryId","nextEntryId","extracted","memoryDraft","persistedDraft","cachedDraft","restoredInput","handleQueueSendBase","editContext","draftId","clearPendingDraft","didQueueSend","handleQueueDeleteSafe","handleQueueClearSafe","resetQueueEditState","useQueueManager","setQueue","currentThreadId","queue","queueMessages","messageById","ids","names","msgId","fileNames","setQueueBusy","setQueueHighlightedEntryId","queueHighlightTimerRef","previousQueueCountRef","previousQueueExpandedRef","queueCountIncreased","queueJustExpanded","listEl","highlightQueueEntry","persistQueuePromote","applyLocalQueueReorder","sourceIndex","nextQueued","moved","queuedOrder","nextQueue","aOrder","bOrder","prevQueue","queuedEntry","maxIndex","clampedTarget","steps","useSkillOptionsSource","setSkillOptions","setSkillOptionsLoading","requestSeqRef","mountedRef","loadSkillOptions","force","requestId","fetchSkillOptionsWithCache","seedSkillOptionsCache","onUpdated","SKILL_OPTIONS_UPDATED_EVENT","useTemplateMode","setGuidedModeEnabled","useWorkspaceMenu","workspaceOptions","onSelectEmptyWorkspace","onSelectExistingWorkspace","onOpenFolderPicker","filteredWorkspaceOptions","ChatInput","selectedFolderName","activeWorkspacePath","dragDropScopeRef","navigate","useNavigate","useAgentData","setMentionDataVersion","refreshThreadExpertMentionData","expertOptions","expert","buildExpertOption","buildMentionOptions","replaceThreadTargetAgents","setInputState","setMentionRefs","appendMentionRef","replaceMentionRefs","refs","setDragOverlayHost","resolvedDragDropScope","setResolvedDragDropScope","MAX_PENDING_QUEUE","inspirationDraftWorkspacePath","setInspirationDraftWorkspacePath","insert","consumedPendingChatInsertRef","prevThreadIdRef","effectivePlaceholderWorkspacePath","handleQueueSendWithDraft","handleSendBase","reconcileMentionRefs","placeholderWorkspacePath","didSend","typedMentionIds","deriveTargetAgentIds","contentHeight","nextHeight","TEXTAREA_MIN_HEIGHT","TEXTAREA_MAX_HEIGHT","nextOverflowY","nextHeightCss","activeTrigger","explicitScope","fallbackScope","getNativeBridge","notifiedToolApprovalRequestIds","pendingToolApprovalNotificationIds","activeToolApprovalTitleFlashes","focusThread","targetPath","requestNotificationPermission","showBrowserNotification","createBrowserNotification","notification","sendDesktopNotificationRequest","startToolApprovalTitleFlash","agentLabel","originalTitle","alertTitle","showAlert","tick","intervalId","onVisibilityChange","stop","resolveAgentDisplayLabel","agentId","getCachedAgents","notifyOnTaskComplete","notifyToolApprovalRequest","permission","THREAD_LIVE_REFRESH_EVENT","requestThreadLiveRefresh","reason","isSharedRateLimitError","getRateLimitChatMessage","isDailyQuotaExhaustedAgentError","isSharedDailyQuotaExhaustedError","getDailyQuotaExhaustedChatMessage","isSensitiveInputAgentError","isSharedSensitiveInputError","getSensitiveInputErrorToastContent","ERROR_SUBTYPE_LABELS","getSharedFriendlyAgentErrorMessage","getErrorSubtypeLabel","rawContent","getAgentErrorToastContent","subtypeLabel","baseMessage","isSchedulerPlaceholderMessage","isRecord","getNullableString","getNumber","getPagesDirFromHtmlPath","htmlPath","inferPageNumberFromHtmlPath","coercePptStudioSlide","pageNumber","slideId","coercePptStudioStatus","coercePptStudioSlidesUpdate","source","slides","slide","singleSlide","pagesDir","stripWrappedValue","extractPseudoField","re","extractPseudoTrailingField","parseSystemInfoContent","mergeStrategy","recoverBackgroundStreamingMessage","streamKey","threadMessages","consumeBackgroundSystemInfo","existingRef","sysContent","sysVariant","consumed","sessionUpdate","targetCatId","invocationId","bgStreamKey","targetId","completeInvId","dur","hit","m","currentInvocationId","tasks","count","found","level","warningText","pct","_d","thinkingText","_e","STATUS_MAP","getStreamKey","buildMessageExtra","extra","getErrorFallback","finalMessage","fb","findLatestActiveInvocationIdForAgent","activeInvocations","info","shouldClearBackgroundRefOnActiveEvent","getThreadInvocationId","threadState","clearBackgroundStreamRefForActiveEvent","bgStreamRefs","stopTrackedStream","existing","markBackgroundErrorToastShown","hasShownBackgroundErrorToast","truncate","safeJsonPreview","toolUseDetail","toolName","toolInput","addBackgroundSystemMessage","variant","recoverStreamingMessage","recordDebugEvent","findBackgroundCallbackReplacementTarget","finalizedId","finalized","shouldSuppressLateBackgroundStreamChunk","replacedInvocationId","ensureBackgroundAssistantMessage","recoveredId","messageId","markThreadInvocationActive","markThreadInvocationComplete","activeInvocationSlot","handleBackgroundAgentMessage","isCallbackText","finalMsgId","replacementTarget","cbId","bgInvocationId","errorFallback","preview","notificationType","notificationTitle","notificationBody","toast","_f","_g","_h","currentStatus","latestAssistantMessage","messageErrorFallback","_i","_j","_k","_l","_m","_n","_o","joinedRoomsPrimaryKey","userId","joinedRoomsLegacyKey","isThreadRoom","room","loadJoinedRoomsFromSession","primary","legacy","rooms","saveJoinedRoomsToSession","domAudio","getDomAudio","PlaybackManager","callbacks","mimeType","binary","blobUrl","audio","fetchFn","capturedBatchId","fn","orig","newState","syncVoiceModeToBackend","voiceMode","sessionCounter","stopCallbacks","useVoiceSessionStore","autoplayUnlocked","session","playbackState","blockId","nextIds","managerInstance","getOrCreateManager","voiceStore","matchesActiveSession","handleVoiceStreamStart","handleVoiceChunk","handleVoiceStreamEnd","useVoiceStream","pause","resume","skip","USER_CHANNEL_CONNECTORS","isUserChannelConnector","connectorId","readStringField","registerAndNotifyAuthorizationRequest","useAuthorizationPendingStore","ROOM_JOIN_ACK_TIMEOUT_MS","ROOM_JOIN_POLL_INTERVAL_MS","ROOM_JOIN_SETTLE_MS","MISSING_THREAD_ID_RECOVERY_THROTTLE_MS","MISSING_THREAD_ID_BUFFER_TIMEOUT_MS","RECONNECT_RECONCILE_DELAY_MS","reconcileGeneration","reconcileInvocationStateOnReconnect","activeThreadId","generation","threadsToCheckSet","ts","threadsToCheck","serverActiveAgentIds","isActiveThread","syntheticId","hadStuckStreamBubble","useSocket","watchedThreadIds","socketRef","joinedRoomsRef","bgStreamRefsRef","bgReplacedInvocationsRef","bgErrorToastsShownRef","bgFinalizedRefsRef","bgSeqRef","userIdRef","getUserId","threadIdRef","missingThreadRecoveryAtRef","invocationThreadMapRef","missingThreadBufferRef","missingThreadBufferTimerRef","queueAutoContinueInFlightRef","callbacksRef","persistJoinedRooms","normalizedWatchedThreadIds","seen","rawId","bootstrapDebugFromStorage","ensureWindowDebugApi","recordInvocationEvent","isDebugEnabled","traceThreadId","socket","io","API_URL","getTransportName","engine","attachNativeCloseLogger","transport","ws","rejoinedRooms","tid","requestMissingThreadCatchUp","sourceMsg","refreshThreadId","lastRecoveryAt","flushBufferedInvocationMessages","resolvedThreadId","buffered","bufferedMsg","routeAgentMessage","routedMsg","originalMsg","recoveredFromBuffer","routeThread","storeThread","isActiveThreadMessage","timeoutId","pendingMsg","notifySkillOptionsChanged","primaryCat","task","currentThread","normalizeQueueForDebug","getQueueStatusesForDebug","normalizedQueue","stateAfterUpdate","shouldTreatAsUser","args","details","handleVisibilityChange","joinRoom","roomThreadId","awaitThreadRoom","timeoutMs","deadline","remaining","leaveRoom","syncRooms","threadIds","targetRooms","watchedThreadId","cancelInvocation"],"mappings":"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"}