cx-viewer 1.0.3 → 1.0.4

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 (1440) hide show
  1. package/README.md +49 -20
  2. package/build.js +15 -0
  3. package/cli.js +102 -18
  4. package/concepts/ar/BodyDiffJSON.md +1 -1
  5. package/concepts/ar/BodyFields.md +30 -33
  6. package/concepts/ar/GlobalSettings.md +165 -167
  7. package/concepts/ar/MainAgent.md +3 -4
  8. package/concepts/ar/ProxySwitch.md +3 -3
  9. package/concepts/ar/QRCode.md +1 -1
  10. package/concepts/ar/ResponseFields.md +29 -41
  11. package/concepts/ar/SubAgent-Search.md +12 -12
  12. package/concepts/ar/Teammate.md +16 -16
  13. package/concepts/ar/ToolsFirst.md +42 -48
  14. package/concepts/ar/TranslateContextPollution.md +9 -9
  15. package/concepts/ar/UltraPlan.md +38 -38
  16. package/concepts/da/BodyDiffJSON.md +2 -2
  17. package/concepts/da/BodyFields.md +30 -33
  18. package/concepts/da/GlobalSettings.md +165 -167
  19. package/concepts/da/MainAgent.md +3 -4
  20. package/concepts/da/ProxySwitch.md +3 -3
  21. package/concepts/da/QRCode.md +1 -1
  22. package/concepts/da/ResponseFields.md +29 -41
  23. package/concepts/da/SubAgent-Search.md +11 -11
  24. package/concepts/da/Teammate.md +16 -16
  25. package/concepts/da/ToolsFirst.md +42 -48
  26. package/concepts/da/TranslateContextPollution.md +9 -9
  27. package/concepts/da/UltraPlan.md +38 -38
  28. package/concepts/de/BodyDiffJSON.md +2 -2
  29. package/concepts/de/BodyFields.md +30 -33
  30. package/concepts/de/GlobalSettings.md +165 -167
  31. package/concepts/de/MainAgent.md +3 -4
  32. package/concepts/de/ProxySwitch.md +3 -3
  33. package/concepts/de/QRCode.md +1 -1
  34. package/concepts/de/ResponseFields.md +29 -41
  35. package/concepts/de/SubAgent-Search.md +11 -11
  36. package/concepts/de/Teammate.md +15 -15
  37. package/concepts/de/ToolsFirst.md +41 -47
  38. package/concepts/de/TranslateContextPollution.md +9 -9
  39. package/concepts/de/UltraPlan.md +38 -38
  40. package/concepts/en/BodyDiffJSON.md +5 -5
  41. package/concepts/en/BodyFields.md +17 -20
  42. package/concepts/en/GlobalSettings.md +49 -51
  43. package/concepts/en/MainAgent.md +8 -8
  44. package/concepts/en/ProxySwitch.md +3 -3
  45. package/concepts/en/QRCode.md +6 -6
  46. package/concepts/en/ResponseFields.md +7 -19
  47. package/concepts/en/SubAgent-Search.md +2 -2
  48. package/concepts/en/Teammate.md +4 -4
  49. package/concepts/en/Tool-apply_patch.md +11 -0
  50. package/concepts/en/Tool-create_goal.md +8 -0
  51. package/concepts/en/Tool-exec.md +88 -0
  52. package/concepts/en/Tool-followup_task.md +10 -0
  53. package/concepts/en/Tool-get_goal.md +5 -0
  54. package/concepts/en/Tool-image_generation.md +5 -0
  55. package/concepts/en/Tool-interrupt_agent.md +9 -0
  56. package/concepts/en/Tool-list_agents.md +9 -0
  57. package/concepts/en/Tool-list_mcp_resource_templates.md +8 -0
  58. package/concepts/en/Tool-list_mcp_resources.md +8 -0
  59. package/concepts/en/Tool-read_mcp_resource.md +10 -0
  60. package/concepts/en/Tool-request_user_input.md +9 -0
  61. package/concepts/en/Tool-send_message.md +10 -0
  62. package/concepts/en/Tool-shell_command.md +12 -0
  63. package/concepts/en/Tool-spawn_agent.md +11 -0
  64. package/concepts/en/Tool-tool_search.md +12 -0
  65. package/concepts/en/Tool-update_goal.md +9 -0
  66. package/concepts/en/Tool-update_plan.md +9 -0
  67. package/concepts/en/Tool-view_image.md +10 -0
  68. package/concepts/en/Tool-wait.md +12 -0
  69. package/concepts/en/Tool-wait_agent.md +9 -0
  70. package/concepts/en/Tool-web_search.md +11 -0
  71. package/concepts/en/Tools.md +29 -58
  72. package/concepts/en/ToolsFirst.md +24 -30
  73. package/concepts/en/TranslateContextPollution.md +10 -38
  74. package/concepts/en/UltraPlan.md +7 -7
  75. package/concepts/es/BodyDiffJSON.md +1 -1
  76. package/concepts/es/BodyFields.md +35 -38
  77. package/concepts/es/GlobalSettings.md +165 -167
  78. package/concepts/es/MainAgent.md +3 -4
  79. package/concepts/es/ProxySwitch.md +3 -3
  80. package/concepts/es/QRCode.md +1 -1
  81. package/concepts/es/ResponseFields.md +28 -40
  82. package/concepts/es/SubAgent-Search.md +12 -12
  83. package/concepts/es/Teammate.md +17 -17
  84. package/concepts/es/ToolsFirst.md +41 -47
  85. package/concepts/es/TranslateContextPollution.md +9 -9
  86. package/concepts/es/UltraPlan.md +38 -38
  87. package/concepts/fr/BodyDiffJSON.md +2 -2
  88. package/concepts/fr/BodyFields.md +35 -38
  89. package/concepts/fr/GlobalSettings.md +165 -167
  90. package/concepts/fr/MainAgent.md +3 -4
  91. package/concepts/fr/ProxySwitch.md +3 -3
  92. package/concepts/fr/QRCode.md +1 -1
  93. package/concepts/fr/ResponseFields.md +25 -37
  94. package/concepts/fr/SubAgent-Search.md +12 -12
  95. package/concepts/fr/Teammate.md +16 -16
  96. package/concepts/fr/ToolsFirst.md +40 -46
  97. package/concepts/fr/TranslateContextPollution.md +9 -9
  98. package/concepts/fr/UltraPlan.md +38 -38
  99. package/concepts/it/BodyDiffJSON.md +2 -2
  100. package/concepts/it/BodyFields.md +35 -38
  101. package/concepts/it/GlobalSettings.md +165 -167
  102. package/concepts/it/MainAgent.md +3 -4
  103. package/concepts/it/ProxySwitch.md +3 -3
  104. package/concepts/it/QRCode.md +1 -1
  105. package/concepts/it/ResponseFields.md +28 -40
  106. package/concepts/it/SubAgent-Search.md +12 -12
  107. package/concepts/it/Teammate.md +17 -17
  108. package/concepts/it/ToolsFirst.md +41 -47
  109. package/concepts/it/TranslateContextPollution.md +9 -9
  110. package/concepts/it/UltraPlan.md +38 -38
  111. package/concepts/ja/BodyDiffJSON.md +1 -1
  112. package/concepts/ja/BodyFields.md +30 -33
  113. package/concepts/ja/GlobalSettings.md +165 -167
  114. package/concepts/ja/MainAgent.md +3 -4
  115. package/concepts/ja/ProxySwitch.md +3 -3
  116. package/concepts/ja/QRCode.md +1 -1
  117. package/concepts/ja/ResponseFields.md +29 -41
  118. package/concepts/ja/SubAgent-Search.md +12 -12
  119. package/concepts/ja/Teammate.md +17 -17
  120. package/concepts/ja/ToolsFirst.md +41 -47
  121. package/concepts/ja/TranslateContextPollution.md +9 -9
  122. package/concepts/ja/UltraPlan.md +38 -38
  123. package/concepts/ko/BodyDiffJSON.md +1 -1
  124. package/concepts/ko/BodyFields.md +30 -33
  125. package/concepts/ko/GlobalSettings.md +165 -167
  126. package/concepts/ko/MainAgent.md +3 -4
  127. package/concepts/ko/ProxySwitch.md +3 -3
  128. package/concepts/ko/QRCode.md +1 -1
  129. package/concepts/ko/ResponseFields.md +29 -41
  130. package/concepts/ko/SubAgent-Search.md +12 -12
  131. package/concepts/ko/Teammate.md +17 -17
  132. package/concepts/ko/ToolsFirst.md +41 -47
  133. package/concepts/ko/TranslateContextPollution.md +9 -9
  134. package/concepts/ko/UltraPlan.md +38 -38
  135. package/concepts/no/BodyDiffJSON.md +2 -2
  136. package/concepts/no/BodyFields.md +30 -33
  137. package/concepts/no/GlobalSettings.md +165 -167
  138. package/concepts/no/MainAgent.md +3 -4
  139. package/concepts/no/ProxySwitch.md +3 -3
  140. package/concepts/no/QRCode.md +1 -1
  141. package/concepts/no/ResponseFields.md +29 -41
  142. package/concepts/no/SubAgent-Search.md +12 -12
  143. package/concepts/no/Teammate.md +17 -17
  144. package/concepts/no/ToolsFirst.md +42 -48
  145. package/concepts/no/TranslateContextPollution.md +9 -9
  146. package/concepts/no/UltraPlan.md +38 -38
  147. package/concepts/pl/BodyDiffJSON.md +2 -2
  148. package/concepts/pl/BodyFields.md +30 -33
  149. package/concepts/pl/GlobalSettings.md +165 -167
  150. package/concepts/pl/MainAgent.md +3 -4
  151. package/concepts/pl/ProxySwitch.md +3 -3
  152. package/concepts/pl/QRCode.md +1 -1
  153. package/concepts/pl/ResponseFields.md +29 -41
  154. package/concepts/pl/SubAgent-Search.md +12 -12
  155. package/concepts/pl/Teammate.md +17 -17
  156. package/concepts/pl/ToolsFirst.md +42 -48
  157. package/concepts/pl/TranslateContextPollution.md +9 -9
  158. package/concepts/pl/UltraPlan.md +38 -38
  159. package/concepts/pt-BR/BodyDiffJSON.md +2 -2
  160. package/concepts/pt-BR/BodyFields.md +30 -33
  161. package/concepts/pt-BR/GlobalSettings.md +165 -167
  162. package/concepts/pt-BR/MainAgent.md +3 -4
  163. package/concepts/pt-BR/ProxySwitch.md +3 -3
  164. package/concepts/pt-BR/QRCode.md +1 -1
  165. package/concepts/pt-BR/ResponseFields.md +29 -41
  166. package/concepts/pt-BR/SubAgent-Search.md +12 -12
  167. package/concepts/pt-BR/Teammate.md +17 -17
  168. package/concepts/pt-BR/ToolsFirst.md +41 -47
  169. package/concepts/pt-BR/TranslateContextPollution.md +9 -9
  170. package/concepts/pt-BR/UltraPlan.md +38 -38
  171. package/concepts/ru/BodyDiffJSON.md +1 -1
  172. package/concepts/ru/BodyFields.md +30 -33
  173. package/concepts/ru/GlobalSettings.md +165 -167
  174. package/concepts/ru/MainAgent.md +3 -4
  175. package/concepts/ru/ProxySwitch.md +3 -3
  176. package/concepts/ru/QRCode.md +1 -1
  177. package/concepts/ru/ResponseFields.md +29 -41
  178. package/concepts/ru/SubAgent-Search.md +12 -12
  179. package/concepts/ru/Teammate.md +17 -17
  180. package/concepts/ru/ToolsFirst.md +41 -47
  181. package/concepts/ru/TranslateContextPollution.md +9 -9
  182. package/concepts/ru/UltraPlan.md +38 -38
  183. package/concepts/th/BodyDiffJSON.md +1 -1
  184. package/concepts/th/BodyFields.md +30 -33
  185. package/concepts/th/GlobalSettings.md +165 -167
  186. package/concepts/th/MainAgent.md +3 -4
  187. package/concepts/th/ProxySwitch.md +3 -3
  188. package/concepts/th/QRCode.md +1 -1
  189. package/concepts/th/ResponseFields.md +29 -41
  190. package/concepts/th/SubAgent-Search.md +12 -12
  191. package/concepts/th/Teammate.md +17 -17
  192. package/concepts/th/ToolsFirst.md +42 -48
  193. package/concepts/th/TranslateContextPollution.md +9 -9
  194. package/concepts/th/UltraPlan.md +38 -38
  195. package/concepts/tr/BodyDiffJSON.md +1 -1
  196. package/concepts/tr/BodyFields.md +30 -33
  197. package/concepts/tr/GlobalSettings.md +165 -167
  198. package/concepts/tr/MainAgent.md +3 -4
  199. package/concepts/tr/ProxySwitch.md +3 -3
  200. package/concepts/tr/QRCode.md +1 -1
  201. package/concepts/tr/ResponseFields.md +29 -41
  202. package/concepts/tr/SubAgent-Search.md +12 -12
  203. package/concepts/tr/Teammate.md +16 -16
  204. package/concepts/tr/ToolsFirst.md +42 -48
  205. package/concepts/tr/TranslateContextPollution.md +9 -9
  206. package/concepts/tr/UltraPlan.md +38 -38
  207. package/concepts/uk/BodyDiffJSON.md +1 -1
  208. package/concepts/uk/BodyFields.md +30 -33
  209. package/concepts/uk/GlobalSettings.md +165 -167
  210. package/concepts/uk/MainAgent.md +3 -4
  211. package/concepts/uk/ProxySwitch.md +3 -3
  212. package/concepts/uk/QRCode.md +1 -1
  213. package/concepts/uk/ResponseFields.md +29 -41
  214. package/concepts/uk/SubAgent-Search.md +12 -12
  215. package/concepts/uk/Teammate.md +17 -17
  216. package/concepts/uk/ToolsFirst.md +42 -48
  217. package/concepts/uk/TranslateContextPollution.md +9 -9
  218. package/concepts/uk/UltraPlan.md +38 -38
  219. package/concepts/zh/BodyDiffJSON.md +4 -4
  220. package/concepts/zh/BodyFields.md +17 -20
  221. package/concepts/zh/GlobalSettings.md +26 -28
  222. package/concepts/zh/MainAgent.md +6 -6
  223. package/concepts/zh/ProxySwitch.md +1 -1
  224. package/concepts/zh/ResponseFields.md +7 -18
  225. package/concepts/zh/SubAgent-Search.md +2 -2
  226. package/concepts/zh/Teammate.md +4 -4
  227. package/concepts/zh/Tool-apply_patch.md +11 -0
  228. package/concepts/zh/Tool-create_goal.md +8 -0
  229. package/concepts/zh/Tool-exec.md +88 -0
  230. package/concepts/zh/Tool-followup_task.md +10 -0
  231. package/concepts/zh/Tool-get_goal.md +5 -0
  232. package/concepts/zh/Tool-image_generation.md +5 -0
  233. package/concepts/zh/Tool-interrupt_agent.md +9 -0
  234. package/concepts/zh/Tool-list_agents.md +9 -0
  235. package/concepts/zh/Tool-list_mcp_resource_templates.md +8 -0
  236. package/concepts/zh/Tool-list_mcp_resources.md +8 -0
  237. package/concepts/zh/Tool-read_mcp_resource.md +10 -0
  238. package/concepts/zh/Tool-request_user_input.md +9 -0
  239. package/concepts/zh/Tool-send_message.md +10 -0
  240. package/concepts/zh/Tool-shell_command.md +12 -0
  241. package/concepts/zh/Tool-spawn_agent.md +11 -0
  242. package/concepts/zh/Tool-tool_search.md +12 -0
  243. package/concepts/zh/Tool-update_goal.md +9 -0
  244. package/concepts/zh/Tool-update_plan.md +9 -0
  245. package/concepts/zh/Tool-view_image.md +10 -0
  246. package/concepts/zh/Tool-wait.md +12 -0
  247. package/concepts/zh/Tool-wait_agent.md +9 -0
  248. package/concepts/zh/Tool-web_search.md +11 -0
  249. package/concepts/zh/Tools.md +29 -58
  250. package/concepts/zh/ToolsFirst.md +21 -27
  251. package/concepts/zh/TranslateContextPollution.md +10 -38
  252. package/concepts/zh/UltraPlan.md +7 -7
  253. package/concepts/zh-TW/BodyFields.md +27 -30
  254. package/concepts/zh-TW/GlobalSettings.md +26 -28
  255. package/concepts/zh-TW/MainAgent.md +0 -1
  256. package/concepts/zh-TW/ProxySwitch.md +22 -22
  257. package/concepts/zh-TW/ResponseFields.md +29 -40
  258. package/concepts/zh-TW/SubAgent-Search.md +12 -12
  259. package/concepts/zh-TW/Teammate.md +16 -16
  260. package/concepts/zh-TW/ToolsFirst.md +41 -47
  261. package/concepts/zh-TW/UltraPlan.md +38 -38
  262. package/dist/assets/App-BZ9oclBj.js +2 -0
  263. package/dist/assets/App-rWON7PuS.css +1 -0
  264. package/dist/assets/MdxEditorPanel-B4lZ7Z_A.js +1 -0
  265. package/dist/assets/MdxEditorPanel-Da_ceLFo.css +1 -0
  266. package/dist/assets/Mobile-B5V_-6Hc.css +1 -0
  267. package/dist/assets/Mobile-C7Hy-TIM.js +1 -0
  268. package/dist/assets/abnfDiagram-VRR7QNED-DYYppIQV.js +1 -0
  269. package/dist/assets/apl-B8ZmNFqK.js +1 -0
  270. package/dist/assets/arc-BT3um7r4.js +1 -0
  271. package/dist/assets/architectureDiagram-ZJ3FMSHR-uweBqnh-.js +1 -0
  272. package/dist/assets/asciiarmor-CIte6N-S.js +1 -0
  273. package/dist/assets/asn1-Ax1-z1nk.js +1 -0
  274. package/dist/assets/asterisk-CLHf-iRz.js +1 -0
  275. package/dist/assets/blockDiagram-677ZJIJ3-DzeI4GyV.js +1 -0
  276. package/dist/assets/brainfuck-CdLnmYpe.js +1 -0
  277. package/dist/assets/c4Diagram-LMCZKHZV-DBI0K7wS.js +1 -0
  278. package/dist/assets/channel-BrN6yx0e.js +1 -0
  279. package/dist/assets/chunk-2Q5K7J3B-DK9JA8Ct.js +1 -0
  280. package/dist/assets/chunk-32BRIVSS-VNg3Ylzs.js +1 -0
  281. package/dist/assets/chunk-5VM5RSS4-DFhufY9o.js +1 -0
  282. package/dist/assets/chunk-EX3LRPZG-B93MHNBT.js +1 -0
  283. package/dist/assets/chunk-JWPE2WC7-C54OW1iN.js +1 -0
  284. package/dist/assets/chunk-MOJQB5TN-lKhWWIDe.js +1 -0
  285. package/dist/assets/chunk-RYQCIY6F-BK2jDXwB.js +1 -0
  286. package/dist/assets/chunk-V7JOEXUC-aLHBmfOc.js +1 -0
  287. package/dist/assets/chunk-VR4S4FIN-Bomuor1h.js +1 -0
  288. package/dist/assets/chunk-XXDRQBXY-BPj05P7g.js +1 -0
  289. package/dist/assets/classDiagram-OUVF2IWQ-COm0X4uJ.js +1 -0
  290. package/dist/assets/classDiagram-v2-EOCWNBFH-COm0X4uJ.js +1 -0
  291. package/dist/assets/clike-BDgEuk0n.js +1 -0
  292. package/dist/assets/clojure-CrPxgQZl.js +1 -0
  293. package/dist/assets/cmake-BknZiLBu.js +1 -0
  294. package/dist/assets/cobol-DN1mHbgw.js +1 -0
  295. package/dist/assets/coffeescript-DTAwRC7M.js +1 -0
  296. package/dist/assets/commonlisp-B4DJ--Bo.js +1 -0
  297. package/dist/assets/cose-bilkent-JH36ORCC-DU44QHSb.js +1 -0
  298. package/dist/assets/crystal-DoipYOOv.js +1 -0
  299. package/dist/assets/css-BeQRP3p5.js +1 -0
  300. package/dist/assets/cynefin-VYW2F7L2-C0dowxsF.js +15 -0
  301. package/dist/assets/cynefinDiagram-TSTJHNR4-C6vNWPUV.js +1 -0
  302. package/dist/assets/cypher-BzELKutH.js +1 -0
  303. package/dist/assets/cytoscape.esm-D0POlJZ1.js +9 -0
  304. package/dist/assets/d-Mh2Rawoc.js +1 -0
  305. package/dist/assets/dagre-VKFMJZFB-aLG4uEb-.js +1 -0
  306. package/dist/assets/defaultLocale-DZ7E7S9R.js +1 -0
  307. package/dist/assets/diagram-FQU43EPY-D5C8GfdU.js +1 -0
  308. package/dist/assets/diagram-G47NLZAW-C9tRw_xi.js +1 -0
  309. package/dist/assets/diagram-NH7WQ7WH-AYxTxwJ2.js +1 -0
  310. package/dist/assets/diagram-OA4YK3LP-BuBE5n9n.js +1 -0
  311. package/dist/assets/diagram-WEI45ONY-Cda7zYeO.js +1 -0
  312. package/dist/assets/diff-B1OtBbfz.js +1 -0
  313. package/dist/assets/dockerfile-Du7niAGi.js +1 -0
  314. package/dist/assets/dtd-So5hjSa8.js +1 -0
  315. package/dist/assets/dylan-Co15g-RX.js +1 -0
  316. package/dist/assets/ebnf-DWrAnno4.js +1 -0
  317. package/dist/assets/ebnfDiagram-CCIWWBDH-DC_OGyoh.js +1 -0
  318. package/dist/assets/ecl-8tbf0rUT.js +1 -0
  319. package/dist/assets/eiffel-BXtlUtEg.js +1 -0
  320. package/dist/assets/elm-BwiUluiH.js +1 -0
  321. package/dist/assets/erDiagram-Q63AITRT-D2G21PVY.js +1 -0
  322. package/dist/assets/erlang-CrHBLi-m.js +1 -0
  323. package/dist/assets/factor-C7nC06Ta.js +1 -0
  324. package/dist/assets/fcl-DKWfryFT.js +1 -0
  325. package/dist/assets/flowDiagram-23GEKE2U-CEQPYHrk.js +1 -0
  326. package/dist/assets/forth-Cg8ASoTj.js +1 -0
  327. package/dist/assets/fortran-BHf_qfFx.js +1 -0
  328. package/dist/assets/ganttDiagram-NO4QXBWP-JStxUtFR.js +1 -0
  329. package/dist/assets/gas-cj_2N_z1.js +1 -0
  330. package/dist/assets/gherkin-BiuTaH40.js +1 -0
  331. package/dist/assets/gitGraphDiagram-IHSO6WYX-BiojPH-V.js +1 -0
  332. package/dist/assets/graph-CnJdn47S.js +1 -0
  333. package/dist/assets/groovy-Bq8cXYUU.js +1 -0
  334. package/dist/assets/haskell-1ANuaeie.js +1 -0
  335. package/dist/assets/haxe-BUNSvWf_.js +1 -0
  336. package/dist/assets/html2canvas.esm-HFdlUwfn.js +20 -0
  337. package/dist/assets/http-DPC2IRQA.js +1 -0
  338. package/dist/assets/idl-DDbIciu_.js +1 -0
  339. package/dist/assets/index-BEyKG3O5.css +1 -0
  340. package/dist/assets/index-BduJoLQ5.js +1 -0
  341. package/dist/assets/index-BqwR8F0v.js +1 -0
  342. package/dist/assets/index-BsycQyrv.js +1 -0
  343. package/dist/assets/index-CFSDxZyA.js +1 -0
  344. package/dist/assets/index-CunNLTHc.js +1 -0
  345. package/dist/assets/index-OGkDFNTK.js +1 -0
  346. package/dist/assets/index-oxOyrL07.js +2 -0
  347. package/dist/assets/index-wvaycTGT.js +1 -0
  348. package/dist/assets/infoDiagram-FWYZ7A6U-Csl_aBIC.js +1 -0
  349. package/dist/assets/init-DMZMl1PR.js +1 -0
  350. package/dist/assets/ishikawaDiagram-FXEZZL3T-CjgGuMwr.js +1 -0
  351. package/dist/assets/javascript-Cet1BUca.js +1 -0
  352. package/dist/assets/journeyDiagram-5HDEW3XC-DUOy1PCq.js +1 -0
  353. package/dist/assets/jszip.min-BxIXdRg4.js +12 -0
  354. package/dist/assets/julia-CdxLCr68.js +1 -0
  355. package/dist/assets/kanban-definition-HUTT4EX6-Cx7GSrSj.js +1 -0
  356. package/dist/assets/katex-CfXf84Fz.js +1 -0
  357. package/dist/assets/layout-CCUE9ZRw.js +1 -0
  358. package/dist/assets/linear-GeBi6jJp.js +1 -0
  359. package/dist/assets/livescript-Bw1Vw7Ae.js +1 -0
  360. package/dist/assets/lua-DM1wbcnc.js +1 -0
  361. package/dist/assets/map-DQeg2hXV.js +1 -0
  362. package/dist/assets/mathematica-BXSv1_O1.js +1 -0
  363. package/dist/assets/mbox-CWY0keg3.js +1 -0
  364. package/dist/assets/mermaid.core-Cy9iVxov.js +7 -0
  365. package/dist/assets/mindmap-definition-LN4V7U3C-CUVxVkK5.js +1 -0
  366. package/dist/assets/mirc-CMLrLVMT.js +1 -0
  367. package/dist/assets/mllike-naqhAFf1.js +1 -0
  368. package/dist/assets/modelica-BvadsaHY.js +1 -0
  369. package/dist/assets/mscgen-DOr-Q10p.js +1 -0
  370. package/dist/assets/mumps-DKTl5Nyj.js +1 -0
  371. package/dist/assets/nginx-DWR90-d1.js +1 -0
  372. package/dist/assets/nsis-ooFGduGn.js +1 -0
  373. package/dist/assets/ntriples-q5jkU4X1.js +1 -0
  374. package/dist/assets/octave-Deu9Ci7_.js +1 -0
  375. package/dist/assets/orbiting-BCD4Vuij.svg +7 -0
  376. package/dist/assets/ordinal-DA-_8pMy.js +1 -0
  377. package/dist/assets/oz-cTQm1aoB.js +1 -0
  378. package/dist/assets/pascal-Oh3VmczP.js +1 -0
  379. package/dist/assets/pegDiagram-2B236MQR-BCF1byLY.js +1 -0
  380. package/dist/assets/perl-BddWF1HQ.js +1 -0
  381. package/dist/assets/pieDiagram-ENE6RG2P-D2cZTo8-.js +1 -0
  382. package/dist/assets/pig-g5ZQNIDr.js +1 -0
  383. package/dist/assets/powershell-CNmQNFVJ.js +1 -0
  384. package/dist/assets/properties-B41DXfv6.js +1 -0
  385. package/dist/assets/protobuf-eEBl31OJ.js +1 -0
  386. package/dist/assets/pug-DRSo4eCK.js +1 -0
  387. package/dist/assets/puppet-ClfRubAD.js +1 -0
  388. package/dist/assets/python-BSflc812.js +1 -0
  389. package/dist/assets/q-BBDx3N9Y.js +1 -0
  390. package/dist/assets/quadrantDiagram-ABIIQ3AL-Bwsn2--F.js +1 -0
  391. package/dist/assets/r-CByC1eO8.js +1 -0
  392. package/dist/assets/railroadDiagram-RFXS5EU6-CLGLpWHs.js +1 -0
  393. package/dist/assets/requirementDiagram-TGXJPOKE-BfmBYwZl.js +1 -0
  394. package/dist/assets/rpm-8t935XkD.js +1 -0
  395. package/dist/assets/ruby-CAgbkLZh.js +1 -0
  396. package/dist/assets/sankeyDiagram-HTMAVEWB-CqZhbyFn.js +1 -0
  397. package/dist/assets/sas-C-JWcRvo.js +1 -0
  398. package/dist/assets/scheme-D7o9RjUX.js +1 -0
  399. package/dist/assets/seqResourceLoaders-Bkh2Rb9i.js +2 -0
  400. package/dist/assets/seqResourceLoaders-Do7Kqg3B.css +41 -0
  401. package/dist/assets/sequenceDiagram-DBY2YBRQ-CcOdXkN2.js +1 -0
  402. package/dist/assets/shell-BXA79DV6.js +1 -0
  403. package/dist/assets/shimmer-BBDejmDf.svg +7 -0
  404. package/dist/assets/sieve-DNwyl0rd.js +1 -0
  405. package/dist/assets/simple-mode-CoQRusFX.js +1 -0
  406. package/dist/assets/sizeCapture-X5ZJPWSS-B4OVmPqu.js +1 -0
  407. package/dist/assets/smalltalk-DggktV6S.js +1 -0
  408. package/dist/assets/solr-D7NRuIPM.js +1 -0
  409. package/dist/assets/sparql-Cr71deJQ.js +1 -0
  410. package/dist/assets/spreadsheet-BMD3tYqw.js +1 -0
  411. package/dist/assets/sql-CbOjXfBR.js +1 -0
  412. package/dist/assets/stateDiagram-2N3HPSRC-Dysun0oO.js +1 -0
  413. package/dist/assets/stateDiagram-v2-6OUMAXLB-BFet8xAz.js +1 -0
  414. package/dist/assets/stex-iDPIkRmr.js +1 -0
  415. package/dist/assets/stylus-nWZizI-c.js +1 -0
  416. package/dist/assets/swift-DOhLK5SG.js +1 -0
  417. package/dist/assets/swimlanes-5IMT3BWC-_30OXwXy.js +2 -0
  418. package/dist/assets/swimlanesDiagram-G3AALYLV-C19viY0G.js +1 -0
  419. package/dist/assets/tcl-CQhJd1WY.js +1 -0
  420. package/dist/assets/textile-D9XqfVtL.js +1 -0
  421. package/dist/assets/tiddlywiki-DfOYgVky.js +1 -0
  422. package/dist/assets/tiki-a0_YLWvV.js +1 -0
  423. package/dist/assets/timeline-definition-FHXFAJF6-X1Xk3onD.js +1 -0
  424. package/dist/assets/toml-ekl3F1YB.js +1 -0
  425. package/dist/assets/troff-Bh_pcXF1.js +1 -0
  426. package/dist/assets/ttcn-M6363IRW.js +1 -0
  427. package/dist/assets/ttcn-cfg-7I2DgJEN.js +1 -0
  428. package/dist/assets/turtle-B5jdxH6D.js +1 -0
  429. package/dist/assets/vb-DM-xPmVv.js +1 -0
  430. package/dist/assets/vbscript-B0qu41Yc.js +1 -0
  431. package/dist/assets/velocity-FCgsuVHf.js +1 -0
  432. package/dist/assets/vendor-antd-Bzi1WuBb.js +17 -0
  433. package/dist/assets/vendor-codemirror-CKTrJd47.js +1 -0
  434. package/dist/assets/vendor-highlight-IFTJ9nxW.js +1 -0
  435. package/dist/assets/vendor-markdown-BN3QLsBu.js +3 -0
  436. package/dist/assets/vendor-mdxeditor-4PbKH6K7.js +2 -0
  437. package/dist/assets/vendor-qrcode-Bnjm0rcu.js +6 -0
  438. package/dist/assets/vendor-react-l0sNRNKZ.js +1 -0
  439. package/dist/assets/vendor-virtuoso-2P4SowHC.js +1 -0
  440. package/dist/assets/vendor-xterm-DckPrCx1.js +37 -0
  441. package/dist/assets/vennDiagram-L72KCM5P-D3fQnGq7.js +1 -0
  442. package/dist/assets/verilog-nrfFvR12.js +1 -0
  443. package/dist/assets/vhdl-WlDXtV-W.js +1 -0
  444. package/dist/assets/wardleyDiagram-EHGQE667-CRhqI6-g.js +1 -0
  445. package/dist/assets/webidl-RIQoSXDx.js +1 -0
  446. package/dist/assets/xquery-BN45G3lJ.js +1 -0
  447. package/dist/assets/xychartDiagram-FW5EYKEG-Cmtgmmtg.js +1 -0
  448. package/dist/assets/yacas-U6gaIVhD.js +1 -0
  449. package/dist/assets/z80-CFe5BHbK.js +1 -0
  450. package/dist/index.html +25 -6
  451. package/dist/voice-packs/default/A_choice_for_your_consideration_sir.MP3 +0 -0
  452. package/dist/voice-packs/default/It_is_done_sir.MP3 +0 -0
  453. package/dist/voice-packs/default/The_plan_awaits_your_approval_sir.MP3 +0 -0
  454. package/dist/voice-packs/default/pack.json +24 -0
  455. package/dist/voice-packs/sanguo/ask.MP3 +0 -0
  456. package/dist/voice-packs/sanguo/end.MP3 +0 -0
  457. package/dist/voice-packs/sanguo/pack.json +24 -0
  458. package/dist/voice-packs/sanguo/plan.MP3 +0 -0
  459. package/electron/diag.js +110 -0
  460. package/electron/main.js +1432 -0
  461. package/electron/menu-model.js +107 -0
  462. package/electron/tab-bar.html +575 -0
  463. package/electron/tab-content-preload.js +66 -0
  464. package/electron/tab-preload.js +24 -0
  465. package/electron/tab-worker.js +142 -0
  466. package/electron/window-state.js +60 -0
  467. package/electron/workspace-preload.js +19 -0
  468. package/findcx.js +4 -0
  469. package/i18n.js +3 -423
  470. package/index.html +30 -0
  471. package/interceptor.js +144 -70
  472. package/jsconfig.json +25 -0
  473. package/lib/approval-reviewer.js +23 -0
  474. package/lib/appserver-bridge.js +1753 -237
  475. package/lib/ask-bridge.js +5 -5
  476. package/lib/cli-args.js +1 -0
  477. package/lib/codex-config.js +157 -18
  478. package/lib/context-watcher.js +6 -65
  479. package/lib/delta-reconstructor.js +74 -52
  480. package/lib/ensure-hooks.js +37 -30
  481. package/lib/interceptor-core.js +490 -43
  482. package/lib/log-watcher.js +3 -8
  483. package/lib/main-agent-entry.js +68 -0
  484. package/lib/openai-body.js +95 -0
  485. package/lib/otel-adapter.js +3 -2
  486. package/lib/otel-receiver.js +1 -2
  487. package/lib/perm-bridge.js +84 -44
  488. package/lib/proxy-env.js +45 -1
  489. package/lib/sdk-adapter.js +241 -51
  490. package/lib/sdk-manager.js +523 -370
  491. package/lib/skills-api.js +364 -0
  492. package/lib/stats-worker.js +21 -21
  493. package/lib/token-usage.js +29 -0
  494. package/lib/updater.js +3 -7
  495. package/package.json +27 -6
  496. package/plugins/.gitkeep +0 -0
  497. package/plugins/README.md +8 -0
  498. package/proxy.js +187 -241
  499. package/pty-manager.js +17 -1
  500. package/public/favicon.ico +0 -0
  501. package/public/voice-packs/default/A_choice_for_your_consideration_sir.MP3 +0 -0
  502. package/public/voice-packs/default/It_is_done_sir.MP3 +0 -0
  503. package/public/voice-packs/default/The_plan_awaits_your_approval_sir.MP3 +0 -0
  504. package/public/voice-packs/default/pack.json +24 -0
  505. package/public/voice-packs/sanguo/ask.MP3 +0 -0
  506. package/public/voice-packs/sanguo/end.MP3 +0 -0
  507. package/public/voice-packs/sanguo/pack.json +24 -0
  508. package/public/voice-packs/sanguo/plan.MP3 +0 -0
  509. package/scripts/check-no-control-bytes.js +130 -0
  510. package/scripts/check-sign-config.sh +85 -0
  511. package/scripts/gen-default-voicepack.js +176 -0
  512. package/scripts/mac-sign.sh +47 -0
  513. package/scripts/npm-pack-dry-run.mjs +20 -0
  514. package/server/lib/approval-modal-prefs.js +72 -0
  515. package/server/lib/context-rules.js +70 -0
  516. package/server/lib/delta-reconstructor.js +403 -0
  517. package/server/lib/tools-xml-formatter.js +91 -0
  518. package/server/lib/voice-pack-events.js +79 -0
  519. package/server.js +420 -86
  520. package/src/App.jsx +638 -0
  521. package/src/App.module.css +1088 -0
  522. package/src/AppBase.jsx +2803 -0
  523. package/src/Mobile.jsx +1348 -0
  524. package/src/components/approval/ApprovalModal.jsx +319 -0
  525. package/src/components/approval/ApprovalModal.module.css +160 -0
  526. package/src/components/approval/ToolApprovalPanel.jsx +111 -0
  527. package/src/components/approval/ToolApprovalPanel.module.css +250 -0
  528. package/src/components/chat/ApprovalPortalContext.js +26 -0
  529. package/src/components/chat/AskQuestionForm.jsx +279 -0
  530. package/src/components/chat/AskTimeoutCountdown.jsx +113 -0
  531. package/src/components/chat/ChatInputBar.jsx +584 -0
  532. package/src/components/chat/ChatInputBar.module.css +656 -0
  533. package/src/components/chat/ChatMessage.jsx +1587 -0
  534. package/src/components/chat/ChatMessage.module.css +1560 -0
  535. package/src/components/chat/ChatView.jsx +3533 -0
  536. package/src/components/chat/ChatView.module.css +418 -0
  537. package/src/components/chat/DiffView.jsx +111 -0
  538. package/src/components/chat/DiffView.module.css +141 -0
  539. package/src/components/chat/RoleFilterBar.jsx +35 -0
  540. package/src/components/chat/RoleFilterBar.module.css +62 -0
  541. package/src/components/chat/controllers/askFlowController.js +789 -0
  542. package/src/components/chat/controllers/permissionController.js +84 -0
  543. package/src/components/chat/controllers/ptyPromptController.js +166 -0
  544. package/src/components/chat/controllers/scrollHighlightController.js +50 -0
  545. package/src/components/chat/controllers/splitDragController.js +135 -0
  546. package/src/components/chat/controllers/toolFileChangeController.js +216 -0
  547. package/src/components/chat/interactionOwnership.js +106 -0
  548. package/src/components/chat/uploadDeferLogic.js +46 -0
  549. package/src/components/common/ConceptHelp.jsx +97 -0
  550. package/src/components/common/ConceptHelp.module.css +151 -0
  551. package/src/components/common/ConfirmRemoveButton.jsx +78 -0
  552. package/src/components/common/CountryFlag.jsx +105 -0
  553. package/src/components/common/CountryFlag.module.css +36 -0
  554. package/src/components/common/DingTalkIcon.jsx +20 -0
  555. package/src/components/common/DiscordIcon.jsx +21 -0
  556. package/src/components/common/FeishuIcon.jsx +23 -0
  557. package/src/components/common/HoverPreviewTip.jsx +62 -0
  558. package/src/components/common/HoverPreviewTip.module.css +21 -0
  559. package/src/components/common/ImageLightbox.jsx +244 -0
  560. package/src/components/common/ImageLightbox.module.css +120 -0
  561. package/src/components/common/MemoryDetailModal.jsx +75 -0
  562. package/src/components/common/OpenFolderIcon.jsx +53 -0
  563. package/src/components/common/OpenFolderIcon.module.css +7 -0
  564. package/src/components/common/PanelResizer.jsx +48 -0
  565. package/src/components/common/PanelResizer.module.css +11 -0
  566. package/src/components/common/QuickAutoApproveRows.jsx +66 -0
  567. package/src/components/common/RefreshIcon.jsx +50 -0
  568. package/src/components/common/RefreshIcon.module.css +26 -0
  569. package/src/components/common/SnapLineOverlay.jsx +47 -0
  570. package/src/components/common/SnapLineOverlay.module.css +31 -0
  571. package/src/components/common/ToolsHelp.jsx +113 -0
  572. package/src/components/common/ToolsHelp.module.css +85 -0
  573. package/src/components/common/WeComIcon.jsx +22 -0
  574. package/src/components/common/quickMenuIcons.jsx +99 -0
  575. package/src/components/common/sharedChrome.module.css +274 -0
  576. package/src/components/dashboard/AppHeader.jsx +2085 -0
  577. package/src/components/dashboard/AppHeader.module.css +676 -0
  578. package/src/components/dashboard/CachePopoverContent.jsx +538 -0
  579. package/src/components/dashboard/CachePopoverContent.module.css +191 -0
  580. package/src/components/dashboard/ContextTab.jsx +769 -0
  581. package/src/components/dashboard/ContextTab.module.css +565 -0
  582. package/src/components/dashboard/DetailPanel.jsx +813 -0
  583. package/src/components/dashboard/DetailPanel.module.css +513 -0
  584. package/src/components/dashboard/LiveTagPopover.jsx +89 -0
  585. package/src/components/dashboard/LiveTagPopover.module.css +67 -0
  586. package/src/components/dashboard/RequestList.jsx +146 -0
  587. package/src/components/dashboard/RequestList.module.css +146 -0
  588. package/src/components/dashboard/TeamSessionPanel.jsx +584 -0
  589. package/src/components/dashboard/TeamSessionPanel.module.css +457 -0
  590. package/src/components/dashboard/UsageWindowPill.jsx +166 -0
  591. package/src/components/dashboard/UsageWindowPill.module.css +140 -0
  592. package/src/components/dashboard/WorkflowRunsPanel.jsx +108 -0
  593. package/src/components/dashboard/WorkflowRunsPanel.module.css +72 -0
  594. package/src/components/dashboard/WorkspaceList.jsx +410 -0
  595. package/src/components/dashboard/WorkspaceList.module.css +254 -0
  596. package/src/components/files/FileContentView.jsx +1013 -0
  597. package/src/components/files/FileContentView.module.css +418 -0
  598. package/src/components/files/FileExplorer.jsx +937 -0
  599. package/src/components/files/FileExplorer.module.css +173 -0
  600. package/src/components/files/MdxEditorPanel.base.css +9 -0
  601. package/src/components/files/MdxEditorPanel.jsx +181 -0
  602. package/src/components/files/MdxEditorPanel.module.css +917 -0
  603. package/src/components/git/DiffMiniMap.jsx +98 -0
  604. package/src/components/git/DiffMiniMap.module.css +17 -0
  605. package/src/components/git/FullFileDiffView.jsx +265 -0
  606. package/src/components/git/FullFileDiffView.module.css +176 -0
  607. package/src/components/git/GitChanges.jsx +461 -0
  608. package/src/components/git/GitChanges.module.css +337 -0
  609. package/src/components/git/GitDiffView.jsx +161 -0
  610. package/src/components/git/GitDiffView.module.css +205 -0
  611. package/src/components/mobile/MobileDrawerCloseButton.jsx +18 -0
  612. package/src/components/mobile/MobileFileExplorer.jsx +231 -0
  613. package/src/components/mobile/MobileFileExplorer.module.css +171 -0
  614. package/src/components/mobile/MobileGitDiff.jsx +293 -0
  615. package/src/components/mobile/MobileGitDiff.module.css +317 -0
  616. package/src/components/mobile/MobileStats.jsx +211 -0
  617. package/src/components/mobile/MobileStats.module.css +75 -0
  618. package/src/components/settings/ImAppendSystemModal.jsx +104 -0
  619. package/src/components/settings/ImConversationModal.jsx +328 -0
  620. package/src/components/settings/ImConversationModal.module.css +49 -0
  621. package/src/components/settings/ImPlatformSettings.jsx +453 -0
  622. package/src/components/settings/ImPlatformSettings.module.css +110 -0
  623. package/src/components/settings/ImSkillsModal.jsx +94 -0
  624. package/src/components/settings/ImStatusChip.jsx +80 -0
  625. package/src/components/settings/ImStatusChip.module.css +36 -0
  626. package/src/components/settings/MessagingModal.jsx +65 -0
  627. package/src/components/settings/MessagingModal.module.css +95 -0
  628. package/src/components/settings/ModelPromptTabs.jsx +118 -0
  629. package/src/components/settings/PluginModal.jsx +423 -0
  630. package/src/components/settings/PluginModal.module.css +136 -0
  631. package/src/components/settings/PreferencesForm.jsx +104 -0
  632. package/src/components/settings/PreferencesForm.module.css +27 -0
  633. package/src/components/settings/ProcessModal.jsx +175 -0
  634. package/src/components/settings/ProcessModal.module.css +21 -0
  635. package/src/components/settings/ProjectAliasEditor.jsx +138 -0
  636. package/src/components/settings/ProjectAliasEditor.module.css +87 -0
  637. package/src/components/settings/ProjectPrefsManagerModal.jsx +123 -0
  638. package/src/components/settings/ProjectPrefsManagerModal.module.css +52 -0
  639. package/src/components/settings/ProxyModal.jsx +286 -0
  640. package/src/components/settings/ProxyModal.module.css +141 -0
  641. package/src/components/settings/SkillsManagerModal.jsx +143 -0
  642. package/src/components/settings/SkillsManagerModal.module.css +143 -0
  643. package/src/components/settings/SystemTextModal.jsx +312 -0
  644. package/src/components/settings/SystemTextModal.module.css +331 -0
  645. package/src/components/settings/VoicePackSettings.jsx +319 -0
  646. package/src/components/settings/VoicePackSettings.module.css +151 -0
  647. package/src/components/settings/imPlatforms.js +177 -0
  648. package/src/components/terminal/CustomUltraplanEditModal.jsx +227 -0
  649. package/src/components/terminal/CustomUltraplanEditModal.module.css +189 -0
  650. package/src/components/terminal/PresetExpertPickerModal.jsx +116 -0
  651. package/src/components/terminal/PresetExpertPickerModal.module.css +90 -0
  652. package/src/components/terminal/PresetModal.jsx +118 -0
  653. package/src/components/terminal/ScratchTerminal.jsx +359 -0
  654. package/src/components/terminal/TerminalPanel.jsx +2021 -0
  655. package/src/components/terminal/TerminalPanel.module.css +872 -0
  656. package/src/components/terminal/TerminalWsContext.jsx +226 -0
  657. package/src/components/terminal/UltraPlanModal.jsx +328 -0
  658. package/src/components/terminal/UltraPlanModal.module.css +527 -0
  659. package/src/components/terminal/UltraplanExpertManagerModal.jsx +114 -0
  660. package/src/components/terminal/UltraplanExpertManagerModal.module.css +91 -0
  661. package/src/components/terminal/UltraplanPanel.jsx +307 -0
  662. package/src/components/terminal/UltraplanPanel.module.css +540 -0
  663. package/src/components/terminal/terminalThemes.js +33 -0
  664. package/src/components/viewers/ImageViewer.jsx +288 -0
  665. package/src/components/viewers/ImageViewer.module.css +203 -0
  666. package/src/components/viewers/JsonViewer.jsx +40 -0
  667. package/src/components/viewers/JsonViewer.module.css +9 -0
  668. package/src/components/viewers/LogTable.jsx +131 -0
  669. package/src/components/viewers/MarkdownBlock.jsx +112 -0
  670. package/src/components/viewers/MarkdownBlock.module.css +157 -0
  671. package/src/components/viewers/ToolResultView.jsx +389 -0
  672. package/src/components/viewers/ToolResultView.module.css +108 -0
  673. package/src/components/viewers/WebResultsView.jsx +74 -0
  674. package/src/components/viewers/WebResultsView.module.css +85 -0
  675. package/src/components/viewers/WorkflowLiveHud.jsx +153 -0
  676. package/src/components/viewers/WorkflowLiveHud.module.css +256 -0
  677. package/src/components/viewers/WorkflowPanel.jsx +243 -0
  678. package/src/components/viewers/WorkflowPanel.module.css +265 -0
  679. package/src/components/viewers/WorkflowTimeline.jsx +83 -0
  680. package/src/components/viewers/WorkflowTimeline.module.css +116 -0
  681. package/src/contexts/SettingsContext.jsx +140 -0
  682. package/src/env.js +54 -0
  683. package/src/global.css +607 -0
  684. package/src/hooks/useMarkdownExport.js +146 -0
  685. package/src/hooks/useMermaidRender.js +193 -0
  686. package/src/hooks/useProjectAlias.js +29 -0
  687. package/src/hooks/useSessionStoragePersistedSet.js +41 -0
  688. package/src/i18n/mdxTranslations.js +472 -0
  689. package/src/i18n.js +12409 -0
  690. package/src/img/ccv-logo.png +0 -0
  691. package/src/img/codex/entrance.svg +7 -0
  692. package/src/img/codex/exit.svg +7 -0
  693. package/src/img/codex/orbiting.svg +7 -0
  694. package/src/img/codex/shimmer.svg +7 -0
  695. package/src/img/codex/thinking.svg +7 -0
  696. package/src/img/codex/tickle.svg +7 -0
  697. package/src/img/codex/waiting.svg +7 -0
  698. package/src/img/codex/writing.svg +7 -0
  699. package/src/img/default-avatar.svg +1 -0
  700. package/src/img/default-model-avatar.svg +1 -0
  701. package/src/img/loading-pet.gif +0 -0
  702. package/src/img/model-codex.svg +2 -0
  703. package/src/img/model-deepseek.svg +2 -0
  704. package/src/img/model-gemini.svg +2 -0
  705. package/src/img/model-glm.svg +2 -0
  706. package/src/img/model-kimi.svg +2 -0
  707. package/src/img/model-minimax.svg +2 -0
  708. package/src/img/model-openai.svg +2 -0
  709. package/src/img/model-qwen.svg +2 -0
  710. package/src/img/teammates/DESIGN.md +165 -0
  711. package/src/img/teammates/analyst.svg +32 -0
  712. package/src/img/teammates/auditor.svg +28 -0
  713. package/src/img/teammates/builder.svg +33 -0
  714. package/src/img/teammates/default.svg +25 -0
  715. package/src/img/teammates/designer.svg +25 -0
  716. package/src/img/teammates/executor.svg +31 -0
  717. package/src/img/teammates/expert.svg +30 -0
  718. package/src/img/teammates/explorer.svg +30 -0
  719. package/src/img/teammates/implementer.svg +34 -0
  720. package/src/img/teammates/investigator.svg +29 -0
  721. package/src/img/teammates/marvel/analyst.svg +26 -0
  722. package/src/img/teammates/marvel/auditor.svg +28 -0
  723. package/src/img/teammates/marvel/builder.svg +15 -0
  724. package/src/img/teammates/marvel/default.svg +25 -0
  725. package/src/img/teammates/marvel/designer.svg +21 -0
  726. package/src/img/teammates/marvel/executor.svg +25 -0
  727. package/src/img/teammates/marvel/expert.svg +31 -0
  728. package/src/img/teammates/marvel/explorer.svg +22 -0
  729. package/src/img/teammates/marvel/implementer.svg +30 -0
  730. package/src/img/teammates/marvel/investigator.svg +21 -0
  731. package/src/img/teammates/marvel/researcher.svg +30 -0
  732. package/src/img/teammates/marvel/reviewer.svg +21 -0
  733. package/src/img/teammates/marvel/scanner.svg +23 -0
  734. package/src/img/teammates/marvel/security.svg +30 -0
  735. package/src/img/teammates/marvel/tracer.svg +19 -0
  736. package/src/img/teammates/marvel/translator.svg +24 -0
  737. package/src/img/teammates/marvel/worker.svg +16 -0
  738. package/src/img/teammates/researcher.svg +35 -0
  739. package/src/img/teammates/reviewer.svg +23 -0
  740. package/src/img/teammates/scanner.svg +31 -0
  741. package/src/img/teammates/security.svg +31 -0
  742. package/src/img/teammates/tracer.svg +30 -0
  743. package/src/img/teammates/translator.svg +32 -0
  744. package/src/img/teammates/worker.svg +29 -0
  745. package/src/main.jsx +30 -0
  746. package/src/tokenInterceptor.js +60 -0
  747. package/src/utils/apiUrl.js +26 -0
  748. package/src/utils/approvalReviewerOptions.js +27 -0
  749. package/src/utils/askFallback.js +21 -0
  750. package/src/utils/askOptionDesc.js +55 -0
  751. package/src/utils/askPortalMatcher.js +54 -0
  752. package/src/utils/autoApproveOptions.js +23 -0
  753. package/src/utils/avatarAnimationPostPass.js +46 -0
  754. package/src/utils/builtinPresets.js +18 -0
  755. package/src/utils/clearCheckpoint.js +154 -0
  756. package/src/utils/commandValidator.js +45 -0
  757. package/src/utils/contentFilter.js +675 -0
  758. package/src/utils/contextRaw.js +17 -0
  759. package/src/utils/contextSidebarNavigation.js +16 -0
  760. package/src/utils/conversationEntryNormalize.js +497 -0
  761. package/src/utils/displayScaleHelper.js +47 -0
  762. package/src/utils/entry-slim.js +594 -0
  763. package/src/utils/entryCache.js +179 -0
  764. package/src/utils/errorReport.js +40 -0
  765. package/src/utils/fileExpandedPathsStorage.js +70 -0
  766. package/src/utils/fileIcons.jsx +36 -0
  767. package/src/utils/fileOpen.js +37 -0
  768. package/src/utils/formatters.js +48 -0
  769. package/src/utils/gitApi.js +50 -0
  770. package/src/utils/gitTreeBuilder.js +19 -0
  771. package/src/utils/helpers.js +462 -0
  772. package/src/utils/identityHeal.js +83 -0
  773. package/src/utils/imOrigin.js +24 -0
  774. package/src/utils/imTr.js +7 -0
  775. package/src/utils/imageCompress.js +83 -0
  776. package/src/utils/imageDownscale.js +28 -0
  777. package/src/utils/imageResize.js +112 -0
  778. package/src/utils/ingestPipeline.js +47 -0
  779. package/src/utils/lazyWithReload.js +53 -0
  780. package/src/utils/markdown.js +30 -0
  781. package/src/utils/markdownIncremental.js +39 -0
  782. package/src/utils/markdownProfiler.js +113 -0
  783. package/src/utils/mdExtensionDetect.js +64 -0
  784. package/src/utils/memoryLinkParser.js +44 -0
  785. package/src/utils/modalMask.js +15 -0
  786. package/src/utils/monotime.js +6 -0
  787. package/src/utils/pinnedMenu.js +55 -0
  788. package/src/utils/presetShortcuts.js +14 -0
  789. package/src/utils/projectAlias.js +135 -0
  790. package/src/utils/promptClassifier.js +111 -0
  791. package/src/utils/promptDetect.js +196 -0
  792. package/src/utils/promptNav.js +60 -0
  793. package/src/utils/ptyChunkBuilder.js +251 -0
  794. package/src/utils/quickMenuHoverIntent.js +35 -0
  795. package/src/utils/rateLimitParser.js +249 -0
  796. package/src/utils/readResultPool.js +106 -0
  797. package/src/utils/refreshCachedItemProp.js +32 -0
  798. package/src/utils/requestTools.js +19 -0
  799. package/src/utils/requestType.js +284 -0
  800. package/src/utils/resizeCalc.js +21 -0
  801. package/src/utils/resolveLocalized.js +17 -0
  802. package/src/utils/seqResourceLoaders.js +79 -0
  803. package/src/utils/sessionManager.js +694 -0
  804. package/src/utils/sessionMerge.js +290 -0
  805. package/src/utils/skillModalController.js +111 -0
  806. package/src/utils/skillsParser.js +116 -0
  807. package/src/utils/slashCommandLabels.js +80 -0
  808. package/src/utils/splitDragCalc.js +73 -0
  809. package/src/utils/stickyBottomController.js +643 -0
  810. package/src/utils/svgSanitize.js +48 -0
  811. package/src/utils/systemTags.js +47 -0
  812. package/src/utils/tCodex.js +20 -0
  813. package/src/utils/teamModalBuilder.js +347 -0
  814. package/src/utils/teamSessionParser.js +186 -0
  815. package/src/utils/teammateAvatars.js +194 -0
  816. package/src/utils/teammateDetector.js +106 -0
  817. package/src/utils/termDiag.js +114 -0
  818. package/src/utils/terminalClipboard.js +117 -0
  819. package/src/utils/terminalWriteQueue.js +398 -0
  820. package/src/utils/thinkingMerge.js +49 -0
  821. package/src/utils/tokenUsage.js +1 -0
  822. package/src/utils/toolCatalog.js +31 -0
  823. package/src/utils/toolNameAliases.js +13 -0
  824. package/src/utils/toolResultBuilder.js +312 -0
  825. package/src/utils/toolResultClassifier.js +16 -0
  826. package/src/utils/toolResultCore.js +161 -0
  827. package/src/utils/toolsDiff.js +44 -0
  828. package/src/utils/toolsXmlFormatter.js +3 -0
  829. package/src/utils/ultraplanController.js +109 -0
  830. package/src/utils/ultraplanExperts.js +86 -0
  831. package/src/utils/ultraplanTemplates.js +152 -0
  832. package/src/utils/userImageRefs.js +49 -0
  833. package/src/utils/voicePackPlayer.js +233 -0
  834. package/src/utils/webResultGrouping.js +111 -0
  835. package/src/utils/workflowFormat.js +52 -0
  836. package/src/utils/workflowRuns.js +118 -0
  837. package/src/utils/workflowStore.js +94 -0
  838. package/vite.config.js +106 -0
  839. package/concepts/ar/CacheRebuild.md +0 -36
  840. package/concepts/ar/KVCacheContent.md +0 -49
  841. package/concepts/ar/Tool-Agent.md +0 -125
  842. package/concepts/ar/Tool-AskUserQuestion.md +0 -75
  843. package/concepts/ar/Tool-Bash.md +0 -167
  844. package/concepts/ar/Tool-Edit.md +0 -46
  845. package/concepts/ar/Tool-EnterPlanMode.md +0 -128
  846. package/concepts/ar/Tool-EnterWorktree.md +0 -56
  847. package/concepts/ar/Tool-ExitPlanMode.md +0 -62
  848. package/concepts/ar/Tool-Glob.md +0 -39
  849. package/concepts/ar/Tool-Grep.md +0 -57
  850. package/concepts/ar/Tool-NotebookEdit.md +0 -33
  851. package/concepts/ar/Tool-Read.md +0 -56
  852. package/concepts/ar/Tool-SendMessage.md +0 -41
  853. package/concepts/ar/Tool-Skill.md +0 -56
  854. package/concepts/ar/Tool-Task.md +0 -51
  855. package/concepts/ar/Tool-TaskCreate.md +0 -78
  856. package/concepts/ar/Tool-TaskGet.md +0 -56
  857. package/concepts/ar/Tool-TaskList.md +0 -56
  858. package/concepts/ar/Tool-TaskOutput.md +0 -40
  859. package/concepts/ar/Tool-TaskStop.md +0 -32
  860. package/concepts/ar/Tool-TaskUpdate.md +0 -123
  861. package/concepts/ar/Tool-TeamCreate.md +0 -38
  862. package/concepts/ar/Tool-TeamDelete.md +0 -30
  863. package/concepts/ar/Tool-WebFetch.md +0 -55
  864. package/concepts/ar/Tool-WebSearch.md +0 -58
  865. package/concepts/ar/Tool-Write.md +0 -39
  866. package/concepts/ar/Tool-executeCode.md +0 -41
  867. package/concepts/ar/Tool-getDiagnostics.md +0 -32
  868. package/concepts/ar/Tools.md +0 -67
  869. package/concepts/da/CacheRebuild.md +0 -36
  870. package/concepts/da/KVCacheContent.md +0 -49
  871. package/concepts/da/Tool-Agent.md +0 -125
  872. package/concepts/da/Tool-AskUserQuestion.md +0 -75
  873. package/concepts/da/Tool-Bash.md +0 -167
  874. package/concepts/da/Tool-Edit.md +0 -46
  875. package/concepts/da/Tool-EnterPlanMode.md +0 -128
  876. package/concepts/da/Tool-EnterWorktree.md +0 -56
  877. package/concepts/da/Tool-ExitPlanMode.md +0 -62
  878. package/concepts/da/Tool-Glob.md +0 -39
  879. package/concepts/da/Tool-Grep.md +0 -57
  880. package/concepts/da/Tool-NotebookEdit.md +0 -33
  881. package/concepts/da/Tool-Read.md +0 -56
  882. package/concepts/da/Tool-SendMessage.md +0 -41
  883. package/concepts/da/Tool-Skill.md +0 -56
  884. package/concepts/da/Tool-Task.md +0 -51
  885. package/concepts/da/Tool-TaskCreate.md +0 -78
  886. package/concepts/da/Tool-TaskGet.md +0 -56
  887. package/concepts/da/Tool-TaskList.md +0 -56
  888. package/concepts/da/Tool-TaskOutput.md +0 -40
  889. package/concepts/da/Tool-TaskStop.md +0 -32
  890. package/concepts/da/Tool-TaskUpdate.md +0 -123
  891. package/concepts/da/Tool-TeamCreate.md +0 -38
  892. package/concepts/da/Tool-TeamDelete.md +0 -30
  893. package/concepts/da/Tool-WebFetch.md +0 -55
  894. package/concepts/da/Tool-WebSearch.md +0 -58
  895. package/concepts/da/Tool-Write.md +0 -39
  896. package/concepts/da/Tool-executeCode.md +0 -41
  897. package/concepts/da/Tool-getDiagnostics.md +0 -32
  898. package/concepts/da/Tools.md +0 -67
  899. package/concepts/de/CacheRebuild.md +0 -36
  900. package/concepts/de/KVCacheContent.md +0 -49
  901. package/concepts/de/Tool-Agent.md +0 -125
  902. package/concepts/de/Tool-AskUserQuestion.md +0 -75
  903. package/concepts/de/Tool-Bash.md +0 -167
  904. package/concepts/de/Tool-Edit.md +0 -46
  905. package/concepts/de/Tool-EnterPlanMode.md +0 -128
  906. package/concepts/de/Tool-EnterWorktree.md +0 -56
  907. package/concepts/de/Tool-ExitPlanMode.md +0 -62
  908. package/concepts/de/Tool-Glob.md +0 -39
  909. package/concepts/de/Tool-Grep.md +0 -57
  910. package/concepts/de/Tool-NotebookEdit.md +0 -33
  911. package/concepts/de/Tool-Read.md +0 -56
  912. package/concepts/de/Tool-SendMessage.md +0 -41
  913. package/concepts/de/Tool-Skill.md +0 -56
  914. package/concepts/de/Tool-Task.md +0 -51
  915. package/concepts/de/Tool-TaskCreate.md +0 -78
  916. package/concepts/de/Tool-TaskGet.md +0 -56
  917. package/concepts/de/Tool-TaskList.md +0 -56
  918. package/concepts/de/Tool-TaskOutput.md +0 -40
  919. package/concepts/de/Tool-TaskStop.md +0 -32
  920. package/concepts/de/Tool-TaskUpdate.md +0 -123
  921. package/concepts/de/Tool-TeamCreate.md +0 -38
  922. package/concepts/de/Tool-TeamDelete.md +0 -30
  923. package/concepts/de/Tool-WebFetch.md +0 -55
  924. package/concepts/de/Tool-WebSearch.md +0 -58
  925. package/concepts/de/Tool-Write.md +0 -39
  926. package/concepts/de/Tool-executeCode.md +0 -41
  927. package/concepts/de/Tool-getDiagnostics.md +0 -32
  928. package/concepts/de/Tools.md +0 -67
  929. package/concepts/en/CacheRebuild.md +0 -36
  930. package/concepts/en/KVCacheContent.md +0 -49
  931. package/concepts/en/Tool-Agent.md +0 -125
  932. package/concepts/en/Tool-AskUserQuestion.md +0 -75
  933. package/concepts/en/Tool-Bash.md +0 -167
  934. package/concepts/en/Tool-Edit.md +0 -46
  935. package/concepts/en/Tool-EnterPlanMode.md +0 -128
  936. package/concepts/en/Tool-EnterWorktree.md +0 -56
  937. package/concepts/en/Tool-ExitPlanMode.md +0 -62
  938. package/concepts/en/Tool-Glob.md +0 -39
  939. package/concepts/en/Tool-Grep.md +0 -57
  940. package/concepts/en/Tool-NotebookEdit.md +0 -33
  941. package/concepts/en/Tool-Read.md +0 -56
  942. package/concepts/en/Tool-SendMessage.md +0 -41
  943. package/concepts/en/Tool-Skill.md +0 -56
  944. package/concepts/en/Tool-Task.md +0 -51
  945. package/concepts/en/Tool-TaskCreate.md +0 -78
  946. package/concepts/en/Tool-TaskGet.md +0 -56
  947. package/concepts/en/Tool-TaskList.md +0 -56
  948. package/concepts/en/Tool-TaskOutput.md +0 -40
  949. package/concepts/en/Tool-TaskStop.md +0 -32
  950. package/concepts/en/Tool-TaskUpdate.md +0 -123
  951. package/concepts/en/Tool-TeamCreate.md +0 -38
  952. package/concepts/en/Tool-TeamDelete.md +0 -30
  953. package/concepts/en/Tool-WebFetch.md +0 -55
  954. package/concepts/en/Tool-WebSearch.md +0 -58
  955. package/concepts/en/Tool-Write.md +0 -39
  956. package/concepts/en/Tool-executeCode.md +0 -41
  957. package/concepts/en/Tool-getDiagnostics.md +0 -32
  958. package/concepts/es/CacheRebuild.md +0 -36
  959. package/concepts/es/KVCacheContent.md +0 -49
  960. package/concepts/es/Tool-Agent.md +0 -125
  961. package/concepts/es/Tool-AskUserQuestion.md +0 -75
  962. package/concepts/es/Tool-Bash.md +0 -167
  963. package/concepts/es/Tool-Edit.md +0 -46
  964. package/concepts/es/Tool-EnterPlanMode.md +0 -128
  965. package/concepts/es/Tool-EnterWorktree.md +0 -56
  966. package/concepts/es/Tool-ExitPlanMode.md +0 -62
  967. package/concepts/es/Tool-Glob.md +0 -39
  968. package/concepts/es/Tool-Grep.md +0 -57
  969. package/concepts/es/Tool-NotebookEdit.md +0 -33
  970. package/concepts/es/Tool-Read.md +0 -56
  971. package/concepts/es/Tool-SendMessage.md +0 -41
  972. package/concepts/es/Tool-Skill.md +0 -56
  973. package/concepts/es/Tool-Task.md +0 -51
  974. package/concepts/es/Tool-TaskCreate.md +0 -78
  975. package/concepts/es/Tool-TaskGet.md +0 -56
  976. package/concepts/es/Tool-TaskList.md +0 -56
  977. package/concepts/es/Tool-TaskOutput.md +0 -40
  978. package/concepts/es/Tool-TaskStop.md +0 -32
  979. package/concepts/es/Tool-TaskUpdate.md +0 -123
  980. package/concepts/es/Tool-TeamCreate.md +0 -38
  981. package/concepts/es/Tool-TeamDelete.md +0 -30
  982. package/concepts/es/Tool-WebFetch.md +0 -55
  983. package/concepts/es/Tool-WebSearch.md +0 -58
  984. package/concepts/es/Tool-Write.md +0 -39
  985. package/concepts/es/Tool-executeCode.md +0 -41
  986. package/concepts/es/Tool-getDiagnostics.md +0 -32
  987. package/concepts/es/Tools.md +0 -67
  988. package/concepts/fr/CacheRebuild.md +0 -36
  989. package/concepts/fr/KVCacheContent.md +0 -49
  990. package/concepts/fr/Tool-Agent.md +0 -125
  991. package/concepts/fr/Tool-AskUserQuestion.md +0 -75
  992. package/concepts/fr/Tool-Bash.md +0 -167
  993. package/concepts/fr/Tool-Edit.md +0 -46
  994. package/concepts/fr/Tool-EnterPlanMode.md +0 -128
  995. package/concepts/fr/Tool-EnterWorktree.md +0 -56
  996. package/concepts/fr/Tool-ExitPlanMode.md +0 -62
  997. package/concepts/fr/Tool-Glob.md +0 -39
  998. package/concepts/fr/Tool-Grep.md +0 -57
  999. package/concepts/fr/Tool-NotebookEdit.md +0 -33
  1000. package/concepts/fr/Tool-Read.md +0 -56
  1001. package/concepts/fr/Tool-SendMessage.md +0 -41
  1002. package/concepts/fr/Tool-Skill.md +0 -56
  1003. package/concepts/fr/Tool-Task.md +0 -51
  1004. package/concepts/fr/Tool-TaskCreate.md +0 -78
  1005. package/concepts/fr/Tool-TaskGet.md +0 -56
  1006. package/concepts/fr/Tool-TaskList.md +0 -56
  1007. package/concepts/fr/Tool-TaskOutput.md +0 -40
  1008. package/concepts/fr/Tool-TaskStop.md +0 -32
  1009. package/concepts/fr/Tool-TaskUpdate.md +0 -123
  1010. package/concepts/fr/Tool-TeamCreate.md +0 -38
  1011. package/concepts/fr/Tool-TeamDelete.md +0 -30
  1012. package/concepts/fr/Tool-WebFetch.md +0 -55
  1013. package/concepts/fr/Tool-WebSearch.md +0 -58
  1014. package/concepts/fr/Tool-Write.md +0 -39
  1015. package/concepts/fr/Tool-executeCode.md +0 -41
  1016. package/concepts/fr/Tool-getDiagnostics.md +0 -32
  1017. package/concepts/fr/Tools.md +0 -67
  1018. package/concepts/it/CacheRebuild.md +0 -36
  1019. package/concepts/it/KVCacheContent.md +0 -49
  1020. package/concepts/it/Tool-Agent.md +0 -125
  1021. package/concepts/it/Tool-AskUserQuestion.md +0 -75
  1022. package/concepts/it/Tool-Bash.md +0 -167
  1023. package/concepts/it/Tool-Edit.md +0 -46
  1024. package/concepts/it/Tool-EnterPlanMode.md +0 -128
  1025. package/concepts/it/Tool-EnterWorktree.md +0 -56
  1026. package/concepts/it/Tool-ExitPlanMode.md +0 -62
  1027. package/concepts/it/Tool-Glob.md +0 -39
  1028. package/concepts/it/Tool-Grep.md +0 -57
  1029. package/concepts/it/Tool-NotebookEdit.md +0 -33
  1030. package/concepts/it/Tool-Read.md +0 -56
  1031. package/concepts/it/Tool-SendMessage.md +0 -41
  1032. package/concepts/it/Tool-Skill.md +0 -56
  1033. package/concepts/it/Tool-Task.md +0 -51
  1034. package/concepts/it/Tool-TaskCreate.md +0 -78
  1035. package/concepts/it/Tool-TaskGet.md +0 -56
  1036. package/concepts/it/Tool-TaskList.md +0 -56
  1037. package/concepts/it/Tool-TaskOutput.md +0 -40
  1038. package/concepts/it/Tool-TaskStop.md +0 -32
  1039. package/concepts/it/Tool-TaskUpdate.md +0 -123
  1040. package/concepts/it/Tool-TeamCreate.md +0 -38
  1041. package/concepts/it/Tool-TeamDelete.md +0 -30
  1042. package/concepts/it/Tool-WebFetch.md +0 -55
  1043. package/concepts/it/Tool-WebSearch.md +0 -58
  1044. package/concepts/it/Tool-Write.md +0 -39
  1045. package/concepts/it/Tool-executeCode.md +0 -41
  1046. package/concepts/it/Tool-getDiagnostics.md +0 -32
  1047. package/concepts/it/Tools.md +0 -67
  1048. package/concepts/ja/CacheRebuild.md +0 -36
  1049. package/concepts/ja/KVCacheContent.md +0 -49
  1050. package/concepts/ja/Tool-Agent.md +0 -125
  1051. package/concepts/ja/Tool-AskUserQuestion.md +0 -75
  1052. package/concepts/ja/Tool-Bash.md +0 -167
  1053. package/concepts/ja/Tool-Edit.md +0 -46
  1054. package/concepts/ja/Tool-EnterPlanMode.md +0 -128
  1055. package/concepts/ja/Tool-EnterWorktree.md +0 -56
  1056. package/concepts/ja/Tool-ExitPlanMode.md +0 -62
  1057. package/concepts/ja/Tool-Glob.md +0 -39
  1058. package/concepts/ja/Tool-Grep.md +0 -57
  1059. package/concepts/ja/Tool-NotebookEdit.md +0 -33
  1060. package/concepts/ja/Tool-Read.md +0 -56
  1061. package/concepts/ja/Tool-SendMessage.md +0 -41
  1062. package/concepts/ja/Tool-Skill.md +0 -56
  1063. package/concepts/ja/Tool-Task.md +0 -51
  1064. package/concepts/ja/Tool-TaskCreate.md +0 -78
  1065. package/concepts/ja/Tool-TaskGet.md +0 -56
  1066. package/concepts/ja/Tool-TaskList.md +0 -56
  1067. package/concepts/ja/Tool-TaskOutput.md +0 -40
  1068. package/concepts/ja/Tool-TaskStop.md +0 -32
  1069. package/concepts/ja/Tool-TaskUpdate.md +0 -123
  1070. package/concepts/ja/Tool-TeamCreate.md +0 -38
  1071. package/concepts/ja/Tool-TeamDelete.md +0 -30
  1072. package/concepts/ja/Tool-WebFetch.md +0 -55
  1073. package/concepts/ja/Tool-WebSearch.md +0 -58
  1074. package/concepts/ja/Tool-Write.md +0 -39
  1075. package/concepts/ja/Tool-executeCode.md +0 -41
  1076. package/concepts/ja/Tool-getDiagnostics.md +0 -32
  1077. package/concepts/ja/Tools.md +0 -67
  1078. package/concepts/ko/CacheRebuild.md +0 -36
  1079. package/concepts/ko/KVCacheContent.md +0 -49
  1080. package/concepts/ko/Tool-Agent.md +0 -125
  1081. package/concepts/ko/Tool-AskUserQuestion.md +0 -75
  1082. package/concepts/ko/Tool-Bash.md +0 -167
  1083. package/concepts/ko/Tool-Edit.md +0 -46
  1084. package/concepts/ko/Tool-EnterPlanMode.md +0 -128
  1085. package/concepts/ko/Tool-EnterWorktree.md +0 -56
  1086. package/concepts/ko/Tool-ExitPlanMode.md +0 -62
  1087. package/concepts/ko/Tool-Glob.md +0 -39
  1088. package/concepts/ko/Tool-Grep.md +0 -57
  1089. package/concepts/ko/Tool-NotebookEdit.md +0 -33
  1090. package/concepts/ko/Tool-Read.md +0 -56
  1091. package/concepts/ko/Tool-SendMessage.md +0 -41
  1092. package/concepts/ko/Tool-Skill.md +0 -56
  1093. package/concepts/ko/Tool-Task.md +0 -51
  1094. package/concepts/ko/Tool-TaskCreate.md +0 -78
  1095. package/concepts/ko/Tool-TaskGet.md +0 -56
  1096. package/concepts/ko/Tool-TaskList.md +0 -56
  1097. package/concepts/ko/Tool-TaskOutput.md +0 -40
  1098. package/concepts/ko/Tool-TaskStop.md +0 -32
  1099. package/concepts/ko/Tool-TaskUpdate.md +0 -123
  1100. package/concepts/ko/Tool-TeamCreate.md +0 -38
  1101. package/concepts/ko/Tool-TeamDelete.md +0 -30
  1102. package/concepts/ko/Tool-WebFetch.md +0 -55
  1103. package/concepts/ko/Tool-WebSearch.md +0 -58
  1104. package/concepts/ko/Tool-Write.md +0 -39
  1105. package/concepts/ko/Tool-executeCode.md +0 -41
  1106. package/concepts/ko/Tool-getDiagnostics.md +0 -32
  1107. package/concepts/ko/Tools.md +0 -67
  1108. package/concepts/no/CacheRebuild.md +0 -36
  1109. package/concepts/no/KVCacheContent.md +0 -49
  1110. package/concepts/no/Tool-Agent.md +0 -125
  1111. package/concepts/no/Tool-AskUserQuestion.md +0 -75
  1112. package/concepts/no/Tool-Bash.md +0 -167
  1113. package/concepts/no/Tool-Edit.md +0 -46
  1114. package/concepts/no/Tool-EnterPlanMode.md +0 -128
  1115. package/concepts/no/Tool-EnterWorktree.md +0 -56
  1116. package/concepts/no/Tool-ExitPlanMode.md +0 -62
  1117. package/concepts/no/Tool-Glob.md +0 -39
  1118. package/concepts/no/Tool-Grep.md +0 -57
  1119. package/concepts/no/Tool-NotebookEdit.md +0 -33
  1120. package/concepts/no/Tool-Read.md +0 -56
  1121. package/concepts/no/Tool-SendMessage.md +0 -41
  1122. package/concepts/no/Tool-Skill.md +0 -56
  1123. package/concepts/no/Tool-Task.md +0 -51
  1124. package/concepts/no/Tool-TaskCreate.md +0 -78
  1125. package/concepts/no/Tool-TaskGet.md +0 -56
  1126. package/concepts/no/Tool-TaskList.md +0 -56
  1127. package/concepts/no/Tool-TaskOutput.md +0 -40
  1128. package/concepts/no/Tool-TaskStop.md +0 -32
  1129. package/concepts/no/Tool-TaskUpdate.md +0 -123
  1130. package/concepts/no/Tool-TeamCreate.md +0 -38
  1131. package/concepts/no/Tool-TeamDelete.md +0 -30
  1132. package/concepts/no/Tool-WebFetch.md +0 -55
  1133. package/concepts/no/Tool-WebSearch.md +0 -58
  1134. package/concepts/no/Tool-Write.md +0 -39
  1135. package/concepts/no/Tool-executeCode.md +0 -41
  1136. package/concepts/no/Tool-getDiagnostics.md +0 -32
  1137. package/concepts/no/Tools.md +0 -67
  1138. package/concepts/pl/CacheRebuild.md +0 -36
  1139. package/concepts/pl/KVCacheContent.md +0 -49
  1140. package/concepts/pl/Tool-Agent.md +0 -125
  1141. package/concepts/pl/Tool-AskUserQuestion.md +0 -75
  1142. package/concepts/pl/Tool-Bash.md +0 -167
  1143. package/concepts/pl/Tool-Edit.md +0 -46
  1144. package/concepts/pl/Tool-EnterPlanMode.md +0 -128
  1145. package/concepts/pl/Tool-EnterWorktree.md +0 -56
  1146. package/concepts/pl/Tool-ExitPlanMode.md +0 -62
  1147. package/concepts/pl/Tool-Glob.md +0 -39
  1148. package/concepts/pl/Tool-Grep.md +0 -57
  1149. package/concepts/pl/Tool-NotebookEdit.md +0 -33
  1150. package/concepts/pl/Tool-Read.md +0 -56
  1151. package/concepts/pl/Tool-SendMessage.md +0 -41
  1152. package/concepts/pl/Tool-Skill.md +0 -56
  1153. package/concepts/pl/Tool-Task.md +0 -51
  1154. package/concepts/pl/Tool-TaskCreate.md +0 -78
  1155. package/concepts/pl/Tool-TaskGet.md +0 -56
  1156. package/concepts/pl/Tool-TaskList.md +0 -56
  1157. package/concepts/pl/Tool-TaskOutput.md +0 -40
  1158. package/concepts/pl/Tool-TaskStop.md +0 -32
  1159. package/concepts/pl/Tool-TaskUpdate.md +0 -123
  1160. package/concepts/pl/Tool-TeamCreate.md +0 -38
  1161. package/concepts/pl/Tool-TeamDelete.md +0 -30
  1162. package/concepts/pl/Tool-WebFetch.md +0 -55
  1163. package/concepts/pl/Tool-WebSearch.md +0 -58
  1164. package/concepts/pl/Tool-Write.md +0 -39
  1165. package/concepts/pl/Tool-executeCode.md +0 -41
  1166. package/concepts/pl/Tool-getDiagnostics.md +0 -32
  1167. package/concepts/pl/Tools.md +0 -67
  1168. package/concepts/pt-BR/CacheRebuild.md +0 -36
  1169. package/concepts/pt-BR/KVCacheContent.md +0 -49
  1170. package/concepts/pt-BR/Tool-Agent.md +0 -125
  1171. package/concepts/pt-BR/Tool-AskUserQuestion.md +0 -75
  1172. package/concepts/pt-BR/Tool-Bash.md +0 -167
  1173. package/concepts/pt-BR/Tool-Edit.md +0 -46
  1174. package/concepts/pt-BR/Tool-EnterPlanMode.md +0 -128
  1175. package/concepts/pt-BR/Tool-EnterWorktree.md +0 -56
  1176. package/concepts/pt-BR/Tool-ExitPlanMode.md +0 -62
  1177. package/concepts/pt-BR/Tool-Glob.md +0 -39
  1178. package/concepts/pt-BR/Tool-Grep.md +0 -57
  1179. package/concepts/pt-BR/Tool-NotebookEdit.md +0 -33
  1180. package/concepts/pt-BR/Tool-Read.md +0 -56
  1181. package/concepts/pt-BR/Tool-SendMessage.md +0 -41
  1182. package/concepts/pt-BR/Tool-Skill.md +0 -56
  1183. package/concepts/pt-BR/Tool-Task.md +0 -51
  1184. package/concepts/pt-BR/Tool-TaskCreate.md +0 -78
  1185. package/concepts/pt-BR/Tool-TaskGet.md +0 -56
  1186. package/concepts/pt-BR/Tool-TaskList.md +0 -56
  1187. package/concepts/pt-BR/Tool-TaskOutput.md +0 -40
  1188. package/concepts/pt-BR/Tool-TaskStop.md +0 -32
  1189. package/concepts/pt-BR/Tool-TaskUpdate.md +0 -123
  1190. package/concepts/pt-BR/Tool-TeamCreate.md +0 -38
  1191. package/concepts/pt-BR/Tool-TeamDelete.md +0 -30
  1192. package/concepts/pt-BR/Tool-WebFetch.md +0 -55
  1193. package/concepts/pt-BR/Tool-WebSearch.md +0 -58
  1194. package/concepts/pt-BR/Tool-Write.md +0 -39
  1195. package/concepts/pt-BR/Tool-executeCode.md +0 -41
  1196. package/concepts/pt-BR/Tool-getDiagnostics.md +0 -32
  1197. package/concepts/pt-BR/Tools.md +0 -67
  1198. package/concepts/ru/CacheRebuild.md +0 -36
  1199. package/concepts/ru/KVCacheContent.md +0 -49
  1200. package/concepts/ru/Tool-Agent.md +0 -125
  1201. package/concepts/ru/Tool-AskUserQuestion.md +0 -75
  1202. package/concepts/ru/Tool-Bash.md +0 -167
  1203. package/concepts/ru/Tool-Edit.md +0 -46
  1204. package/concepts/ru/Tool-EnterPlanMode.md +0 -128
  1205. package/concepts/ru/Tool-EnterWorktree.md +0 -56
  1206. package/concepts/ru/Tool-ExitPlanMode.md +0 -62
  1207. package/concepts/ru/Tool-Glob.md +0 -39
  1208. package/concepts/ru/Tool-Grep.md +0 -57
  1209. package/concepts/ru/Tool-NotebookEdit.md +0 -33
  1210. package/concepts/ru/Tool-Read.md +0 -56
  1211. package/concepts/ru/Tool-SendMessage.md +0 -41
  1212. package/concepts/ru/Tool-Skill.md +0 -56
  1213. package/concepts/ru/Tool-Task.md +0 -51
  1214. package/concepts/ru/Tool-TaskCreate.md +0 -78
  1215. package/concepts/ru/Tool-TaskGet.md +0 -56
  1216. package/concepts/ru/Tool-TaskList.md +0 -56
  1217. package/concepts/ru/Tool-TaskOutput.md +0 -40
  1218. package/concepts/ru/Tool-TaskStop.md +0 -32
  1219. package/concepts/ru/Tool-TaskUpdate.md +0 -123
  1220. package/concepts/ru/Tool-TeamCreate.md +0 -38
  1221. package/concepts/ru/Tool-TeamDelete.md +0 -30
  1222. package/concepts/ru/Tool-WebFetch.md +0 -55
  1223. package/concepts/ru/Tool-WebSearch.md +0 -58
  1224. package/concepts/ru/Tool-Write.md +0 -39
  1225. package/concepts/ru/Tool-executeCode.md +0 -41
  1226. package/concepts/ru/Tool-getDiagnostics.md +0 -32
  1227. package/concepts/ru/Tools.md +0 -67
  1228. package/concepts/th/CacheRebuild.md +0 -36
  1229. package/concepts/th/KVCacheContent.md +0 -49
  1230. package/concepts/th/Tool-Agent.md +0 -125
  1231. package/concepts/th/Tool-AskUserQuestion.md +0 -75
  1232. package/concepts/th/Tool-Bash.md +0 -167
  1233. package/concepts/th/Tool-Edit.md +0 -46
  1234. package/concepts/th/Tool-EnterPlanMode.md +0 -128
  1235. package/concepts/th/Tool-EnterWorktree.md +0 -56
  1236. package/concepts/th/Tool-ExitPlanMode.md +0 -62
  1237. package/concepts/th/Tool-Glob.md +0 -39
  1238. package/concepts/th/Tool-Grep.md +0 -57
  1239. package/concepts/th/Tool-NotebookEdit.md +0 -33
  1240. package/concepts/th/Tool-Read.md +0 -56
  1241. package/concepts/th/Tool-SendMessage.md +0 -41
  1242. package/concepts/th/Tool-Skill.md +0 -56
  1243. package/concepts/th/Tool-Task.md +0 -51
  1244. package/concepts/th/Tool-TaskCreate.md +0 -78
  1245. package/concepts/th/Tool-TaskGet.md +0 -56
  1246. package/concepts/th/Tool-TaskList.md +0 -56
  1247. package/concepts/th/Tool-TaskOutput.md +0 -40
  1248. package/concepts/th/Tool-TaskStop.md +0 -32
  1249. package/concepts/th/Tool-TaskUpdate.md +0 -123
  1250. package/concepts/th/Tool-TeamCreate.md +0 -38
  1251. package/concepts/th/Tool-TeamDelete.md +0 -30
  1252. package/concepts/th/Tool-WebFetch.md +0 -55
  1253. package/concepts/th/Tool-WebSearch.md +0 -58
  1254. package/concepts/th/Tool-Write.md +0 -39
  1255. package/concepts/th/Tool-executeCode.md +0 -41
  1256. package/concepts/th/Tool-getDiagnostics.md +0 -32
  1257. package/concepts/th/Tools.md +0 -67
  1258. package/concepts/tr/CacheRebuild.md +0 -36
  1259. package/concepts/tr/KVCacheContent.md +0 -49
  1260. package/concepts/tr/Tool-Agent.md +0 -125
  1261. package/concepts/tr/Tool-AskUserQuestion.md +0 -75
  1262. package/concepts/tr/Tool-Bash.md +0 -167
  1263. package/concepts/tr/Tool-Edit.md +0 -46
  1264. package/concepts/tr/Tool-EnterPlanMode.md +0 -128
  1265. package/concepts/tr/Tool-EnterWorktree.md +0 -56
  1266. package/concepts/tr/Tool-ExitPlanMode.md +0 -62
  1267. package/concepts/tr/Tool-Glob.md +0 -39
  1268. package/concepts/tr/Tool-Grep.md +0 -57
  1269. package/concepts/tr/Tool-NotebookEdit.md +0 -33
  1270. package/concepts/tr/Tool-Read.md +0 -56
  1271. package/concepts/tr/Tool-SendMessage.md +0 -41
  1272. package/concepts/tr/Tool-Skill.md +0 -56
  1273. package/concepts/tr/Tool-Task.md +0 -51
  1274. package/concepts/tr/Tool-TaskCreate.md +0 -78
  1275. package/concepts/tr/Tool-TaskGet.md +0 -56
  1276. package/concepts/tr/Tool-TaskList.md +0 -56
  1277. package/concepts/tr/Tool-TaskOutput.md +0 -40
  1278. package/concepts/tr/Tool-TaskStop.md +0 -32
  1279. package/concepts/tr/Tool-TaskUpdate.md +0 -123
  1280. package/concepts/tr/Tool-TeamCreate.md +0 -38
  1281. package/concepts/tr/Tool-TeamDelete.md +0 -30
  1282. package/concepts/tr/Tool-WebFetch.md +0 -55
  1283. package/concepts/tr/Tool-WebSearch.md +0 -58
  1284. package/concepts/tr/Tool-Write.md +0 -39
  1285. package/concepts/tr/Tool-executeCode.md +0 -41
  1286. package/concepts/tr/Tool-getDiagnostics.md +0 -32
  1287. package/concepts/tr/Tools.md +0 -67
  1288. package/concepts/uk/CacheRebuild.md +0 -36
  1289. package/concepts/uk/KVCacheContent.md +0 -49
  1290. package/concepts/uk/Tool-Agent.md +0 -125
  1291. package/concepts/uk/Tool-AskUserQuestion.md +0 -75
  1292. package/concepts/uk/Tool-Bash.md +0 -167
  1293. package/concepts/uk/Tool-Edit.md +0 -46
  1294. package/concepts/uk/Tool-EnterPlanMode.md +0 -128
  1295. package/concepts/uk/Tool-EnterWorktree.md +0 -56
  1296. package/concepts/uk/Tool-ExitPlanMode.md +0 -62
  1297. package/concepts/uk/Tool-Glob.md +0 -39
  1298. package/concepts/uk/Tool-Grep.md +0 -57
  1299. package/concepts/uk/Tool-NotebookEdit.md +0 -33
  1300. package/concepts/uk/Tool-Read.md +0 -56
  1301. package/concepts/uk/Tool-SendMessage.md +0 -41
  1302. package/concepts/uk/Tool-Skill.md +0 -56
  1303. package/concepts/uk/Tool-Task.md +0 -51
  1304. package/concepts/uk/Tool-TaskCreate.md +0 -78
  1305. package/concepts/uk/Tool-TaskGet.md +0 -56
  1306. package/concepts/uk/Tool-TaskList.md +0 -56
  1307. package/concepts/uk/Tool-TaskOutput.md +0 -40
  1308. package/concepts/uk/Tool-TaskStop.md +0 -32
  1309. package/concepts/uk/Tool-TaskUpdate.md +0 -123
  1310. package/concepts/uk/Tool-TeamCreate.md +0 -38
  1311. package/concepts/uk/Tool-TeamDelete.md +0 -30
  1312. package/concepts/uk/Tool-WebFetch.md +0 -55
  1313. package/concepts/uk/Tool-WebSearch.md +0 -58
  1314. package/concepts/uk/Tool-Write.md +0 -39
  1315. package/concepts/uk/Tool-executeCode.md +0 -41
  1316. package/concepts/uk/Tool-getDiagnostics.md +0 -32
  1317. package/concepts/uk/Tools.md +0 -67
  1318. package/concepts/zh/CacheRebuild.md +0 -36
  1319. package/concepts/zh/KVCacheContent.md +0 -49
  1320. package/concepts/zh/Tool-Agent.md +0 -125
  1321. package/concepts/zh/Tool-AskUserQuestion.md +0 -75
  1322. package/concepts/zh/Tool-Bash.md +0 -167
  1323. package/concepts/zh/Tool-Edit.md +0 -46
  1324. package/concepts/zh/Tool-EnterPlanMode.md +0 -128
  1325. package/concepts/zh/Tool-EnterWorktree.md +0 -56
  1326. package/concepts/zh/Tool-ExitPlanMode.md +0 -62
  1327. package/concepts/zh/Tool-Glob.md +0 -39
  1328. package/concepts/zh/Tool-Grep.md +0 -57
  1329. package/concepts/zh/Tool-NotebookEdit.md +0 -33
  1330. package/concepts/zh/Tool-Read.md +0 -56
  1331. package/concepts/zh/Tool-SendMessage.md +0 -41
  1332. package/concepts/zh/Tool-Skill.md +0 -56
  1333. package/concepts/zh/Tool-Task.md +0 -51
  1334. package/concepts/zh/Tool-TaskCreate.md +0 -78
  1335. package/concepts/zh/Tool-TaskGet.md +0 -56
  1336. package/concepts/zh/Tool-TaskList.md +0 -56
  1337. package/concepts/zh/Tool-TaskOutput.md +0 -40
  1338. package/concepts/zh/Tool-TaskStop.md +0 -32
  1339. package/concepts/zh/Tool-TaskUpdate.md +0 -123
  1340. package/concepts/zh/Tool-TeamCreate.md +0 -38
  1341. package/concepts/zh/Tool-TeamDelete.md +0 -30
  1342. package/concepts/zh/Tool-WebFetch.md +0 -55
  1343. package/concepts/zh/Tool-WebSearch.md +0 -58
  1344. package/concepts/zh/Tool-Write.md +0 -39
  1345. package/concepts/zh/Tool-executeCode.md +0 -41
  1346. package/concepts/zh/Tool-getDiagnostics.md +0 -32
  1347. package/concepts/zh-TW/CacheRebuild.md +0 -36
  1348. package/concepts/zh-TW/KVCacheContent.md +0 -49
  1349. package/concepts/zh-TW/Tool-Agent.md +0 -125
  1350. package/concepts/zh-TW/Tool-AskUserQuestion.md +0 -75
  1351. package/concepts/zh-TW/Tool-Bash.md +0 -167
  1352. package/concepts/zh-TW/Tool-Edit.md +0 -46
  1353. package/concepts/zh-TW/Tool-EnterPlanMode.md +0 -128
  1354. package/concepts/zh-TW/Tool-EnterWorktree.md +0 -56
  1355. package/concepts/zh-TW/Tool-ExitPlanMode.md +0 -62
  1356. package/concepts/zh-TW/Tool-Glob.md +0 -39
  1357. package/concepts/zh-TW/Tool-Grep.md +0 -57
  1358. package/concepts/zh-TW/Tool-NotebookEdit.md +0 -33
  1359. package/concepts/zh-TW/Tool-Read.md +0 -56
  1360. package/concepts/zh-TW/Tool-SendMessage.md +0 -41
  1361. package/concepts/zh-TW/Tool-Skill.md +0 -56
  1362. package/concepts/zh-TW/Tool-Task.md +0 -51
  1363. package/concepts/zh-TW/Tool-TaskCreate.md +0 -78
  1364. package/concepts/zh-TW/Tool-TaskGet.md +0 -56
  1365. package/concepts/zh-TW/Tool-TaskList.md +0 -56
  1366. package/concepts/zh-TW/Tool-TaskOutput.md +0 -40
  1367. package/concepts/zh-TW/Tool-TaskStop.md +0 -32
  1368. package/concepts/zh-TW/Tool-TaskUpdate.md +0 -123
  1369. package/concepts/zh-TW/Tool-TeamCreate.md +0 -38
  1370. package/concepts/zh-TW/Tool-TeamDelete.md +0 -30
  1371. package/concepts/zh-TW/Tool-WebFetch.md +0 -55
  1372. package/concepts/zh-TW/Tool-WebSearch.md +0 -58
  1373. package/concepts/zh-TW/Tool-Write.md +0 -39
  1374. package/concepts/zh-TW/Tool-executeCode.md +0 -41
  1375. package/concepts/zh-TW/Tool-getDiagnostics.md +0 -32
  1376. package/concepts/zh-TW/Tools.md +0 -67
  1377. package/dist/assets/App-BN2YmKSu.js +0 -41
  1378. package/dist/assets/App-fG2r3jFq.css +0 -1
  1379. package/dist/assets/AppHeader-BqUGBbBx.css +0 -41
  1380. package/dist/assets/AppHeader.module-CvH9GQQ2.js +0 -1250
  1381. package/dist/assets/Mobile-BnDkLcBv.css +0 -1
  1382. package/dist/assets/Mobile-CbC8YD3O.js +0 -10
  1383. package/dist/assets/_baseUniq-B2ddYY2A.js +0 -1
  1384. package/dist/assets/arc-DFPOHgcd.js +0 -1
  1385. package/dist/assets/architectureDiagram-Q4EWVU46-1tuXixQv.js +0 -36
  1386. package/dist/assets/blockDiagram-DXYQGD6D-BfVKQPAV.js +0 -132
  1387. package/dist/assets/c4Diagram-AHTNJAMY-Bua8O4-1.js +0 -10
  1388. package/dist/assets/channel-Cf9uPxYW.js +0 -1
  1389. package/dist/assets/chunk-4BX2VUAB-YOIkSNn_.js +0 -1
  1390. package/dist/assets/chunk-4TB4RGXK-CjZt-To5.js +0 -206
  1391. package/dist/assets/chunk-55IACEB6-BAEfMF5S.js +0 -1
  1392. package/dist/assets/chunk-EDXVE4YY-BUYDmLXU.js +0 -1
  1393. package/dist/assets/chunk-FMBD7UC4-Cw_LDap-.js +0 -15
  1394. package/dist/assets/chunk-OYMX7WX6-PlfZFFxd.js +0 -231
  1395. package/dist/assets/chunk-QZHKN3VN-C2ReFZl_.js +0 -1
  1396. package/dist/assets/chunk-YZCP3GAM-B7IVGkPB.js +0 -1
  1397. package/dist/assets/classDiagram-6PBFFD2Q-DdwVeNLZ.js +0 -1
  1398. package/dist/assets/classDiagram-v2-HSJHXN6E-DdwVeNLZ.js +0 -1
  1399. package/dist/assets/clone-C8Lz0121.js +0 -1
  1400. package/dist/assets/cose-bilkent-S5V4N54A-M6rBKf0y.js +0 -1
  1401. package/dist/assets/cytoscape.esm-DxGcaOPV.js +0 -331
  1402. package/dist/assets/dagre-KV5264BT-UPacTWnL.js +0 -4
  1403. package/dist/assets/defaultLocale-DX6XiGOO.js +0 -1
  1404. package/dist/assets/diagram-5BDNPKRD-Cjjtnh0e.js +0 -10
  1405. package/dist/assets/diagram-G4DWMVQ6-CjXILMP0.js +0 -24
  1406. package/dist/assets/diagram-MMDJMWI5-C_-XZ9gc.js +0 -43
  1407. package/dist/assets/diagram-TYMM5635-Dxe2GxUR.js +0 -24
  1408. package/dist/assets/erDiagram-SMLLAGMA-1w-wtgMd.js +0 -85
  1409. package/dist/assets/flowDiagram-DWJPFMVM-B9naMGCj.js +0 -162
  1410. package/dist/assets/ganttDiagram-T4ZO3ILL-BPZBdhPv.js +0 -292
  1411. package/dist/assets/gitGraphDiagram-UUTBAWPF-_P9PdiGG.js +0 -106
  1412. package/dist/assets/graph-CjOY8lRz.js +0 -1
  1413. package/dist/assets/html2canvas.esm-QH1iLAAe.js +0 -22
  1414. package/dist/assets/index-BcCW9op4.js +0 -41
  1415. package/dist/assets/index-DCtZ2KSX.css +0 -1
  1416. package/dist/assets/infoDiagram-42DDH7IO-Ch8SOTtq.js +0 -2
  1417. package/dist/assets/init-Gi6I4Gst.js +0 -1
  1418. package/dist/assets/ishikawaDiagram-UXIWVN3A-XLscQrJT.js +0 -70
  1419. package/dist/assets/journeyDiagram-VCZTEJTY-C3FQ_QPk.js +0 -139
  1420. package/dist/assets/kanban-definition-6JOO6SKY-DIQDTOi3.js +0 -89
  1421. package/dist/assets/katex-DkKDou_j.js +0 -257
  1422. package/dist/assets/layout-DO9W0X_b.js +0 -1
  1423. package/dist/assets/linear-ClCJqwn1.js +0 -1
  1424. package/dist/assets/mermaid.core-BW02B1TS.js +0 -308
  1425. package/dist/assets/min-BuzClhio.js +0 -1
  1426. package/dist/assets/mindmap-definition-QFDTVHPH-DuCaTeZu.js +0 -96
  1427. package/dist/assets/ordinal-Cboi1Yqb.js +0 -1
  1428. package/dist/assets/pieDiagram-DEJITSTG-BZoZ6CI1.js +0 -30
  1429. package/dist/assets/quadrantDiagram-34T5L4WZ-DFNwvtmc.js +0 -7
  1430. package/dist/assets/requirementDiagram-MS252O5E-DPG-7raV.js +0 -84
  1431. package/dist/assets/sankeyDiagram-XADWPNL6-Bp92e1ie.js +0 -10
  1432. package/dist/assets/sequenceDiagram-FGHM5R23-C6ADwqJY.js +0 -157
  1433. package/dist/assets/stateDiagram-FHFEXIEX-BfrwZGmF.js +0 -1
  1434. package/dist/assets/stateDiagram-v2-QKLJ7IA2-4gBW7EPI.js +0 -1
  1435. package/dist/assets/timeline-definition-GMOUNBTQ-Bb-TxYx2.js +0 -120
  1436. package/dist/assets/vennDiagram-DHZGUBPP-DTRiNXJu.js +0 -34
  1437. package/dist/assets/wardley-RL74JXVD-C8j_kjXS.js +0 -162
  1438. package/dist/assets/wardleyDiagram-NUSXRM2D-CvICMc3N.js +0 -20
  1439. package/dist/assets/xychartDiagram-5P7HB3ND-DI0bBGwq.js +0 -7
  1440. package/lib/kv-cache-analyzer.js +0 -164
@@ -0,0 +1,2021 @@
1
+ // ============================================================================
2
+ // 主 terminal 组件 —— 渲染 Codex TUI 的"大 terminal"
3
+ // 工具栏下方的"小/scratch terminal"是另外一个独立组件,见 ScratchTerminal.jsx
4
+ // CSS:主 terminal 用 .terminalContainer + .terminalHost;scratch 用 .scratchInner + .scratchHost
5
+ // ============================================================================
6
+ import React from 'react';
7
+ import { message, Tooltip, Popover, Popconfirm, Button, Checkbox, Modal } from 'antd';
8
+ import { Terminal } from '@xterm/xterm';
9
+ import { FitAddon } from '@xterm/addon-fit';
10
+ import { WebglAddon } from '@xterm/addon-webgl';
11
+ import { WebLinksAddon } from '@xterm/addon-web-links';
12
+ import { Unicode11Addon } from '@xterm/addon-unicode11';
13
+ import '@xterm/xterm/css/xterm.css';
14
+ import { t } from '../../i18n';
15
+ import { TerminalWsContext } from './TerminalWsContext';
16
+ import { apiUrl } from '../../utils/apiUrl';
17
+ import { isMobile, isIOS, isAndroid, isPad, isWindows, isMac } from '../../env';
18
+ import styles from './TerminalPanel.module.css';
19
+ import { BUILTIN_PRESETS } from '../../utils/builtinPresets.js';
20
+ import { buildLocalUltraplan } from '../../utils/ultraplanTemplates';
21
+ import { UltraplanController } from '../../utils/ultraplanController';
22
+ import { buildBracketPasteSubmitChunks, BRACKET_PASTE_SUBMIT_SETTLE_MS, sanitizeBracketPasteText } from '../../utils/ptyChunkBuilder';
23
+ import { clipboardKeyAction, copyTextToClipboard, planPasteSend } from '../../utils/terminalClipboard';
24
+ import CustomUltraplanEditModal from './CustomUltraplanEditModal';
25
+ import UltraplanExpertManagerModal from './UltraplanExpertManagerModal';
26
+ import { visibleExpertKeys } from '../../utils/ultraplanExperts';
27
+ import { TerminalWriteQueue, INBAND_RESET } from '../../utils/terminalWriteQueue';
28
+ import { installTermDiag, diagCount } from '../../utils/termDiag';
29
+ import { downscaleForRetina } from '../../utils/imageDownscale';
30
+ import { buildPresetShortcutsPayload } from '../../utils/presetShortcuts';
31
+ import ImageLightbox from '../common/ImageLightbox';
32
+ import ConfirmRemoveButton from '../common/ConfirmRemoveButton';
33
+ import ScratchTerminal from './ScratchTerminal';
34
+ import { darkTerminalTheme, lightTerminalTheme, terminalFontFamily } from './terminalThemes';
35
+ import { resizeImageIfNeeded } from '../../utils/imageResize';
36
+ import UltraplanPanel, { readUltraplanPopoverSize, ultraplanOverlayInnerStyle } from './UltraplanPanel';
37
+ import { AgentTeamIcon, UploadIcon, TrashIcon, SPARKLE_MASK_STYLE, ULTRAPLAN_MASK_STYLE } from '../common/quickMenuIcons';
38
+ import QuickAutoApproveRows from '../common/QuickAutoApproveRows';
39
+ import { createQuickMenuHoverIntent } from '../../utils/quickMenuHoverIntent';
40
+ import chrome from '../common/sharedChrome.module.css';
41
+
42
+ // WebGL longtask 自动降级常量
43
+ const WEBGL_STALL_MS = 200; // 单次 longtask 阈值 (ms)
44
+ const WEBGL_STALL_COUNT = 3; // 触发降级的 stall 次数
45
+ const WEBGL_STALL_WINDOW_MS = 30000; // 滑动窗口 (ms)
46
+ const WEBGL_GRACE_MS = 5000; // 初始化宽限期 (ms)
47
+ const WEBGL_STICKY_KEY = 'cxv_webgl_disabled_until';
48
+ const WEBGL_STICKY_TTL_MS = 7 * 24 * 3600 * 1000; // 7 天后自动重试
49
+
50
+ // 渲染器平台策略:Android(移动端 DOM 卡顿明显)无条件 WebGL;macOS 桌面在 longtask 守卫
51
+ // 可用时启用 WebGL(能力门:Safari 无 'longtask' PerformanceObserver,守卫失效则不冒险,
52
+ // 留 DOM;Chrome/Edge/Electron 带完整降级安全网)。Windows/Linux 维持 DOM(GPU 长任务/
53
+ // 花屏实测多发)。isIOS 排除 iPadOS(iPad 桌面 UA 的 navigator.platform 是 MacIntel,
54
+ // 会误命中 isMac)。
55
+ const WEBGL_RENDERER = isAndroid || (isMac && !isIOS
56
+ && typeof PerformanceObserver !== 'undefined'
57
+ && !!PerformanceObserver.supportedEntryTypes?.includes('longtask'));
58
+
59
+ const SCRATCH_OPEN_KEY = 'cx-viewer-scratch-open';
60
+ const SCRATCH_HEIGHT_KEY = 'cx-viewer-scratch-height';
61
+ const SCRATCH_TABS_KEY = 'cx-viewer-scratch-tabs';
62
+ const SCRATCH_ACTIVE_TAB_KEY = 'cx-viewer-scratch-active-tab';
63
+ // 注:.scratchWrap 用 outline + outline-offset:-4px 画 focus 环(不占布局),存储/clamp 的高度
64
+ // 即可见高度本身,不再被边框吞噬;fitAddon 自动 refit,与历史 session 存储值兼容。
65
+ const SCRATCH_HEIGHT_MIN = 100;
66
+ const SCRATCH_HEIGHT_MAX = 600;
67
+ const SCRATCH_HEIGHT_DEFAULT = 200;
68
+ const SCRATCH_TAB_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
69
+ const SCRATCH_TAB_MAX = 8;
70
+
71
+ function readScratchOpen() {
72
+ try { return localStorage.getItem(SCRATCH_OPEN_KEY) === 'true'; } catch { return false; }
73
+ }
74
+ function readScratchHeight() {
75
+ try {
76
+ const v = parseInt(localStorage.getItem(SCRATCH_HEIGHT_KEY), 10);
77
+ if (!Number.isFinite(v)) return SCRATCH_HEIGHT_DEFAULT;
78
+ return Math.max(SCRATCH_HEIGHT_MIN, Math.min(SCRATCH_HEIGHT_MAX, v));
79
+ } catch { return SCRATCH_HEIGHT_DEFAULT; }
80
+ }
81
+
82
+ function genScratchTabId() {
83
+ // 与服务端 SCRATCH_ID_RE `/^[A-Za-z0-9_-]{1,64}$/` 兼容
84
+ const rand = (typeof crypto !== 'undefined' && crypto.randomUUID)
85
+ ? crypto.randomUUID().replace(/-/g, '')
86
+ : Math.random().toString(36).slice(2) + Date.now().toString(36);
87
+ return ('t-' + rand).slice(0, 64);
88
+ }
89
+
90
+ function readScratchTabs() {
91
+ try {
92
+ const raw = localStorage.getItem(SCRATCH_TABS_KEY);
93
+ if (!raw) return [];
94
+ const arr = JSON.parse(raw);
95
+ if (!Array.isArray(arr)) return [];
96
+ const out = [];
97
+ for (const t of arr) {
98
+ if (t && typeof t.id === 'string' && SCRATCH_TAB_ID_RE.test(t.id)) {
99
+ out.push({ id: t.id });
100
+ if (out.length >= SCRATCH_TAB_MAX) break;
101
+ }
102
+ }
103
+ return out;
104
+ } catch { return []; }
105
+ }
106
+
107
+ function readScratchActiveTab(tabs) {
108
+ try {
109
+ const v = localStorage.getItem(SCRATCH_ACTIVE_TAB_KEY);
110
+ if (v && tabs.some(t => t.id === v)) return v;
111
+ } catch {}
112
+ return tabs[0]?.id ?? '';
113
+ }
114
+
115
+ function writeScratchTabs(tabs) {
116
+ try { localStorage.setItem(SCRATCH_TABS_KEY, JSON.stringify(tabs)); } catch {}
117
+ }
118
+ function writeScratchActiveTab(id) {
119
+ try { localStorage.setItem(SCRATCH_ACTIVE_TAB_KEY, id); } catch {}
120
+ }
121
+
122
+ // 真实 $SHELL basename 由后端 WS state 消息上报后填进 state.scratchShellBasename,
123
+ // 在拿到之前用 'zsh' 作为占位(macOS 默认 shell;新 server 到达 state 后会按真实 basename 覆盖)
124
+
125
+ function PlusIcon() {
126
+ return (
127
+ <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
128
+ <line x1="12" y1="5" x2="12" y2="19" />
129
+ <line x1="5" y1="12" x2="19" y2="12" />
130
+ </svg>
131
+ );
132
+ }
133
+
134
+ // SparkleIcon / ShieldCheckIcon / PlanClipboardIcon / AgentTeamIcon / UltraplanIcon /
135
+ // UploadIcon / TrashIcon 已迁至 ../common/quickMenuIcons.jsx(与 ChatInputBar 四芒星菜单共用)
136
+
137
+ function CloseIcon() {
138
+ return (
139
+ <svg viewBox="0 0 24 24" width="10" height="10" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
140
+ <line x1="18" y1="6" x2="6" y2="18" />
141
+ <line x1="6" y1="6" x2="18" y2="18" />
142
+ </svg>
143
+ );
144
+ }
145
+
146
+ function ScratchTerminalIcon() {
147
+ return (
148
+ <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
149
+ <rect x="3" y="4" width="18" height="16" rx="2" />
150
+ <polyline points="7 9 10 12 7 15" />
151
+ <line x1="13" y1="15" x2="17" y2="15" />
152
+ </svg>
153
+ );
154
+ }
155
+
156
+ // 虚拟按键定义:label 显示文字,seq 为发送到终端的转义序列
157
+ const VIRTUAL_KEYS = [
158
+ { label: '↑', seq: '\x1b[A' },
159
+ { label: '↓', seq: '\x1b[B' },
160
+ { label: '←', seq: '\x1b[D' },
161
+ { label: '→', seq: '\x1b[C' },
162
+ { label: 'Enter', seq: '\r' },
163
+ { label: 'Tab', seq: '\t' },
164
+ { label: 'Esc', seq: '\x1b' },
165
+ { label: 'Ctrl+C', seq: '\x03' },
166
+ ];
167
+
168
+ export async function uploadFileAndGetPath(file) {
169
+ const MAX_SIZE = 100 * 1024 * 1024; // 100MB
170
+ let upload = file;
171
+ // 图片压缩失败直接用原文件,保证上传流程不中断
172
+ try { upload = await resizeImageIfNeeded(file, 2000); } catch { upload = file; }
173
+ if (upload.size > MAX_SIZE) throw new Error('File too large (max 100MB)');
174
+ const form = new FormData();
175
+ form.append('file', upload);
176
+ const res = await fetch(apiUrl('/api/upload'), { method: 'POST', body: form });
177
+ const data = await res.json();
178
+ if (!data.ok) throw new Error(data.error || 'Upload failed');
179
+ return data.path;
180
+ }
181
+
182
+ class TerminalPanel extends React.Component {
183
+ // 通过 Context 共享 App 层的单条 /ws/terminal,this.context = { send, isOpen, addMessageHandler, addStateListener }
184
+ static contextType = TerminalWsContext;
185
+
186
+ // 兼容 stub:同 ChatView,getter 模拟旧 this.ws 的 send/readyState API → 映射到 context。
187
+ // 这样所有 `this.ws.send(JSON.stringify(...))` 和 `this.ws.readyState === WebSocket.OPEN` 不用改。
188
+ get ws() {
189
+ const ctx = this.context;
190
+ if (!ctx || typeof ctx.send !== 'function') return null;
191
+ return {
192
+ get readyState() { return ctx.isOpen && ctx.isOpen() ? WebSocket.OPEN : WebSocket.CLOSED; },
193
+ send: (s) => {
194
+ let obj;
195
+ try { obj = JSON.parse(s); } catch { return false; }
196
+ return ctx.send(obj);
197
+ },
198
+ };
199
+ }
200
+
201
+ constructor(props) {
202
+ super(props);
203
+ this.containerRef = React.createRef();
204
+ this.fileInputRef = React.createRef();
205
+ // UltraPlan 文件 / 自定义专家纯逻辑(与 ChatView 共享,见 ../utils/ultraplanController)。
206
+ // host 适配器桥接 state / 上传 / 提示 / 偏好 / 关闭编辑器;下方 6 个方法退化为委托。
207
+ this._ultraplan = new UltraplanController({
208
+ getState: () => this.state,
209
+ setState: (updater) => this.setState(updater),
210
+ onUpdatePreferences: (p) => this.props.onUpdatePreferences?.(p),
211
+ uploadFile: (file) => uploadFileAndGetPath(file),
212
+ messageError: (msg) => message.error(msg),
213
+ closeEditor: () => this.closeCustomUltraplanEditor(),
214
+ });
215
+ this.terminal = null;
216
+ this.fitAddon = null;
217
+ // ws 现在是 getter(挂在原型),不在 constructor 上设字段,避免覆盖 getter
218
+ this._unsubWsHandler = null;
219
+ this._unsubWsState = null;
220
+ this.resizeObserver = null;
221
+ this.state = {
222
+ terminalFocused: false,
223
+ quickSettingsOpen: false,
224
+ quickSettingsExpanded: null, // null | 'agentteam' | 'perm' | 'plan' —— 同时只展开一个子菜单
225
+
226
+ ultraplanOpen: false,
227
+ ultraplanVariant: 'codeExpert',
228
+ ultraplanPrompt: '',
229
+ ultraplanFiles: [],
230
+ // PC UltraPlan popover 拖拽尺寸,持久化到 localStorage 两 key;手机/iPad 不走这条路径
231
+ // (那边用 UltraPlanModal),所以无 gate,但 popover 入口本身 isMobile 不显示终端工具栏。
232
+ ultraplanPopoverSize: readUltraplanPopoverSize(),
233
+ customUltraplanExperts: [],
234
+ // 专家显隐 / 排序(管理弹窗)。键 = 'codeExpert' / 'researchExpert' / 'custom:'+id;
235
+ // 落服务端 preferences(ultraplanExpertOrder / ultraplanExpertHidden),缺省=自然序、全可见。
236
+ ultraplanExpertOrder: [],
237
+ ultraplanExpertHidden: [],
238
+ ultraplanManagerOpen: false,
239
+ customUltraplanEditOpen: false,
240
+ customUltraplanEditing: null,
241
+ presetModalVisible: false,
242
+ presetItems: [],
243
+ presetSelected: new Set(),
244
+ presetAddVisible: false,
245
+ presetAddText: '',
246
+ presetAddName: '',
247
+ presetEditId: null,
248
+ lightbox: null,
249
+ ultraplanLightbox: null,
250
+ ultraplanConfirming: false,
251
+ scratchOpen: readScratchOpen(),
252
+ scratchHeight: readScratchHeight(),
253
+ isDraggingScratch: false,
254
+ scratchFocused: false,
255
+ scratchTabs: (() => {
256
+ const t = readScratchTabs();
257
+ return t.length > 0 ? t : [{ id: genScratchTabId() }];
258
+ })(),
259
+ activeScratchTabId: '',
260
+ scratchShellBasename: '',
261
+ };
262
+ // 持久化 active id(先用 readScratchActiveTab 选;下面 mount 后再 sync 到 localStorage)
263
+ this.state.activeScratchTabId = readScratchActiveTab(this.state.scratchTabs);
264
+ this._scratchWrapRef = React.createRef();
265
+ this._scratchRefs = new Map(); // id -> React.createRef()
266
+ this._scratchDragging = false;
267
+ this._scratchDragLastH = null;
268
+ this._scratchPointerId = null;
269
+ }
270
+
271
+ _getScratchRef(id) {
272
+ let ref = this._scratchRefs.get(id);
273
+ if (!ref) {
274
+ ref = React.createRef();
275
+ this._scratchRefs.set(id, ref);
276
+ }
277
+ return ref;
278
+ }
279
+
280
+ handleScratchTabClick = (id) => {
281
+ if (id === this.state.activeScratchTabId) return;
282
+ this.setState({ activeScratchTabId: id }, () => {
283
+ writeScratchActiveTab(id);
284
+ const r = this._scratchRefs.get(id);
285
+ if (r?.current) {
286
+ r.current.refit();
287
+ r.current.focus();
288
+ }
289
+ });
290
+ };
291
+
292
+ handleScratchTabAdd = () => {
293
+ if (this.state.scratchTabs.length >= SCRATCH_TAB_MAX) return;
294
+ const newId = genScratchTabId();
295
+ const tabs = [...this.state.scratchTabs, { id: newId }];
296
+ this.setState({ scratchTabs: tabs, activeScratchTabId: newId }, () => {
297
+ writeScratchTabs(tabs);
298
+ writeScratchActiveTab(newId);
299
+ // 等下一帧 ScratchTerminal mount + 显示后再 refit/focus
300
+ Promise.resolve().then(() => {
301
+ const r = this._scratchRefs.get(newId);
302
+ r?.current?.refit();
303
+ r?.current?.focus();
304
+ });
305
+ });
306
+ };
307
+
308
+ handleScratchTabClose = (id, e) => {
309
+ if (e) { e.stopPropagation(); e.preventDefault(); }
310
+ if (this.state.scratchTabs.length <= 1) return; // 最少保留 1
311
+ const ref = this._scratchRefs.get(id);
312
+ try { ref?.current?.requestKill(); } catch {}
313
+ this._scratchRefs.delete(id);
314
+ const idx = this.state.scratchTabs.findIndex(t => t.id === id);
315
+ const tabs = this.state.scratchTabs.filter(t => t.id !== id);
316
+ let active = this.state.activeScratchTabId;
317
+ if (active === id) {
318
+ // 取右邻居,否则左邻居
319
+ active = (this.state.scratchTabs[idx + 1] ?? this.state.scratchTabs[idx - 1])?.id ?? tabs[0]?.id ?? '';
320
+ }
321
+ this.setState({ scratchTabs: tabs, activeScratchTabId: active }, () => {
322
+ writeScratchTabs(tabs);
323
+ writeScratchActiveTab(active);
324
+ if (active) {
325
+ const r = this._scratchRefs.get(active);
326
+ r?.current?.refit();
327
+ r?.current?.focus();
328
+ }
329
+ });
330
+ };
331
+
332
+ // 仅 active tab 的 focus/blur 事件影响 scratchFocused,避免 tab 切换时新旧并发触发抖动
333
+ handleScratchTabFocusChange = (id, focused) => {
334
+ if (id !== this.state.activeScratchTabId) return;
335
+ if (focused !== this.state.scratchFocused) {
336
+ this.setState({ scratchFocused: focused });
337
+ }
338
+ };
339
+
340
+ // 后端首条 state 消息携带 shellBasename;所有 tab 共用一个 $SHELL,只需取第一次到达的
341
+ handleScratchShellInfo = (name) => {
342
+ if (!name || this.state.scratchShellBasename) return;
343
+ this.setState({ scratchShellBasename: name });
344
+ };
345
+
346
+ toggleScratch = () => {
347
+ const next = !this.state.scratchOpen;
348
+ this.setState({ scratchOpen: next });
349
+ try { localStorage.setItem(SCRATCH_OPEN_KEY, String(next)); } catch {}
350
+ };
351
+
352
+ // 用 DOM 直写 style.height 而非 React JSX inline style:
353
+ // 1) 防 theme MutationObserver / preset-changed 等无关 setState 在拖拽中途把高度 snap 回去
354
+ // 2) 拖拽期间每帧 setState 抖动开销大;mouseup 时一次性 setState + localStorage 提交
355
+ _applyScratchHeight = () => {
356
+ const el = this._scratchWrapRef.current;
357
+ if (el) el.style.height = this.state.scratchHeight + 'px';
358
+ };
359
+
360
+ // Pointer Events + setPointerCapture:自动覆盖 mouseup 飞出窗口、iPad 触摸;不挂 document 全局监听
361
+ handleScratchResizerPointerDown = (e) => {
362
+ if (e.button !== undefined && e.button !== 0) return; // 仅主键
363
+ e.preventDefault();
364
+ this._scratchDragging = true;
365
+ this._scratchDragStartY = e.clientY;
366
+ this._scratchDragStartH = this.state.scratchHeight;
367
+ this._scratchDragLastH = this.state.scratchHeight;
368
+ this._scratchPointerId = e.pointerId;
369
+ try { e.currentTarget.setPointerCapture(e.pointerId); } catch {}
370
+ document.body.style.cursor = 'row-resize';
371
+ document.body.style.userSelect = 'none';
372
+ this.setState({ isDraggingScratch: true });
373
+ };
374
+
375
+ handleScratchResizerPointerMove = (e) => {
376
+ if (!this._scratchDragging) return;
377
+ const newH = Math.max(
378
+ SCRATCH_HEIGHT_MIN,
379
+ Math.min(SCRATCH_HEIGHT_MAX, this._scratchDragStartH + (this._scratchDragStartY - e.clientY))
380
+ );
381
+ const el = this._scratchWrapRef.current;
382
+ if (!el) return;
383
+ el.style.height = newH + 'px';
384
+ this._scratchDragLastH = newH;
385
+ };
386
+
387
+ handleScratchResizerPointerUp = (e) => {
388
+ if (!this._scratchDragging) return;
389
+ this._endScratchDrag(e);
390
+ };
391
+
392
+ _endScratchDrag = (e) => {
393
+ this._scratchDragging = false;
394
+ document.body.style.cursor = '';
395
+ document.body.style.userSelect = '';
396
+ if (e && this._scratchPointerId != null && e.currentTarget) {
397
+ try { e.currentTarget.releasePointerCapture(this._scratchPointerId); } catch {}
398
+ }
399
+ this._scratchPointerId = null;
400
+ const h = this._scratchDragLastH;
401
+ this._scratchDragLastH = null;
402
+ if (h != null) {
403
+ try { localStorage.setItem(SCRATCH_HEIGHT_KEY, String(h)); } catch {}
404
+ this.setState({ scratchHeight: h, isDraggingScratch: false });
405
+ } else {
406
+ this.setState({ isDraggingScratch: false });
407
+ }
408
+ };
409
+
410
+ componentDidMount() {
411
+ // 幂等:window.__cxvTermDiag 快照 + longtask 计数 + cxv_term_diag 周期日志。
412
+ // 有意不在 unmount 配对卸载——app-lifetime 单例(计数器/定时器全局唯一,
413
+ // 跨面板共享;_installed 守卫防重复安装)。
414
+ installTermDiag();
415
+ this.initTerminal();
416
+ // 注册 ws 消息 + 状态 handler。Provider 已在 App/Mobile 层根据 cliMode/terminalVisible 决定是否建立 ws。
417
+ if (this.context && this.context.addMessageHandler) {
418
+ this._unsubWsHandler = this.context.addMessageHandler(this._onTerminalWsMessage);
419
+ }
420
+ if (this.context && this.context.addStateListener) {
421
+ this._unsubWsState = this.context.addStateListener(this._onTerminalWsState);
422
+ }
423
+ // 若 ws 已 OPEN(本组件 mount 较 Provider 晚的常见场景),立即 sendResize 让 PTY 用当前 cols/rows。
424
+ if (this.context && this.context.isOpen && this.context.isOpen()) {
425
+ this.sendResize();
426
+ }
427
+ this.setupResizeObserver();
428
+ // 定时强制刷新,按渲染器分流:
429
+ // - Android(WebGL):纹理脏真实存在,保留 60s 轻量维护(clearTextureAtlas + refresh;
430
+ // 可动态 fit 的端再 fit + sendResize)。phone 上 canFit=false 自动退化为 atlas+refresh。
431
+ // - mac(WebGL)/Windows·Linux·iPad(DOM):120s 轻量分支——atlas 清理(mac WebGL 防
432
+ // sleep-wake/GPU 切换的纹理脏累积,DOM 渲染器下为 no-op)+ 全行 refresh 被动自愈;
433
+ // 不做 fit/sendResize,避免定时 resize 抖动。iPhone 维持无定时器(内存/电量预算)。
434
+ // tab 隐藏时跳过(无渲染需求)。
435
+ if (isAndroid) {
436
+ this._autoRefreshInterval = setInterval(() => {
437
+ if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;
438
+ this._refreshAndroidTerminalRendering();
439
+ }, 60000);
440
+ } else if (!isMobile || isPad) {
441
+ this._autoRefreshInterval = setInterval(() => {
442
+ if (typeof document !== 'undefined' && document.visibilityState === 'hidden') return;
443
+ if (!this.terminal) return;
444
+ try { this.terminal.clearTextureAtlas?.(); } catch {}
445
+ this.terminal.refresh(0, this.terminal.rows - 1);
446
+ }, 120000);
447
+ }
448
+ // 加载预置 (props.preferences 已 ready 时立即,否则 componentDidUpdate 接力)
449
+ this._loadPresetShortcuts();
450
+ this._onFocusTerminal = () => { if (this.terminal && this.containerRef?.current?.offsetWidth > 0) this.terminal.focus(); };
451
+ window.addEventListener('cxv-focus-terminal', this._onFocusTerminal);
452
+ this._themeObserver = new MutationObserver(() => {
453
+ if (this.terminal) {
454
+ const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
455
+ this.terminal.options.theme = isDark ? darkTerminalTheme : lightTerminalTheme;
456
+ }
457
+ });
458
+ this._themeObserver.observe(document.documentElement, { attributes: true, attributeFilter: ['data-theme'] });
459
+ if (this.state.scratchOpen) this._applyScratchHeight();
460
+ // mount 时 sync tab 列表 / active id 到 localStorage(兼容旧版本只有 open/height 的存档)
461
+ writeScratchTabs(this.state.scratchTabs);
462
+ if (this.state.activeScratchTabId) writeScratchActiveTab(this.state.activeScratchTabId);
463
+ }
464
+
465
+ componentDidUpdate(prevProps, prevState) {
466
+ // SettingsContext 异步 fetch 完成后,props.preferences 才到达;这里接力加载 AgentTeam 预置。
467
+ if (prevProps.preferences !== this.props.preferences) {
468
+ this._loadPresetShortcuts();
469
+ }
470
+ if (prevState.scratchOpen !== this.state.scratchOpen) {
471
+ if (this.state.scratchOpen) {
472
+ // componentDidUpdate 在 React commit 之后、浏览器 paint 之前同步触发,
473
+ // 此时 ref.current 已是最新 DOM;直接写 style.height,不走 microtask 防 1 帧闪烁
474
+ this._applyScratchHeight();
475
+ } else if (this._scratchDragging) {
476
+ // 拖拽过程中 scratchOpen 被外部翻 false:resizer 已卸载、pointerup 不会再触达,
477
+ // 这里兜底恢复 body 样式与拖拽标志,防止 cursor/userSelect 残留
478
+ document.body.style.cursor = '';
479
+ document.body.style.userSelect = '';
480
+ this._scratchDragging = false;
481
+ this._scratchDragLastH = null;
482
+ this._scratchPointerId = null;
483
+ this.setState({ isDraggingScratch: false });
484
+ }
485
+ }
486
+ }
487
+
488
+ _loadPresetShortcuts() {
489
+ // 数据从 props.preferences 派生(SettingsContext 集中 fetch);未 ready 时静默返回,
490
+ // componentDidUpdate 接力。
491
+ const data = this.props.preferences;
492
+ if (!data) return;
493
+ const dismissed = Array.isArray(data.dismissedBuiltinPresets) ? new Set(data.dismissedBuiltinPresets) : new Set();
494
+ this._dismissedBuiltinPresets = dismissed;
495
+ let items = [];
496
+ if (Array.isArray(data.presetShortcuts)) {
497
+ items = data.presetShortcuts.map((item, i) => {
498
+ if (typeof item === 'string') return { id: Date.now() + i, teamName: '', description: item };
499
+ return {
500
+ id: Date.now() + i,
501
+ teamName: item.teamName || '',
502
+ description: item.description || '',
503
+ ...(item.builtinId ? { builtinId: item.builtinId } : {}),
504
+ ...(item.modified ? { modified: true } : {}),
505
+ };
506
+ });
507
+ }
508
+ // 合并内置预置:未被用户删除且不在已有列表中的
509
+ const existingBuiltinIds = new Set(items.filter(i => i.builtinId).map(i => i.builtinId));
510
+ for (const bp of BUILTIN_PRESETS) {
511
+ if (dismissed.has(bp.builtinId) || existingBuiltinIds.has(bp.builtinId)) continue;
512
+ items.unshift({ id: Date.now() + Math.random(), builtinId: bp.builtinId, teamName: bp.teamName, description: bp.description });
513
+ }
514
+ const customExperts = Array.isArray(data.customUltraplanExperts) ? data.customUltraplanExperts : [];
515
+ const expertOrder = Array.isArray(data.ultraplanExpertOrder) ? data.ultraplanExpertOrder : [];
516
+ const expertHidden = Array.isArray(data.ultraplanExpertHidden) ? data.ultraplanExpertHidden : [];
517
+ const next = { presetItems: items, customUltraplanExperts: customExperts, ultraplanExpertOrder: expertOrder, ultraplanExpertHidden: expertHidden };
518
+ // 若当前选中的变体已不可见(被另一端删除 / 隐藏),回退到首个可见专家(无可见则 codeExpert)。
519
+ const current = this.state.ultraplanVariant;
520
+ const visible = visibleExpertKeys(customExperts, expertOrder, expertHidden);
521
+ if (typeof current === 'string' && !visible.includes(current)) {
522
+ next.ultraplanVariant = visible[0] || 'codeExpert';
523
+ }
524
+ this.setState(next);
525
+ }
526
+
527
+ componentWillUnmount() {
528
+ this._qmHover.cancel();
529
+ // mid-drag 卸载兜底:恢复 body 样式,标记终止
530
+ if (this._scratchDragging) {
531
+ document.body.style.cursor = '';
532
+ document.body.style.userSelect = '';
533
+ this._scratchDragging = false;
534
+ this._scratchDragLastH = null;
535
+ this._scratchPointerId = null;
536
+ }
537
+ if (this.terminal?.textarea) {
538
+ this.terminal.textarea.removeEventListener('focus', this._handleTermFocus);
539
+ this.terminal.textarea.removeEventListener('blur', this._handleTermBlur);
540
+ }
541
+ if (this._themeObserver) { this._themeObserver.disconnect(); this._themeObserver = null; }
542
+ window.removeEventListener('cxv-focus-terminal', this._onFocusTerminal);
543
+ if (this._stopMobileMomentum) this._stopMobileMomentum();
544
+ // unmount 前同步排空 buffer 给 xterm,防最后 16ms 数据丢失(既有 bug 缓解)。
545
+ // dispose 后 push 静默忽略、rAF 取消,与 terminal.dispose 顺序无关。
546
+ if (this._writeQ) {
547
+ try { this._writeQ.drain(); } catch {}
548
+ this._writeQ.dispose();
549
+ }
550
+ if (this._wsReconnectTimer) clearTimeout(this._wsReconnectTimer);
551
+ if (this._unsubWsHandler) { try { this._unsubWsHandler(); } catch {} this._unsubWsHandler = null; }
552
+ if (this._unsubWsState) { try { this._unsubWsState(); } catch {} this._unsubWsState = null; }
553
+ if (this._resizeDebounceTimer) clearTimeout(this._resizeDebounceTimer);
554
+ if (this._webglRecoveryTimer) clearTimeout(this._webglRecoveryTimer);
555
+ if (this._autoRefreshInterval) { clearInterval(this._autoRefreshInterval); this._autoRefreshInterval = null; }
556
+ if (this._initRafId) { cancelAnimationFrame(this._initRafId); this._initRafId = 0; }
557
+ if (this.resizeObserver) {
558
+ this.resizeObserver.disconnect();
559
+ }
560
+ if (this.webglAddon || this._webglLongtaskObserver) {
561
+ this._disposeWebgl();
562
+ }
563
+ if (this.terminal) {
564
+ if (this.terminal.textarea) {
565
+ this.terminal.textarea.removeEventListener('paste', this._handlePaste, true);
566
+ }
567
+ this.terminal.dispose();
568
+ // 置 null 让晚到的异步回调(如 document.fonts.ready 重 fit)的 !this.terminal
569
+ // 守卫真正生效,与 ScratchTerminal 行为对齐
570
+ this.terminal = null;
571
+ }
572
+ // fitAddon 随 terminal.dispose 失效,置 null 让晚到回调的 !this.fitAddon 守卫生效
573
+ this.fitAddon = null;
574
+ }
575
+
576
+ initTerminal() {
577
+ const isDark = document.documentElement.getAttribute('data-theme') !== 'light';
578
+ this.terminal = new Terminal({
579
+ cursorBlink: false,
580
+ cursorStyle: 'bar',
581
+ cursorWidth: 1,
582
+ cursorInactiveStyle: 'none',
583
+ fontSize: (isMobile && !isPad) ? 11 : 13,
584
+ fontFamily: terminalFontFamily,
585
+ theme: isDark ? darkTerminalTheme : lightTerminalTheme,
586
+ allowProposedApi: true,
587
+ // Windows:超出 cell 宽度的字形(CJK 落回退字体时常见)按 cell 缩放,配合
588
+ // terminalFontFamily 治 IME 中文输入整体偏移;仅 win 开启,mac 渲染零变化。
589
+ // 注:DOM 渲染器下该选项无效(WebGL/Canvas 有效),字体栈修复不受影响。
590
+ rescaleOverlappingGlyphs: isWindows,
591
+ scrollback: isPad ? 2000 : isIOS ? 200 : isMobile ? 1000 : 2000,
592
+ smoothScrollDuration: 0,
593
+ scrollOnUserInput: true,
594
+ });
595
+
596
+ this.fitAddon = new FitAddon();
597
+ this.terminal.loadAddon(this.fitAddon);
598
+ this.terminal.loadAddon(new WebLinksAddon());
599
+
600
+ const unicode11 = new Unicode11Addon();
601
+ this.terminal.loadAddon(unicode11);
602
+ this.terminal.unicode.activeVersion = '11';
603
+
604
+ this.terminal.open(this.containerRef.current);
605
+
606
+ // 终端 focus/blur → 边框高亮 (xterm v6 removed onFocus/onBlur, use DOM events)
607
+ this._handleTermFocus = () => this.setState({ terminalFocused: true });
608
+ this._handleTermBlur = () => this.setState({ terminalFocused: false });
609
+ const termTextarea = this.terminal.textarea;
610
+ if (termTextarea) {
611
+ termTextarea.addEventListener('focus', this._handleTermFocus);
612
+ termTextarea.addEventListener('blur', this._handleTermBlur);
613
+ }
614
+
615
+ // 渲染器选择:Android + macOS 桌面(Chromium 系)启用 WebGL,详见 WEBGL_RENDERER 常量;
616
+ // Windows/Linux/iOS/Safari 走 xterm.js 6.0 内置 DOM 渲染器——Windows 上实测 DOM 比
617
+ // WebGL 更稳定(无纹理脏花屏 / context loss / GPU 长任务降级等问题)。
618
+ if (WEBGL_RENDERER) {
619
+ this._loadWebglAddon(false);
620
+ } else {
621
+ // WebGL 时代 longtask 降级留下的 sticky key 在 DOM 平台已是死状态,一次性清理
622
+ try { localStorage.removeItem(WEBGL_STICKY_KEY); } catch {}
623
+ }
624
+
625
+ // 写入节流:批量合并高频输出,避免逐条触发渲染。
626
+ // 用 TerminalWriteQueue 替代原「string += / slice」实现,消除大流量时
627
+ // O(n²) 字符串切片热点(trace3 显示 _flushWrite 794ms self),同时
628
+ // 修复 UTF-16 surrogate 边界切碎、unmount 16ms 数据丢失等隐患。
629
+ // 节奏与原实现等价:每帧 1 个 chunk,不做激进 multi-chunk drain。
630
+ // 移动端内存预算低,积压自保水位减半(默认桌面 2MB/512KB)。
631
+ // chunk 初值:Windows DOM 渲染器解析慢,16KB 保守起步(其余平台 32KB),
632
+ // 运行期由 write callback 计时 AIMD 自适应收敛(详见 terminalWriteQueue 头注释)。
633
+ this._writeQ = new TerminalWriteQueue(
634
+ () => this.terminal,
635
+ {
636
+ ...((isMobile && !isPad) ? { highWaterBytes: 1024 * 1024, trimTargetBytes: 256 * 1024 } : null),
637
+ ...(isWindows ? { initialChunkBytes: 16 * 1024 } : null),
638
+ // 积压丢弃后向服务端请求权威快照对齐(整项丢弃的中段对增量输出流不会自愈)
639
+ onTrim: () => this._requestResync(),
640
+ }
641
+ );
642
+
643
+ if (isMobile && !isPad) {
644
+ // 移动端:基于屏幕尺寸一次性计算固定 cols/rows,避免动态 fit 导致渲染抖动
645
+ this._initRafId = requestAnimationFrame(() => {
646
+ this._initRafId = 0;
647
+ if (!this.terminal) return; // mount 后一帧内 unmount 的竞态守卫
648
+ this._mobileFixedResize();
649
+ });
650
+ } else {
651
+ this._initRafId = requestAnimationFrame(() => {
652
+ this._initRafId = 0;
653
+ if (!this.terminal || !this.fitAddon) return; // unmount 竞态:fit/focus 作用于尸体会抛
654
+ this.fitAddon.fit();
655
+ this.terminal.focus();
656
+ });
657
+ // 字体异步就绪后重 fit + 重绘:初始 fit 可能基于回退字体的 cell 测量,
658
+ // 字体加载完成后宽度变化会造成错位(Windows CJK 场景尤甚)。
659
+ if (typeof document !== 'undefined' && document.fonts?.ready?.then) {
660
+ document.fonts.ready.then(() => {
661
+ if (!this.terminal) return;
662
+ this._fitPreservingScroll();
663
+ try { this.terminal.refresh(0, this.terminal.rows - 1); } catch { /* noop */ }
664
+ });
665
+ }
666
+ }
667
+
668
+ // Shift+Enter: 发 ESC+CR(Alt+Enter 的 escape 码),和 Codex `/terminal-setup`
669
+ // 写进 VS Code/Cursor keybindings 的 `\x1b\r` 等价。Codex CLI 识别这个序列为
670
+ // "插入换行而非提交"。之前用 bracketed-paste-LF 对老版可能有效,2.x 版已不兼容。
671
+ this.terminal.attachCustomKeyEventHandler((e) => {
672
+ // Win/Linux 智能复制粘贴(见 utils/terminalClipboard.js 注释):xterm 6 把 Ctrl+C/Ctrl+V
673
+ // 当控制字符并 preventDefault,压掉原生 paste。这里在最先执行的 customKeyEventHandler 接管。
674
+ const clipAction = clipboardKeyAction(e, { isMac });
675
+ if (clipAction === 'paste') {
676
+ // 主动读剪贴板(不依赖被 xterm 压掉的原生 paste 默认动作 → 同样修复 Electron 端),
677
+ // 终端走 _pasteText 安全路径(bracketed-paste 包裹 + 注入消毒,保留图片粘贴)。
678
+ if (navigator.clipboard && (navigator.clipboard.read || navigator.clipboard.readText)) {
679
+ e.preventDefault();
680
+ e.stopPropagation();
681
+ // 双重粘贴防护:主动读剪贴板期间,若个别浏览器仍触发原生 paste(preventDefault 抑制
682
+ // paste 是约定行为、非规范硬保证),让 _handlePaste 早退,避免叠加。下个事件循环清闸。
683
+ this._activePasteInFlight = true;
684
+ setTimeout(() => { this._activePasteInFlight = false; }, 0);
685
+ this._activePaste();
686
+ return false;
687
+ }
688
+ // 非安全上下文(如 LAN HTTP)无 clipboard API:不 preventDefault,放行原生 paste → _handlePaste
689
+ return false;
690
+ }
691
+ if (clipAction === 'copy') {
692
+ const sel = this.terminal?.getSelection?.();
693
+ if (sel) {
694
+ // 有选区:复制(对齐 VS Code / Windows Terminal)。仅复制成功才清选区——失败(非安全
695
+ // 上下文且 execCommand 也失败)时保留选区,用户可改用 Ctrl+Insert 重试,不致"选区被吞"。
696
+ e.preventDefault();
697
+ e.stopPropagation();
698
+ copyTextToClipboard(sel).then((ok) => { if (ok) this.terminal?.clearSelection?.(); });
699
+ return false;
700
+ }
701
+ return true; // 无选区:交回 xterm 发 \x03(SIGINT),保留中断能力
702
+ }
703
+ if (e.type === 'keydown' && e.key === 'Enter' && e.shiftKey) {
704
+ // 必须显式 preventDefault:xterm customKeyEventHandler 返回 false 只阻 xterm 内部处理,
705
+ // 不阻浏览器 textarea 默认行为(Enter 会往隐藏 textarea 塞 \n 再被 xterm onData 转发到 PTY)。
706
+ // 不 preventDefault 会让 PTY 同时收到 \x1b\r(我们显式发的)和 \n(textarea 漏进来的),
707
+ // 后者被 Codex 当作 Enter 提交,于是"看起来换行没生效"。
708
+ e.preventDefault();
709
+ e.stopPropagation();
710
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
711
+ this.ws.send(JSON.stringify({ type: 'input', data: '\x1b\r' }));
712
+ }
713
+ return false;
714
+ }
715
+ // Enter: 如果有 pending 文件,先注入路径到终端输入行(不带回车),
716
+ // 用户可以看到路径后再按 Enter 确认发送
717
+ // 跳过 alternate screen(vim/less 等交互程序),避免误注入
718
+ if (e.type === 'keydown' && e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.metaKey) {
719
+ const pending = this.props.pendingImages;
720
+ const inAlternateScreen = this.terminal?.buffer?.active?.type === 'alternate';
721
+ if (pending?.length > 0 && !inAlternateScreen && this.ws?.readyState === WebSocket.OPEN) {
722
+ // 必须 preventDefault(同上 Shift+Enter 分支):仅 return false 不阻浏览器默认,
723
+ // Enter 的 keypress 仍被 xterm 转发 \r 到 PTY → 路径注入后立即提交,违背
724
+ // "用户看到路径再按 Enter 确认" 的设计。
725
+ e.preventDefault();
726
+ e.stopPropagation();
727
+ const paths = pending.map(img => `'${img.path.replace(/'/g, "'\\''")}'`).join(' ');
728
+ this.ws.send(JSON.stringify({ type: 'input', data: paths + ' ' }));
729
+ this.props.onClearPendingImages?.();
730
+ return false;
731
+ }
732
+ }
733
+ return true;
734
+ });
735
+
736
+ // alt 屏(Codex Ink 等 TUI,buffer.hasScrollback=false)下,xterm 默认把 wheel
737
+ // 翻译成 ↑/↓ 发 PTY,Ink 输入会把它当作历史翻页。这里拦截:正常屏让 xterm 自己滚
738
+ // scrollback;alt 屏转发滚动到外层 chat scroller(Virtuoso),由 ChatView 通过
739
+ // getChatScroller prop 传入。祖先链上没有可滚元素,必须显式拿这个 sibling ref。
740
+ this.terminal.attachCustomWheelEventHandler((ev) => {
741
+ if (this.terminal?.buffer?.active?.type !== 'alternate') return true;
742
+ const scroller = this.props.getChatScroller?.();
743
+ if (scroller) {
744
+ const px = ev.deltaMode === 1 ? ev.deltaY * 16
745
+ : ev.deltaMode === 2 ? ev.deltaY * (scroller.clientHeight || 0)
746
+ : ev.deltaY;
747
+ scroller.scrollTop += px;
748
+ }
749
+ ev.preventDefault();
750
+ return false;
751
+ });
752
+
753
+ this.terminal.onData((data) => {
754
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
755
+ this.ws.send(JSON.stringify({ type: 'input', data }));
756
+ }
757
+ });
758
+
759
+ // 拦截粘贴事件,用 bracketed paste 转义序列包裹,
760
+ // 防止多行粘贴时换行符被当作 Enter 逐行执行
761
+ // 使用 capture 阶段确保在 xterm.js 自身的 paste handler 之前执行
762
+ if (this.terminal.textarea) {
763
+ this.terminal.textarea.addEventListener('paste', this._handlePaste, true);
764
+ }
765
+
766
+ if (isMobile) {
767
+ this._setupMobileTouchScroll();
768
+ }
769
+ }
770
+
771
+ /**
772
+ * 手机端触摸滚动:xterm 的 viewport 在 screen 层之下,原生触摸无法滚动。
773
+ * 使用 terminal.scrollLines() 官方 API 代替直接操作 scrollTop,
774
+ * 确保与 xterm 内部状态同步。通过 rAF 批量处理 + 惯性动画实现流畅滚动。
775
+ * 参考: https://github.com/xtermjs/xterm.js/issues/594
776
+ */
777
+ _setupMobileTouchScroll() {
778
+ const screen = this.containerRef.current?.querySelector('.xterm-screen');
779
+ if (!screen) return;
780
+
781
+ const term = this.terminal;
782
+ // 获取行高(用于将像素 delta 转为行数)
783
+ const getLineHeight = () => {
784
+ const cellDims = term._core?._renderService?.dimensions?.css?.cell;
785
+ return cellDims?.height || 15;
786
+ };
787
+
788
+ let lastY = 0;
789
+ let lastTime = 0;
790
+ let momentumRaf = null;
791
+ // 像素级累积器,不足一行时保留小数部分
792
+ let pixelAccum = 0;
793
+ let pendingDy = 0;
794
+ let scrollRaf = null;
795
+ let velocitySamples = [];
796
+
797
+ const stopMomentum = () => {
798
+ if (momentumRaf) {
799
+ cancelAnimationFrame(momentumRaf);
800
+ momentumRaf = null;
801
+ }
802
+ if (scrollRaf) {
803
+ cancelAnimationFrame(scrollRaf);
804
+ scrollRaf = null;
805
+ }
806
+ pendingDy = 0;
807
+ pixelAccum = 0;
808
+ };
809
+
810
+ // 将累积的像素偏移转化为行滚动
811
+ const flushScroll = () => {
812
+ scrollRaf = null;
813
+ if (pendingDy === 0) return;
814
+ pixelAccum += pendingDy;
815
+ pendingDy = 0;
816
+ const lh = getLineHeight();
817
+ const lines = Math.trunc(pixelAccum / lh);
818
+ if (lines !== 0) {
819
+ term.scrollLines(lines);
820
+ pixelAccum -= lines * lh;
821
+ }
822
+ };
823
+
824
+ screen.addEventListener('touchstart', (e) => {
825
+ stopMomentum();
826
+ if (e.touches.length !== 1) return;
827
+ lastY = e.touches[0].clientY;
828
+ lastTime = performance.now();
829
+ velocitySamples = [];
830
+ }, { passive: true });
831
+
832
+ screen.addEventListener('touchmove', (e) => {
833
+ if (e.touches.length !== 1) return;
834
+ const y = e.touches[0].clientY;
835
+ const now = performance.now();
836
+ const dt = now - lastTime;
837
+ const dy = lastY - y; // 正值 = 向上滚
838
+
839
+ if (dt > 0) {
840
+ const v = dy / dt * 16;
841
+ velocitySamples.push({ v, t: now });
842
+ // 只保留最近 100ms 的样本
843
+ while (velocitySamples.length > 0 && now - velocitySamples[0].t > 100) {
844
+ velocitySamples.shift();
845
+ }
846
+ }
847
+
848
+ pendingDy += dy;
849
+ if (!scrollRaf) {
850
+ scrollRaf = requestAnimationFrame(flushScroll);
851
+ }
852
+
853
+ lastY = y;
854
+ lastTime = now;
855
+ }, { passive: true });
856
+
857
+ screen.addEventListener('touchend', () => {
858
+ // 刷掉剩余 pending
859
+ if (scrollRaf) {
860
+ cancelAnimationFrame(scrollRaf);
861
+ scrollRaf = null;
862
+ }
863
+ if (pendingDy !== 0) {
864
+ pixelAccum += pendingDy;
865
+ pendingDy = 0;
866
+ const lh = getLineHeight();
867
+ const lines = Math.trunc(pixelAccum / lh);
868
+ if (lines !== 0) term.scrollLines(lines);
869
+ pixelAccum = 0;
870
+ }
871
+
872
+ // 用加权平均计算末速度(像素/帧)
873
+ let velocity = 0;
874
+ if (velocitySamples.length >= 2) {
875
+ let totalWeight = 0;
876
+ let weightedV = 0;
877
+ const latest = velocitySamples[velocitySamples.length - 1].t;
878
+ for (const s of velocitySamples) {
879
+ const w = Math.max(0, 1 - (latest - s.t) / 100);
880
+ weightedV += s.v * w;
881
+ totalWeight += w;
882
+ }
883
+ velocity = totalWeight > 0 ? weightedV / totalWeight : 0;
884
+ }
885
+ velocitySamples = [];
886
+
887
+ // 惯性滚动(仍用像素级累积器保证精度)
888
+ if (Math.abs(velocity) < 0.5) return;
889
+ const friction = 0.95;
890
+ let mAccum = 0;
891
+ const tick = () => {
892
+ if (Math.abs(velocity) < 0.3) {
893
+ // 最后残余不足一行则四舍五入
894
+ const lh = getLineHeight();
895
+ const rest = Math.round(mAccum / lh);
896
+ if (rest !== 0) term.scrollLines(rest);
897
+ momentumRaf = null;
898
+ return;
899
+ }
900
+ mAccum += velocity;
901
+ const lh = getLineHeight();
902
+ const lines = Math.trunc(mAccum / lh);
903
+ if (lines !== 0) {
904
+ term.scrollLines(lines);
905
+ mAccum -= lines * lh;
906
+ }
907
+ velocity *= friction;
908
+ momentumRaf = requestAnimationFrame(tick);
909
+ };
910
+ momentumRaf = requestAnimationFrame(tick);
911
+ }, { passive: true });
912
+
913
+ this._stopMobileMomentum = stopMomentum;
914
+ }
915
+
916
+ // 通过 TerminalWsContext 共享 ws — 不再自建。本方法接收 Provider 派发的所有消息,
917
+ // 自己 switch type;ChatView/TerminalPanel 各自只处理关心的类型,互不干扰。
918
+ // (原 hook/sdk-* 类消息在合并 ws 后也会进来,但这里不识别 → try/catch 之外也无作用,自然忽略。)
919
+ _onTerminalWsMessage = (msg) => {
920
+ try {
921
+ if (msg.type === 'data') {
922
+ this._throttledWrite(msg.data);
923
+ } else if (msg.type === 'data-resync') {
924
+ // 服务端反压恢复:丢弃本地积压、重置 xterm、写快照一步对齐到服务端当前末态
925
+ // (与 ws close→重连全量 replay 的既有恢复惯例同款;TUI 重绘由服务端 SIGWINCH/resize 抖动驱动)。
926
+ // 有意取舍:全量重置会连洪泛前的 scrollback 一起清掉——保留 scrollback 改写
927
+ // 分隔条+追加快照的方案会让快照开头与已渲染内容重叠重复,且洪泛流的半截转义残留可能
928
+ // 卡坏 ANSI 状态机;reset 换取干净对齐,黄字提示已向用户明示发生过跳过。
929
+ // 重置必须走带内 INBAND_RESET 而非带外 terminal.reset()——后者不清 xterm 内部
930
+ // WriteBuffer,残留字节在 reset 后以 ground state 续解析,半截序列按字面渲染成
931
+ // `0;134m` 类残片且永久留在新 scrollback(见 terminalWriteQueue.INBAND_RESET doc)。
932
+ diagCount('resyncCount');
933
+ this._writeQ.reset();
934
+ this._writeQ.push(INBAND_RESET + '\x1b[33m[cx-viewer] output skipped during congestion\x1b[0m\r\n');
935
+ if (msg.data) this._writeQ.push(msg.data);
936
+ } else if (msg.type === 'exit') {
937
+ this._flushWrite();
938
+ this.terminal.write(`\r\n\x1b[33m${t('ui.terminal.exited', { code: msg.exitCode ?? '?' })}\x1b[0m\r\n`);
939
+ this.terminal.write(`\x1b[90m${t('ui.terminal.pressEnterForShell')}\x1b[0m\r\n`);
940
+ } else if (msg.type === 'editor-open') {
941
+ if (this.props.onEditorOpen) {
942
+ this.props.onEditorOpen(msg.sessionId, msg.filePath);
943
+ }
944
+ } else if (msg.type === 'state') {
945
+ if (!msg.running && msg.exitCode !== null) {
946
+ this._flushWrite();
947
+ this.terminal.write(`\x1b[33m${t('ui.terminal.exited', { code: msg.exitCode })}\x1b[0m\r\n`);
948
+ this.terminal.write(`\x1b[90m${t('ui.terminal.pressEnterForShell')}\x1b[0m\r\n`);
949
+ }
950
+ } else if (msg.type === 'toast') {
951
+ this._flushWrite();
952
+ this.terminal.write(`\r\n\x1b[33m⚠ ${msg.message}\x1b[0m\r\n`);
953
+ }
954
+ } catch {}
955
+ };
956
+
957
+ // ws 状态变更:open 时 sendResize(原 onopen 行为);close 时 reset xterm(避免残留半截 ANSI)。
958
+ // 重连本身由 Provider 内部 2s 退避完成,组件无感。
959
+ _onTerminalWsState = (state) => {
960
+ if (state === 'open') {
961
+ this.sendResize();
962
+ } else if (state === 'close') {
963
+ // writeQ 与 terminal 都要 reset(同 data-resync 分支):close 时队列若有积压,
964
+ // 重连 replay 会把这些字节再发一遍 → 局部重复。只 reset xterm 漏了写队列。
965
+ // 重置走带内序列防 WriteBuffer 残留撕裂(同 data-resync 分支注释)。
966
+ this._writeQ?.reset();
967
+ this._writeQ?.push(INBAND_RESET);
968
+ }
969
+ };
970
+
971
+ // write-queue 积压丢弃后请求服务端快照对齐(服务端回 data-resync,见上方分支)。
972
+ // 持续过载期 _maybeTrim 每次 push 都可能触发——2s 节流防请求风暴(服务端另有冷却兜底)。
973
+ _requestResync() {
974
+ const nowTs = Date.now();
975
+ if (nowTs - (this._lastResyncReqAt || 0) < 2000) return;
976
+ this._lastResyncReqAt = nowTs;
977
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
978
+ try { this.ws.send(JSON.stringify({ type: 'resync-request' })); } catch {}
979
+ }
980
+ }
981
+
982
+ sendResize() {
983
+ if (this.ws && this.ws.readyState === WebSocket.OPEN && this.terminal) {
984
+ const msg = {
985
+ type: 'resize',
986
+ cols: this.terminal.cols,
987
+ rows: this.terminal.rows,
988
+ };
989
+ if (isMobile) msg.mobile = true;
990
+ this.ws.send(JSON.stringify(msg));
991
+ }
992
+ }
993
+
994
+ // Android 定时渲染维护:走 xterm 官方 escape hatch,不通过改 DOM 高度骗 fit() 重建渲染层。
995
+ _refreshAndroidTerminalRendering = () => {
996
+ const term = this.terminal;
997
+ if (!term) return;
998
+
999
+ try { term.clearTextureAtlas?.(); } catch {}
1000
+ try { term.refresh(0, term.rows - 1); } catch {}
1001
+ // 仅动态 fit 路径才允许 fit();移动端非 iPad 由 _mobileFixedResize 维护固定 60 列,
1002
+ // 调 fit() 会把固定列覆盖成按容器算的动态列,破坏移动端契约。
1003
+ const canFit = !isMobile || isPad;
1004
+ if (canFit) {
1005
+ this._fitPreservingScroll();
1006
+ this.sendResize();
1007
+ }
1008
+ };
1009
+
1010
+ // 调 fitAddon.fit() 并尽量保持用户的 scrollTop —— fit() 会重排 viewport,scrollHeight 变后
1011
+ // scrollTop 默认会被重置。贴底时直接贴底,其他情况按 prev/new scrollHeight 比例换算。
1012
+ // ResizeObserver 路径和 Android 60s 自动维护都走它,行为统一。
1013
+ _fitPreservingScroll = () => {
1014
+ if (!this.fitAddon || !this.containerRef.current) return;
1015
+ // 0/极小尺寸守卫(同 ScratchTerminal):容器可见但高度≈0 时 FitAddon 会算出 2×1
1016
+ // (MINIMUM_COLS=2/ROWS=1) 并经 sendResize 发给 PTY → ConPTY 全屏 reflow 崩坏 +
1017
+ // 恢复时二次重绘。尺寸无效时跳过 fit,等容器恢复后 ResizeObserver 再触发。
1018
+ const el = this.containerRef.current;
1019
+ if (el.offsetWidth <= 0 || el.offsetHeight <= 0) return;
1020
+ try {
1021
+ const vp = this.containerRef.current.querySelector('.xterm-viewport');
1022
+ const prevScrollTop = vp?.scrollTop ?? 0;
1023
+ const prevScrollHeight = vp?.scrollHeight ?? 1;
1024
+ const wasAtBottom = vp ? (prevScrollTop + vp.clientHeight >= prevScrollHeight - 5) : true;
1025
+ this.fitAddon.fit();
1026
+ if (vp) {
1027
+ if (wasAtBottom) {
1028
+ vp.scrollTop = vp.scrollHeight;
1029
+ } else {
1030
+ const ratio = prevScrollHeight > 0 ? prevScrollTop / prevScrollHeight : 0;
1031
+ vp.scrollTop = ratio * vp.scrollHeight;
1032
+ }
1033
+ }
1034
+ } catch {}
1035
+ };
1036
+
1037
+ setupResizeObserver() {
1038
+ // 移动端使用固定尺寸,不需要 ResizeObserver(iPad 例外,走动态 fit)
1039
+ if (isMobile && !isPad) return;
1040
+
1041
+ this.resizeObserver = new ResizeObserver(() => {
1042
+ if (this._resizeDebounceTimer) clearTimeout(this._resizeDebounceTimer);
1043
+ this._resizeDebounceTimer = setTimeout(() => {
1044
+ this._resizeDebounceTimer = null;
1045
+ this._fitPreservingScroll();
1046
+ this.sendResize();
1047
+ }, 150);
1048
+ });
1049
+ if (this.containerRef.current) {
1050
+ this.resizeObserver.observe(this.containerRef.current);
1051
+ }
1052
+ }
1053
+
1054
+ _loadWebglAddon(isRetry) {
1055
+ // Sticky disable 检查:7 天内曾因 GPU 长任务降级过,跳过 WebGL 加载
1056
+ try {
1057
+ const until = localStorage.getItem(WEBGL_STICKY_KEY);
1058
+ if (until && Date.now() < Number(until)) return;
1059
+ } catch {}
1060
+
1061
+ try {
1062
+ this.webglAddon = new WebglAddon();
1063
+ this.webglAddon.onContextLoss(() => {
1064
+ this._disposeWebgl();
1065
+ if (!isRetry) {
1066
+ this._webglRecoveryTimer = setTimeout(() => {
1067
+ this._webglRecoveryTimer = null;
1068
+ this._loadWebglAddon(true);
1069
+ }, 1000);
1070
+ }
1071
+ });
1072
+ this.terminal.loadAddon(this.webglAddon);
1073
+ this._installWebglLongtaskGuard();
1074
+ } catch {
1075
+ // 若 loadAddon(activate) 中途抛出,addon 可能已创建 GL context/canvas/onContextLoss
1076
+ // disposable——只置 null 会泄漏,先显式 dispose 再置 null。
1077
+ try { this.webglAddon?.dispose(); } catch {}
1078
+ this.webglAddon = null;
1079
+ }
1080
+ }
1081
+
1082
+ _disposeWebgl() {
1083
+ // 清掉 pending 的 onContextLoss 恢复重试:longtask 降级(写 sticky)与 1s 恢复 timer
1084
+ // 交错时,不再依赖 sticky 检查巧合拦截重载已判废的 addon(mac 上 context loss 更频繁)。
1085
+ if (this._webglRecoveryTimer) {
1086
+ clearTimeout(this._webglRecoveryTimer);
1087
+ this._webglRecoveryTimer = null;
1088
+ }
1089
+ if (this._webglLongtaskObserver) {
1090
+ this._webglLongtaskObserver.disconnect();
1091
+ this._webglLongtaskObserver = null;
1092
+ }
1093
+ if (this.webglAddon) {
1094
+ try { this.webglAddon.dispose(); } catch {}
1095
+ this.webglAddon = null;
1096
+ }
1097
+ }
1098
+
1099
+ // GPU 长任务监测:滑动窗口内累积 stall 达到阈值则自动降级到 DOM 渲染器
1100
+ _installWebglLongtaskGuard() {
1101
+ if (typeof PerformanceObserver === 'undefined') return;
1102
+ const startTime = performance.now();
1103
+ const recentStalls = [];
1104
+
1105
+ this._webglLongtaskObserver = new PerformanceObserver((list) => {
1106
+ if (!this.webglAddon) return;
1107
+ const now = performance.now();
1108
+ if (now - startTime < WEBGL_GRACE_MS) return;
1109
+ for (const entry of list.getEntries()) {
1110
+ if (entry.duration >= WEBGL_STALL_MS) {
1111
+ recentStalls.push(now);
1112
+ }
1113
+ }
1114
+ while (recentStalls.length > 0 && now - recentStalls[0] > WEBGL_STALL_WINDOW_MS) {
1115
+ recentStalls.shift();
1116
+ }
1117
+ if (recentStalls.length >= WEBGL_STALL_COUNT) {
1118
+ console.warn('[cx-viewer] WebGL longtask guard: %d stalls in %ds, falling back to DOM renderer',
1119
+ recentStalls.length, WEBGL_STALL_WINDOW_MS / 1000);
1120
+ try { localStorage.setItem(WEBGL_STICKY_KEY, String(Date.now() + WEBGL_STICKY_TTL_MS)); } catch {}
1121
+ this._disposeWebgl();
1122
+ this.terminal?.refresh(0, this.terminal.rows - 1);
1123
+ }
1124
+ });
1125
+ try {
1126
+ this._webglLongtaskObserver.observe({ type: 'longtask', buffered: false });
1127
+ } catch {
1128
+ this._webglLongtaskObserver = null;
1129
+ }
1130
+ }
1131
+
1132
+ /**
1133
+ * 移动端固定 60 列:通过调整 fontSize 使 60 列恰好撑满屏幕宽度,
1134
+ * 行数根据缩放后的行高和可用高度动态计算。
1135
+ */
1136
+ _mobileFixedResize() {
1137
+ if (!this.terminal) return;
1138
+
1139
+ // 从 xterm 渲染器获取当前字符尺寸
1140
+ const cellDims = this.terminal._core?._renderService?.dimensions?.css?.cell;
1141
+ if (!cellDims || !cellDims.width || !cellDims.height) {
1142
+ // 渲染器尚未就绪,延迟重试
1143
+ setTimeout(() => this._mobileFixedResize(), 50);
1144
+ return;
1145
+ }
1146
+
1147
+ const MOBILE_COLS = 60;
1148
+ const padX = 16; // 8px * 2 容器内边距
1149
+ const padY = 8; // 4px * 2
1150
+ const topBarHeight = 40;
1151
+ const keybarHeight = 52;
1152
+
1153
+ const availableWidth = window.innerWidth - padX;
1154
+ const availableHeight = window.innerHeight - topBarHeight - keybarHeight - padY;
1155
+
1156
+ // 根据当前 fontSize 和 charWidth 的比例,计算让 60 列恰好填满宽度所需的 fontSize
1157
+ const currentFontSize = this.terminal.options.fontSize;
1158
+ const currentCharWidth = cellDims.width;
1159
+ const targetFontSize = Math.floor(currentFontSize * availableWidth / (MOBILE_COLS * currentCharWidth) * 10) / 10;
1160
+
1161
+ // 更新字号,xterm 会重新渲染
1162
+ this.terminal.options.fontSize = targetFontSize;
1163
+
1164
+ // 等渲染器更新后再计算行数
1165
+ requestAnimationFrame(() => {
1166
+ if (!this.terminal) return; // unmount 竞态:this.terminal._core 对 null 取属性会抛
1167
+ const newCellDims = this.terminal._core?._renderService?.dimensions?.css?.cell;
1168
+ const lineHeight = newCellDims?.height || cellDims.height;
1169
+ const rows = Math.max(5, Math.min(Math.floor(availableHeight / lineHeight), 100));
1170
+
1171
+ this.terminal.resize(MOBILE_COLS, rows);
1172
+ this.sendResize();
1173
+ });
1174
+ }
1175
+
1176
+ /**
1177
+ * 写入节流:委托给 TerminalWriteQueue(src/utils/terminalWriteQueue.js)。
1178
+ * 行为与原实现等价 —— 每帧最多 write 一个 32KB chunk,rAF 续约。
1179
+ * 收益:消除原 `_writeBuffer = _writeBuffer.slice(N)` 的 O(n²) 字符串切片
1180
+ * + UTF-16 surrogate 守卫 + 异常时不死循环 + drain 修 unmount 数据丢失。
1181
+ */
1182
+ _throttledWrite(data) {
1183
+ this._writeQ.push(data);
1184
+ }
1185
+
1186
+ // 同步排空(exit/state/toast 路径在自身 write 前调用,保留既有顺序语义)。
1187
+ // 注:与原实现一样,这里只 drain 已积累 buffer,不影响 xterm 内部 parser 异步队列。
1188
+ _flushWrite() {
1189
+ this._writeQ.drain();
1190
+ }
1191
+
1192
+ _handlePaste = (e) => {
1193
+ // 主动粘贴进行中:阻止原生 paste 叠加(见 attachCustomKeyEventHandler 的 _activePasteInFlight 注释)
1194
+ if (this._activePasteInFlight) { e.preventDefault?.(); e.stopPropagation?.(); return; }
1195
+ // 检查剪贴板中是否包含图片,如有则上传并将路径插入终端
1196
+ const items = e.clipboardData?.items;
1197
+ if (items) {
1198
+ for (const item of items) {
1199
+ if (item.type.startsWith('image/')) {
1200
+ e.preventDefault();
1201
+ e.stopPropagation();
1202
+ const file = item.getAsFile();
1203
+ if (file) this._uploadClipboardImage(file);
1204
+ return;
1205
+ }
1206
+ }
1207
+ }
1208
+
1209
+ const rawText = e.clipboardData?.getData('text');
1210
+ if (!rawText || !this.ws || this.ws.readyState !== WebSocket.OPEN) return;
1211
+ // paste-injection 防护 + bracketed-paste 包裹决策抽到 planPasteSend(见 utils/terminalClipboard.js):
1212
+ // 剪贴板内嵌的 \x1b[201~ 会提前闭合包裹、余下字节作真实按键注入;xterm 6.0 自动包裹不 sanitize
1213
+ // (上游 7.0 才修),故含该序列 / 多行时我们接管(preventDefault + 自行 sanitize 包裹),
1214
+ // 否则返回 null 交回 xterm / 浏览器原生处理。
1215
+ const data = planPasteSend(rawText, {
1216
+ bracketedPasteMode: this.terminal?.modes?.bracketedPasteMode,
1217
+ active: false,
1218
+ sanitize: sanitizeBracketPasteText,
1219
+ });
1220
+ if (data != null) {
1221
+ e.preventDefault();
1222
+ e.stopPropagation();
1223
+ this.ws.send(JSON.stringify({ type: 'input', data }));
1224
+ }
1225
+ };
1226
+
1227
+ // 主动粘贴的安全送出:复用 planPasteSend(active=true)。区别于 _handlePaste:这里没有原生
1228
+ // paste 事件让 xterm 自动包裹,故 bracketedPasteMode 时也自行包裹(planPasteSend 内已处理)。
1229
+ _pasteText = (rawText) => {
1230
+ if (!rawText || !this.ws || this.ws.readyState !== WebSocket.OPEN) return;
1231
+ const data = planPasteSend(rawText, {
1232
+ bracketedPasteMode: this.terminal?.modes?.bracketedPasteMode,
1233
+ active: true,
1234
+ sanitize: sanitizeBracketPasteText,
1235
+ });
1236
+ if (data != null) this.ws.send(JSON.stringify({ type: 'input', data }));
1237
+ };
1238
+
1239
+ // Ctrl+V 主动读剪贴板:优先取图片(与 _handlePaste 一致地走上传),否则取文本走 _pasteText。
1240
+ // 取不到文本(如剪贴板仅 text/html)或 read() 不可用 / 失败时,显式回退到 readText。
1241
+ _activePaste = async () => {
1242
+ const clip = navigator.clipboard;
1243
+ if (clip?.read) {
1244
+ let items = null;
1245
+ try { items = await clip.read(); }
1246
+ catch (err) { console.warn('[CX Viewer] clipboard.read() 失败,回退 readText', err); }
1247
+ if (items) {
1248
+ for (const item of items) {
1249
+ const imgType = item.types?.find((ty) => ty.startsWith('image/'));
1250
+ if (imgType) {
1251
+ try {
1252
+ const blob = await item.getType(imgType);
1253
+ this._uploadClipboardImage(new File([blob], 'clipboard-image', { type: imgType }));
1254
+ return;
1255
+ } catch { /* 取图失败 → 落到文本 */ }
1256
+ }
1257
+ }
1258
+ // 无图片:从 ClipboardItem 取 text/plain;取到则发送返回,取不到(仅 html 等)显式落到 readText
1259
+ const withText = items.find((it) => it.types?.includes('text/plain'));
1260
+ if (withText) {
1261
+ try {
1262
+ const text = await (await withText.getType('text/plain')).text();
1263
+ if (text) this._pasteText(text);
1264
+ return;
1265
+ } catch { /* 取文本失败 → 落到 readText */ }
1266
+ }
1267
+ }
1268
+ }
1269
+ if (clip?.readText) {
1270
+ try {
1271
+ const text = await clip.readText();
1272
+ if (text) this._pasteText(text);
1273
+ } catch (err) {
1274
+ console.warn('[CX Viewer] active paste failed; fall back to Ctrl+Shift+V', err);
1275
+ }
1276
+ }
1277
+ };
1278
+
1279
+ _uploadClipboardImage = async (file) => {
1280
+ try {
1281
+ const optimized = await downscaleForRetina(file);
1282
+ const path = await uploadFileAndGetPath(optimized);
1283
+ if (this.props.onFilePath) this.props.onFilePath(path);
1284
+ // Notify other views/devices about the uploaded image
1285
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1286
+ this.ws.send(JSON.stringify({ type: 'image-upload-notify', path, source: 'terminal' }));
1287
+ }
1288
+ if (this.terminal) this.terminal.focus();
1289
+ } catch (err) {
1290
+ console.error('[CX Viewer] Clipboard image upload failed:', err);
1291
+ message.error(t('ui.terminal.pasteImageFailed'));
1292
+ }
1293
+ };
1294
+
1295
+
1296
+ handleVirtualKey = (seq) => {
1297
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1298
+ this.ws.send(JSON.stringify({ type: 'input', data: seq }));
1299
+ }
1300
+ // 手机上不 focus 终端,避免弹出系统软键盘;主动 blur 防止先前已聚焦
1301
+ if (isMobile && !isPad) {
1302
+ const ta = this.containerRef.current?.querySelector('.xterm-helper-textarea');
1303
+ if (ta) ta.blur();
1304
+ } else {
1305
+ this.terminal?.focus();
1306
+ }
1307
+ };
1308
+
1309
+ /**
1310
+ * 移动端虚拟按键触摸处理:区分点击与拖动滚动。
1311
+ * 仅当触摸位移 < 阈值时才视为点击并触发按键,否则视为滚动不触发。
1312
+ */
1313
+ _vkTouchStart = (e) => {
1314
+ e.preventDefault(); // 阻止触摸导致 xterm textarea 获焦弹出键盘
1315
+ const touch = e.touches[0];
1316
+ this._vkStartX = touch.clientX;
1317
+ this._vkStartY = touch.clientY;
1318
+ this._vkMoved = false;
1319
+ this._vkTarget = e.currentTarget;
1320
+ this._vkTarget.classList.add(styles.virtualKeyPressed);
1321
+ };
1322
+
1323
+ _vkTouchMove = (e) => {
1324
+ if (this._vkMoved) return;
1325
+ const touch = e.touches[0];
1326
+ const dx = touch.clientX - this._vkStartX;
1327
+ const dy = touch.clientY - this._vkStartY;
1328
+ if (dx * dx + dy * dy > 64) { // 8px 阈值
1329
+ this._vkMoved = true;
1330
+ }
1331
+ };
1332
+
1333
+ _vkTouchEnd = (action, e) => {
1334
+ e.preventDefault(); // 阻止后续 ghost click
1335
+ this._vkTarget?.classList.remove(styles.virtualKeyPressed);
1336
+ this._vkTarget = null;
1337
+ if (!this._vkMoved) {
1338
+ action();
1339
+ }
1340
+ };
1341
+
1342
+ handleFileUpload = async (e) => {
1343
+ const file = e.target.files?.[0];
1344
+ if (!file) return;
1345
+ try {
1346
+ const path = await uploadFileAndGetPath(file);
1347
+ if (this.props.onFilePath) this.props.onFilePath(path);
1348
+ // Notify other views/devices about the uploaded file
1349
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1350
+ this.ws.send(JSON.stringify({ type: 'image-upload-notify', path, source: 'terminal' }));
1351
+ }
1352
+ // refocus terminal after upload (skip on mobile to avoid system keyboard popup)
1353
+ if ((!isMobile || isPad) && this.terminal) this.terminal.focus();
1354
+ } catch (err) {
1355
+ console.error('[CX Viewer] Upload failed:', err);
1356
+ }
1357
+ // reset so same file can be re-selected
1358
+ e.target.value = '';
1359
+ };
1360
+
1361
+ // --- 预置快捷方式相关 ---
1362
+ _savePresetShortcuts = (items, dismissed) => {
1363
+ if (this.props.onUpdatePreferences) {
1364
+ this.props.onUpdatePreferences(buildPresetShortcutsPayload(items, dismissed));
1365
+ }
1366
+ };
1367
+
1368
+ handlePresetAdd = () => {
1369
+ const description = this.state.presetAddText.trim();
1370
+ const teamName = this.state.presetAddName.trim();
1371
+ if (!description && !teamName) return;
1372
+ const { presetEditId, presetItems } = this.state;
1373
+ let next;
1374
+ if (presetEditId) {
1375
+ next = presetItems.map(i => {
1376
+ if (i.id !== presetEditId) return i;
1377
+ const updated = { ...i, teamName, description };
1378
+ if (i.builtinId) updated.modified = true;
1379
+ return updated;
1380
+ });
1381
+ } else {
1382
+ next = [...presetItems, { id: Date.now(), teamName, description }];
1383
+ }
1384
+ this.setState({ presetItems: next, presetAddVisible: false, presetAddText: '', presetAddName: '', presetEditId: null });
1385
+ this._savePresetShortcuts(next);
1386
+ };
1387
+
1388
+ handlePresetDelete = () => {
1389
+ const { presetItems, presetSelected } = this.state;
1390
+ if (presetSelected.size === 0) return;
1391
+ // 收集被删除的内置项 builtinId
1392
+ const dismissed = new Set(this._dismissedBuiltinPresets || []);
1393
+ for (const item of presetItems) {
1394
+ if (presetSelected.has(item.id) && item.builtinId) {
1395
+ dismissed.add(item.builtinId);
1396
+ }
1397
+ }
1398
+ this._dismissedBuiltinPresets = dismissed;
1399
+ const next = presetItems.filter(i => !presetSelected.has(i.id));
1400
+ this.setState({ presetItems: next, presetSelected: new Set() });
1401
+ this._savePresetShortcuts(next, dismissed);
1402
+ };
1403
+
1404
+ handlePresetToggle = (id) => {
1405
+ this.setState(prev => {
1406
+ const next = new Set(prev.presetSelected);
1407
+ next.has(id) ? next.delete(id) : next.add(id);
1408
+ return { presetSelected: next };
1409
+ });
1410
+ };
1411
+
1412
+ // --- 拖拽排序 ---
1413
+ _dragIdx = null;
1414
+ _dragOverIdx = null;
1415
+
1416
+ handleDragStart = (idx, e) => {
1417
+ e.stopPropagation();
1418
+ this._dragIdx = idx;
1419
+ e.dataTransfer.effectAllowed = 'move';
1420
+ e.dataTransfer.setData('text/x-preset-reorder', String(idx));
1421
+ requestAnimationFrame(() => this.forceUpdate());
1422
+ };
1423
+
1424
+ handleDragOver = (idx, e) => {
1425
+ e.preventDefault();
1426
+ e.stopPropagation();
1427
+ e.dataTransfer.dropEffect = 'move';
1428
+ if (this._dragOverIdx !== idx) {
1429
+ this._dragOverIdx = idx;
1430
+ this.forceUpdate();
1431
+ }
1432
+ };
1433
+
1434
+ handleDragEnd = (e) => {
1435
+ if (e) e.stopPropagation();
1436
+ this._dragIdx = null;
1437
+ this._dragOverIdx = null;
1438
+ this.forceUpdate();
1439
+ };
1440
+
1441
+ handleDragLeave = (idx, e) => {
1442
+ e.stopPropagation();
1443
+ if (this._dragOverIdx === idx) {
1444
+ this._dragOverIdx = null;
1445
+ this.forceUpdate();
1446
+ }
1447
+ };
1448
+
1449
+ handleDrop = (idx, e) => {
1450
+ e.preventDefault();
1451
+ e.stopPropagation();
1452
+ const from = this._dragIdx;
1453
+ if (from === null || from === idx) { this.handleDragEnd(); return; }
1454
+ const items = [...this.state.presetItems];
1455
+ const [moved] = items.splice(from, 1);
1456
+ items.splice(from < idx ? idx - 1 : idx, 0, moved);
1457
+ this.setState({ presetItems: items });
1458
+ this._savePresetShortcuts(items);
1459
+ this.handleDragEnd();
1460
+ };
1461
+
1462
+ // 级联子菜单 hover-intent 共享实现见 utils/quickMenuHoverIntent。
1463
+ // iPad 无 hover 不参与(tap 的 synthetic mouseEnter 会与 click 切换互抵),由点击行切换兜底;
1464
+ _qmHover = createQuickMenuHoverIntent({
1465
+ getExpanded: () => this.state.quickSettingsExpanded,
1466
+ setExpanded: (k) => this.setState({ quickSettingsExpanded: k }),
1467
+ skip: () => isPad,
1468
+ });
1469
+
1470
+ handlePresetSend = (description) => {
1471
+ if (!description) return;
1472
+ this.setState({ quickSettingsOpen: false, quickSettingsExpanded: null });
1473
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1474
+ this.ws.send(JSON.stringify({
1475
+ type: 'input-sequential',
1476
+ chunks: buildBracketPasteSubmitChunks(description),
1477
+ settleMs: BRACKET_PASTE_SUBMIT_SETTLE_MS,
1478
+ }));
1479
+ }
1480
+ if ((!isMobile || isPad) && this.terminal) this.terminal.focus();
1481
+ };
1482
+
1483
+ handleClearContext = () => {
1484
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1485
+ this.ws.send(JSON.stringify({
1486
+ type: 'input-sequential',
1487
+ chunks: buildBracketPasteSubmitChunks('/clear'),
1488
+ settleMs: BRACKET_PASTE_SUBMIT_SETTLE_MS,
1489
+ }));
1490
+ this.props.onClearContextOptimistic?.();
1491
+ }
1492
+ if ((!isMobile || isPad) && this.terminal) this.terminal.focus();
1493
+ };
1494
+
1495
+ handleUltraplanSend = () => {
1496
+ const trimmed = this.state.ultraplanPrompt.trim();
1497
+ if (!trimmed && this.state.ultraplanFiles.length === 0) return;
1498
+ const filePaths = this.state.ultraplanFiles.map(f => `"${f.path}"`).join(' ');
1499
+ const userInput = filePaths ? (trimmed ? `${filePaths} ${trimmed}` : filePaths) : trimmed;
1500
+ const variant = this.state.ultraplanVariant;
1501
+ let assembled;
1502
+ if (typeof variant === 'string' && variant.startsWith('custom:')) {
1503
+ const id = variant.slice('custom:'.length);
1504
+ const item = this.state.customUltraplanExperts.find(e => e.id === id);
1505
+ if (!item) { return; }
1506
+ assembled = buildLocalUltraplan(userInput, 'custom', undefined, item.content);
1507
+ } else {
1508
+ assembled = buildLocalUltraplan(userInput, variant);
1509
+ }
1510
+ // 先校验再重置,避免空模板导致用户输入被静默清空
1511
+ if (!assembled) return;
1512
+ this.setState({ ultraplanOpen: false, ultraplanPrompt: '', ultraplanVariant: 'codeExpert', ultraplanFiles: [] });
1513
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
1514
+ this.ws.send(JSON.stringify({
1515
+ type: 'input-sequential',
1516
+ chunks: buildBracketPasteSubmitChunks(assembled),
1517
+ settleMs: BRACKET_PASTE_SUBMIT_SETTLE_MS,
1518
+ }));
1519
+ }
1520
+ if ((!isMobile || isPad) && this.terminal) this.terminal.focus();
1521
+ };
1522
+
1523
+ openCustomUltraplanEditor = (item) => {
1524
+ // UltraPlan 是 Antd Popover(自带"点击外部即关闭"),编辑器是 Antd Modal(portal 挂 body)。
1525
+ // 打开编辑器时不主动收 Popover——保留 UltraPlan 在背景里(编辑器自带蒙层会压暗);
1526
+ // 编辑器 mask 引起的"外部点击"由下面 Popover 的 onOpenChange 守卫拦下(customUltraplanEditOpen)。
1527
+ this.setState({
1528
+ customUltraplanEditOpen: true,
1529
+ customUltraplanEditing: item || null,
1530
+ });
1531
+ };
1532
+
1533
+ closeCustomUltraplanEditor = () => {
1534
+ this.setState({
1535
+ customUltraplanEditOpen: false,
1536
+ customUltraplanEditing: null,
1537
+ });
1538
+ };
1539
+
1540
+ // UltraPlan 文件 / 专家逻辑委托给共享控制器(见 ../utils/ultraplanController)。方法名保持不变,render 零改动。
1541
+ saveCustomUltraplanExpert = (...a) => this._ultraplan.saveExpert(...a);
1542
+
1543
+ deleteCustomUltraplanExpert = (...a) => this._ultraplan.deleteExpert(...a);
1544
+
1545
+ // tab 条上每个专家的图标:内置 code=<> / research=放大镜,自定义=星形。
1546
+ handleUltraplanUpload = (...a) => this._ultraplan.handleUpload(...a);
1547
+
1548
+ handleUltraplanPaste = (...a) => this._ultraplan.handlePaste(...a);
1549
+
1550
+ handleUltraplanRemoveFile = (...a) => this._ultraplan.handleRemoveFile(...a);
1551
+
1552
+ render() {
1553
+ const { pendingImages, onRemovePendingImage } = this.props;
1554
+ return (
1555
+ <div className={styles.terminalPanel}>
1556
+ {/* === 主 terminal (Codex TUI 渲染区) ===
1557
+ 外层 .terminalContainer:padding + focus 边线;内层 .terminalHost:xterm 实际父容器,
1558
+ margin-bottom 4px 让 fitAddon 拿到的高度始终 -4px,xterm-screen 接触不到下方 toolbar */}
1559
+ <div
1560
+ className={`${styles.terminalContainer}${this.state.terminalFocused ? ` ${styles.terminalContainerFocused}` : ''}`}
1561
+ >
1562
+ <div ref={this.containerRef} className={styles.terminalHost} />
1563
+ </div>
1564
+ {pendingImages?.length > 0 && (
1565
+ <div className={styles.pendingFileStrip}>
1566
+ {pendingImages.map((img, i) => {
1567
+ const fileName = img.path.split('/').pop() || img.path;
1568
+ const isImage = /\.(png|jpe?g|gif|svg|bmp|webp|avif|ico|icns)$/i.test(fileName);
1569
+ const src = apiUrl(`/api/file-raw?path=${encodeURIComponent(img.path)}`);
1570
+ return isImage ? (
1571
+ <div key={img.path} className={styles.pendingImageItem}>
1572
+ <img
1573
+ src={src}
1574
+ className={styles.pendingImageThumb}
1575
+ alt={fileName}
1576
+ role="button"
1577
+ tabIndex={0}
1578
+ onClick={() => this.setState({ lightbox: { src, alt: fileName } })}
1579
+ onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); this.setState({ lightbox: { src, alt: fileName } }); } }}
1580
+ />
1581
+ <ConfirmRemoveButton
1582
+ title={t('ui.chatInput.confirmRemoveImage')}
1583
+ onConfirm={() => onRemovePendingImage?.(i)}
1584
+ className={styles.pendingImageRemove}
1585
+ ariaLabel={t('ui.chatInput.removeImage')}
1586
+ >&times;</ConfirmRemoveButton>
1587
+ </div>
1588
+ ) : (
1589
+ <span key={img.path} className={styles.pendingFileTag}>
1590
+ <span className={styles.pendingFileName}>{fileName}</span>
1591
+ <ConfirmRemoveButton
1592
+ title={t('ui.chatInput.confirmRemoveFile')}
1593
+ onConfirm={() => onRemovePendingImage?.(i)}
1594
+ className={styles.pendingFileClose}
1595
+ ariaLabel={t('ui.chatInput.removeImage')}
1596
+ >&times;</ConfirmRemoveButton>
1597
+ </span>
1598
+ );
1599
+ })}
1600
+ </div>
1601
+ )}
1602
+ <input type="file" ref={this.fileInputRef} className={styles.hiddenFileInput} onChange={this.handleFileUpload} />
1603
+ {(!isMobile || isPad) && (
1604
+ <div className={styles.terminalToolbar}>
1605
+ <div className={styles.toolbarLeft}>
1606
+ <Popover
1607
+ trigger="click"
1608
+ placement="top"
1609
+ open={this.state.quickSettingsOpen}
1610
+ onOpenChange={(v) => {
1611
+ if (!v) this._qmHover.cancel();
1612
+ this.setState(v ? { quickSettingsOpen: true } : { quickSettingsOpen: false, quickSettingsExpanded: null });
1613
+ }}
1614
+ overlayInnerStyle={{ background: 'var(--bg-elevated)', border: '1px solid var(--border-hover)', borderRadius: 8, padding: 4, minWidth: 200 }}
1615
+ content={
1616
+ <div className={styles.presetMenu}>
1617
+ <QuickAutoApproveRows
1618
+ approvalsReviewer={this.props.approvalsReviewer}
1619
+ planAutoApproveSeconds={this.props.planAutoApproveSeconds}
1620
+ onApprovalsReviewerChange={this.props.onApprovalsReviewerChange}
1621
+ onPlanAutoApproveChange={this.props.onPlanAutoApproveChange}
1622
+ expandedKey={this.state.quickSettingsExpanded}
1623
+ onToggle={(k) => this.setState({ quickSettingsExpanded: k })}
1624
+ onHoverEnter={this._qmHover.enter}
1625
+ onHoverLeave={this._qmHover.leave}
1626
+ />
1627
+ {/* AgentTeam 快捷指令(自工具栏独立按钮迁入,置于菜单底部)。 */}
1628
+ <div
1629
+ className={`${chrome.quickMenuGroup} ${this.state.quickSettingsExpanded === 'agentteam' ? chrome.quickMenuGroupOpen : ''}`}
1630
+ onMouseEnter={() => this._qmHover.enter('agentteam')}
1631
+ onMouseLeave={() => this._qmHover.leave('agentteam')}
1632
+ >
1633
+ <button
1634
+ className={chrome.quickMenuRow}
1635
+ onClick={() => this.setState(s => ({ quickSettingsExpanded: s.quickSettingsExpanded === 'agentteam' ? null : 'agentteam' }))}
1636
+ >
1637
+ <span className={chrome.quickMenuRowIcon}><AgentTeamIcon /></span>
1638
+ <span className={chrome.quickMenuLabel}>{t('ui.terminal.agentTeam')}</span>
1639
+ <span className={chrome.quickMenuCaret}>▸</span>
1640
+ </button>
1641
+ <div className={chrome.quickMenuSubWrap}>
1642
+ <div className={chrome.quickMenuSub}>
1643
+ <button className={`${styles.presetMenuItem} ${styles.presetMenuItemMuted}`} onClick={() => this.setState({ quickSettingsOpen: false, quickSettingsExpanded: null, presetModalVisible: true })}>
1644
+ {t('ui.terminal.customShortcuts')}
1645
+ </button>
1646
+ {this.state.presetItems.length === 0 ? (
1647
+ <div className={styles.popoverEmptyHint}>—</div>
1648
+ ) : (
1649
+ this.state.presetItems.map(item => {
1650
+ const isBuiltinRaw = item.builtinId && !item.modified;
1651
+ const name = isBuiltinRaw ? t(item.teamName) : item.teamName;
1652
+ const desc = isBuiltinRaw ? t(item.description) : item.description;
1653
+ return (
1654
+ <button key={item.id} className={styles.presetMenuItem} onClick={() => this.handlePresetSend(desc)} title={desc}>
1655
+ {name || desc}
1656
+ </button>
1657
+ );
1658
+ })
1659
+ )}
1660
+ </div>
1661
+ </div>
1662
+ </div>
1663
+ </div>
1664
+ }
1665
+ >
1666
+ <button
1667
+ className={`${styles.toolbarBtn} ${styles.quickSettingsBtn} ${this.state.quickSettingsOpen ? styles.quickSettingsBtnOpen : ''}`}
1668
+ title={t('ui.terminal.quickSettings')}
1669
+ >
1670
+ <span className={styles.quickSettingsIcon}><span className={styles.quickSettingsGlyph} style={SPARKLE_MASK_STYLE} aria-hidden="true" /></span>
1671
+ </button>
1672
+ </Popover>
1673
+ <Popover
1674
+ trigger="click"
1675
+ placement="top"
1676
+ open={this.state.ultraplanOpen}
1677
+ onOpenChange={(v) => {
1678
+ // customUltraplanEditOpen 守卫:编辑器(Antd Modal)通过 portal 挂 body,它的 mask 对本
1679
+ // Popover 而言是"外部点击"。事件顺序保护住了我们:
1680
+ // rc-trigger 注册 capture-phase mousedown(useWinClick.js)→ 早于 rc-dialog 的 bubble
1681
+ // click → onOpenChange 触发时 mask click 还没冒泡到 editor.onCancel,
1682
+ // customUltraplanEditOpen 仍为 true,直接拦掉本次 Popover 关闭。
1683
+ // (这个机制与 React 是否批量化 setState 无关,对 React 19 / concurrent 仍稳。)
1684
+ // ultraplanManagerOpen(管理专家弹窗)同理:它也是 portal Modal,关闭它不应连带收起本 Popover。
1685
+ if (!v && (this.state.lightbox || this.state.ultraplanLightbox || this.state.ultraplanConfirming || this.state.customUltraplanEditOpen || this.state.ultraplanManagerOpen)) return;
1686
+ if (!v) this.setState({ ultraplanOpen: false });
1687
+ }}
1688
+ overlayClassName="cxv-ultraplan-popover"
1689
+ overlayInnerStyle={ultraplanOverlayInnerStyle(this.state.ultraplanPopoverSize)}
1690
+ content={
1691
+ <UltraplanPanel
1692
+ variant={this.state.ultraplanVariant}
1693
+ prompt={this.state.ultraplanPrompt}
1694
+ files={this.state.ultraplanFiles}
1695
+ customExperts={this.state.customUltraplanExperts}
1696
+ expertOrder={this.state.ultraplanExpertOrder}
1697
+ expertHidden={this.state.ultraplanExpertHidden}
1698
+ onVariantChange={(v) => this.setState({ ultraplanVariant: v })}
1699
+ onPromptChange={(p) => this.setState({ ultraplanPrompt: p })}
1700
+ onSend={this.handleUltraplanSend}
1701
+ onUpload={this.handleUltraplanUpload}
1702
+ onPaste={this.handleUltraplanPaste}
1703
+ onRemoveFile={this.handleUltraplanRemoveFile}
1704
+ onClose={() => this.setState({ ultraplanOpen: false })}
1705
+ onOpenManager={() => this.setState({ ultraplanManagerOpen: true })}
1706
+ onOpenCustomEditor={this.openCustomUltraplanEditor}
1707
+ onPreviewImage={(lb) => this.setState({ ultraplanLightbox: lb })}
1708
+ onConfirmingChange={(open) => this.setState({ ultraplanConfirming: open })}
1709
+ onSizeChange={(size) => this.setState({ ultraplanPopoverSize: size })}
1710
+ />
1711
+ }
1712
+ >
1713
+ <button className={`${styles.toolbarBtn} ${this.state.ultraplanOpen ? styles.ultraToggleActive : ''}`} onClick={() => this.setState({ ultraplanOpen: true })} title={t('ui.ultraplan')}>
1714
+ <span className={styles.ultraToggleIcon} style={ULTRAPLAN_MASK_STYLE} aria-hidden="true" />
1715
+ <span className={styles.ultraToggleLabel}>UltraPlan</span>
1716
+ </button>
1717
+ </Popover>
1718
+ <button className={styles.toolbarBtn} onClick={() => this.fileInputRef.current?.click()} title={t('ui.terminal.upload')}>
1719
+ <UploadIcon />
1720
+ </button>
1721
+ {(() => {
1722
+ // i18n 是单句 "X?Y。" 结构,按 ? / ? 拆成 Popconfirm 的 title + description 以换行呈现
1723
+ const confirmFull = t('ui.chatInput.clearContextConfirm');
1724
+ const qIdx = Math.max(confirmFull.indexOf('?'), confirmFull.indexOf('?'));
1725
+ const confirmTitle = qIdx > 0 ? confirmFull.slice(0, qIdx + 1) : confirmFull;
1726
+ const confirmDesc = qIdx > 0 ? confirmFull.slice(qIdx + 1).trim() : null;
1727
+ return (
1728
+ <Popconfirm
1729
+ title={confirmTitle}
1730
+ description={confirmDesc}
1731
+ okText={t('ui.chatInput.clearContext')}
1732
+ cancelText={t('ui.common.confirmCancel')}
1733
+ okButtonProps={{ danger: true }}
1734
+ placement="top"
1735
+ onConfirm={this.handleClearContext}
1736
+ >
1737
+ <button className={styles.toolbarBtn} title={t('ui.chatInput.clearContext')}>
1738
+ <TrashIcon />
1739
+ </button>
1740
+ </Popconfirm>
1741
+ );
1742
+ })()}
1743
+ </div>
1744
+ {/* 中段:血条 portal slot;左/右两端控件分别由 toolbarLeft / toolbarRight 包裹,
1745
+ slot 在中间用 flex-basis 200 + flex-shrink 1 自适应左右控件之间的空间,封顶 200px */}
1746
+ <div className={styles.ctxBarSlot} ref={this.props.setContextBarSlot} />
1747
+ <div className={styles.toolbarRight}>
1748
+ <button
1749
+ className={`${styles.toolbarBtn}${this.state.scratchOpen ? ` ${styles.toolbarBtnActive}` : ''}`}
1750
+ onClick={this.toggleScratch}
1751
+ aria-pressed={this.state.scratchOpen}
1752
+ aria-label={this.state.scratchOpen ? t('ui.terminal.scratchTerminalClose') : t('ui.terminal.scratchTerminalOpen')}
1753
+ title={this.state.scratchOpen ? t('ui.terminal.scratchTerminalClose') : t('ui.terminal.scratchTerminalOpen')}
1754
+ >
1755
+ <ScratchTerminalIcon />
1756
+ </button>
1757
+ </div>
1758
+ </div>
1759
+ )}
1760
+ {(!isMobile || isPad) && this.state.scratchOpen && (
1761
+ <>
1762
+ <div
1763
+ className={`${styles.scratchResizer}${this.state.isDraggingScratch ? ` ${styles.scratchResizerDragging}` : ''}`}
1764
+ onPointerDown={this.handleScratchResizerPointerDown}
1765
+ onPointerMove={this.handleScratchResizerPointerMove}
1766
+ onPointerUp={this.handleScratchResizerPointerUp}
1767
+ onPointerCancel={this.handleScratchResizerPointerUp}
1768
+ role="separator"
1769
+ aria-orientation="horizontal"
1770
+ aria-label={t('ui.terminal.scratchResizer')}
1771
+ />
1772
+ <div
1773
+ ref={this._scratchWrapRef}
1774
+ className={styles.scratchWrap}
1775
+ >
1776
+ <div className={styles.scratchTabs} role="tablist" aria-orientation="vertical">
1777
+ {this.state.scratchTabs.map((tab, idx) => {
1778
+ const isActive = tab.id === this.state.activeScratchTabId;
1779
+ const isLast = this.state.scratchTabs.length === 1;
1780
+ // 同名 shell 重复时追加序号区分
1781
+ // 占位 'zsh':老版本 server 不发 shellBasename 时也展示符合 macOS 默认 shell 的名字;
1782
+ // 新 server 的 WS state 消息携带真实 basename 后会覆盖(bash/fish 用户也对)
1783
+ const baseLabel = this.state.scratchShellBasename || 'zsh';
1784
+ const label = baseLabel + (this.state.scratchTabs.length > 1 ? ` ${idx + 1}` : '');
1785
+ return (
1786
+ <div
1787
+ key={tab.id}
1788
+ role="tab"
1789
+ aria-selected={isActive}
1790
+ tabIndex={isActive ? 0 : -1}
1791
+ className={`${styles.scratchTab}${isActive ? ` ${styles.scratchTabActive}` : ''}`}
1792
+ onClick={() => this.handleScratchTabClick(tab.id)}
1793
+ title={label}
1794
+ >
1795
+ <span className={styles.scratchTabIcon}><ScratchTerminalIcon /></span>
1796
+ <span className={styles.scratchTabLabel}>{label}</span>
1797
+ {!isLast && (
1798
+ <button
1799
+ className={styles.scratchTabClose}
1800
+ onClick={(e) => this.handleScratchTabClose(tab.id, e)}
1801
+ title={t('ui.terminal.scratchTabClose')}
1802
+ aria-label={t('ui.terminal.scratchTabClose')}
1803
+ >
1804
+ <CloseIcon />
1805
+ </button>
1806
+ )}
1807
+ </div>
1808
+ );
1809
+ })}
1810
+ <button
1811
+ className={styles.scratchTabAdd}
1812
+ onClick={this.handleScratchTabAdd}
1813
+ disabled={this.state.scratchTabs.length >= SCRATCH_TAB_MAX}
1814
+ title={t('ui.terminal.scratchTabAdd')}
1815
+ aria-label={t('ui.terminal.scratchTabAdd')}
1816
+ >
1817
+ <PlusIcon />
1818
+ </button>
1819
+ </div>
1820
+ <div className={`${styles.scratchPanes}${this.state.scratchFocused ? ` ${styles.scratchPanesFocused}` : ''}`}>
1821
+ {this.state.scratchTabs.map((tab) => {
1822
+ const isActive = tab.id === this.state.activeScratchTabId;
1823
+ return (
1824
+ <div
1825
+ key={tab.id}
1826
+ className={`${styles.scratchPane}${isActive ? ` ${styles.scratchPaneActive}` : ''}`}
1827
+ role="tabpanel"
1828
+ >
1829
+ <ScratchTerminal
1830
+ ref={this._getScratchRef(tab.id)}
1831
+ id={tab.id}
1832
+ onFocusChange={(f) => this.handleScratchTabFocusChange(tab.id, f)}
1833
+ onShellInfo={this.handleScratchShellInfo}
1834
+ />
1835
+ </div>
1836
+ );
1837
+ })}
1838
+ </div>
1839
+ </div>
1840
+ </>
1841
+ )}
1842
+ {(isMobile && !isPad) && (
1843
+ <div className={styles.virtualKeybar}>
1844
+ {VIRTUAL_KEYS.map(k => (
1845
+ <button
1846
+ key={k.label}
1847
+ className={styles.virtualKey}
1848
+ onTouchStart={this._vkTouchStart}
1849
+ onTouchMove={this._vkTouchMove}
1850
+ onTouchEnd={(e) => this._vkTouchEnd(() => this.handleVirtualKey(k.seq), e)}
1851
+ >
1852
+ {k.label}
1853
+ </button>
1854
+ ))}
1855
+ {/* TODO: 移动端文件上传 - 受限于浏览器安全策略,触摸事件链中 input.click() 无法触发文件选择器
1856
+ <span className={styles.vkSeparator} />
1857
+ <button
1858
+ className={`${styles.virtualKey} ${styles.vkAction}`}
1859
+ onClick={() => {
1860
+ this.fileInputRef.current?.click();
1861
+ const ta = this.containerRef.current?.querySelector('.xterm-helper-textarea');
1862
+ if (ta) ta.blur();
1863
+ }}
1864
+ title={t('ui.terminal.upload')}
1865
+ >
1866
+ <UploadIcon />
1867
+ </button>
1868
+ */}
1869
+ {this.state.presetItems.length > 0 && (
1870
+ <>
1871
+ <span className={styles.vkSeparator} />
1872
+ {this.state.presetItems.map(item => {
1873
+ const isBuiltinRaw = item.builtinId && !item.modified;
1874
+ const name = isBuiltinRaw ? t(item.teamName) : item.teamName;
1875
+ const desc = isBuiltinRaw ? t(item.description) : item.description;
1876
+ return (
1877
+ <button
1878
+ key={item.id}
1879
+ className={`${styles.virtualKey} ${styles.vkAction} ${styles.vkTeamPreset}`}
1880
+ onTouchStart={this._vkTouchStart}
1881
+ onTouchMove={this._vkTouchMove}
1882
+ onTouchEnd={(e) => this._vkTouchEnd(() => this.handlePresetSend(desc), e)}
1883
+ title={desc}
1884
+ >
1885
+ <AgentTeamIcon /><span className={styles.vkTeamLabel}>{name || desc}</span>
1886
+ </button>
1887
+ );
1888
+ })}
1889
+ </>
1890
+ )}
1891
+ </div>
1892
+ )}
1893
+ {/* 预置快捷方式弹窗 */}
1894
+ <Modal
1895
+ title={t('ui.terminal.presetShortcuts')}
1896
+ open={this.state.presetModalVisible}
1897
+ onCancel={() => this.setState({ presetModalVisible: false, presetSelected: new Set() })}
1898
+ footer={null}
1899
+ width={800}
1900
+ styles={{ content: { background: 'var(--bg-elevated)', border: '1px solid var(--border-light)' }, header: { background: 'var(--bg-elevated)', borderBottom: 'none' } }}
1901
+ >
1902
+ <div className={styles.presetSectionHeader}>
1903
+ <span className={styles.presetSectionTitle}>{t('ui.terminal.agentTeamCustom')}</span>
1904
+ </div>
1905
+ <div className={styles.presetList} onDragOver={(e) => { e.preventDefault(); e.stopPropagation(); }} onDrop={(e) => { e.preventDefault(); e.stopPropagation(); }}>
1906
+ {this.state.presetItems.length === 0 ? (
1907
+ <div className={styles.presetListEmptyHint}>—</div>
1908
+ ) : (
1909
+ this.state.presetItems.map((item, idx) => {
1910
+ const isBuiltinRaw = item.builtinId && !item.modified;
1911
+ const name = isBuiltinRaw ? t(item.teamName) : item.teamName;
1912
+ const desc = isBuiltinRaw ? t(item.description) : item.description;
1913
+ const isDragging = this._dragIdx === idx;
1914
+ const isDragOver = this._dragOverIdx === idx && this._dragIdx !== idx;
1915
+ return (
1916
+ <div
1917
+ key={item.id}
1918
+ className={`${styles.presetRow} ${isDragging ? styles.presetRowDragging : ''} ${isDragOver ? styles.presetRowDragOver : ''}`}
1919
+ onDragOver={(e) => this.handleDragOver(idx, e)}
1920
+ onDragLeave={(e) => this.handleDragLeave(idx, e)}
1921
+ onDrop={(e) => this.handleDrop(idx, e)}
1922
+ onDragEnd={this.handleDragEnd}
1923
+ >
1924
+ <span
1925
+ className={styles.dragHandle}
1926
+ draggable
1927
+ onDragStart={(e) => this.handleDragStart(idx, e)}
1928
+ >
1929
+ <svg viewBox="0 0 10 16" width="10" height="16" fill="currentColor">
1930
+ <circle cx="3" cy="3" r="1.2"/><circle cx="7" cy="3" r="1.2"/>
1931
+ <circle cx="3" cy="8" r="1.2"/><circle cx="7" cy="8" r="1.2"/>
1932
+ <circle cx="3" cy="13" r="1.2"/><circle cx="7" cy="13" r="1.2"/>
1933
+ </svg>
1934
+ </span>
1935
+ <Checkbox
1936
+ checked={this.state.presetSelected.has(item.id)}
1937
+ onChange={() => this.handlePresetToggle(item.id)}
1938
+ />
1939
+ <span className={styles.presetName} title={name}>{name || '—'}</span>
1940
+ <span className={styles.presetText} title={desc}>{desc}</span>
1941
+ <Button size="small" type="link" onClick={() => this.setState({ presetAddVisible: true, presetAddName: isBuiltinRaw ? t(item.teamName) : item.teamName, presetAddText: isBuiltinRaw ? t(item.description) : item.description, presetEditId: item.id })}>{t('ui.terminal.editItem')}</Button>
1942
+ </div>
1943
+ );
1944
+ })
1945
+ )}
1946
+ </div>
1947
+ <div className={styles.presetActions}>
1948
+ <Button size="small" danger disabled={this.state.presetSelected.size === 0} onClick={this.handlePresetDelete}>{t('ui.terminal.deleteSelected')}</Button>
1949
+ <Button size="small" onClick={() => this.setState({ presetAddVisible: true, presetAddName: '', presetAddText: '', presetEditId: null })}>{t('ui.terminal.addItem')}</Button>
1950
+ </div>
1951
+ </Modal>
1952
+
1953
+ {/* 添加快捷方式弹窗 */}
1954
+ <Modal
1955
+ title={this.state.presetEditId ? t('ui.terminal.editItem') : t('ui.terminal.addItem')}
1956
+ open={this.state.presetAddVisible}
1957
+ onCancel={() => this.setState({ presetAddVisible: false, presetAddName: '', presetAddText: '', presetEditId: null })}
1958
+ onOk={this.handlePresetAdd}
1959
+ okText={this.state.presetEditId ? t('ui.ok') : t('ui.terminal.addItem')}
1960
+ cancelText={t('ui.cancel')}
1961
+ okButtonProps={{ disabled: !this.state.presetAddText.trim() && !this.state.presetAddName.trim() }}
1962
+ width="fit-content"
1963
+ styles={{ content: { background: 'var(--bg-elevated)', border: '1px solid var(--border-light)' }, header: { background: 'var(--bg-elevated)', borderBottom: 'none' } }}
1964
+ >
1965
+ <div className={styles.presetFormField}>
1966
+ <label className={styles.presetFormLabel}>Team {t('ui.terminal.teamName')}</label>
1967
+ <input
1968
+ className={styles.presetInput}
1969
+ placeholder={t('ui.terminal.teamNamePlaceholder')}
1970
+ value={this.state.presetAddName}
1971
+ onChange={(e) => this.setState({ presetAddName: e.target.value })}
1972
+ />
1973
+ </div>
1974
+ <div>
1975
+ <label className={styles.presetFormLabel}>Team {t('ui.terminal.teamDesc')}</label>
1976
+ <textarea
1977
+ className={styles.presetTextarea}
1978
+ rows={15}
1979
+ placeholder={t('ui.terminal.presetInputPlaceholder')}
1980
+ value={this.state.presetAddText}
1981
+ onChange={(e) => this.setState({ presetAddText: e.target.value })}
1982
+ onKeyDown={(e) => { if (e.key === 'Enter') e.stopPropagation(); }}
1983
+ />
1984
+ </div>
1985
+ </Modal>
1986
+ <CustomUltraplanEditModal
1987
+ open={this.state.customUltraplanEditOpen}
1988
+ initial={this.state.customUltraplanEditing}
1989
+ onSave={this.saveCustomUltraplanExpert}
1990
+ onDelete={this.deleteCustomUltraplanExpert}
1991
+ onClose={this.closeCustomUltraplanEditor}
1992
+ />
1993
+ <UltraplanExpertManagerModal
1994
+ open={this.state.ultraplanManagerOpen}
1995
+ customExperts={this.state.customUltraplanExperts}
1996
+ order={this.state.ultraplanExpertOrder}
1997
+ hidden={this.state.ultraplanExpertHidden}
1998
+ onPersist={({ order, hidden }) => this._ultraplan.persistExpertLayout({ order, hidden })}
1999
+ onClose={() => this.setState({ ultraplanManagerOpen: false })}
2000
+ />
2001
+ {this.state.lightbox && (
2002
+ <ImageLightbox
2003
+ src={this.state.lightbox.src}
2004
+ alt={this.state.lightbox.alt}
2005
+ onClose={() => this.setState({ lightbox: null })}
2006
+ />
2007
+ )}
2008
+ {this.state.ultraplanLightbox && (
2009
+ <ImageLightbox
2010
+ src={this.state.ultraplanLightbox.src}
2011
+ alt={this.state.ultraplanLightbox.alt}
2012
+ zIndex={1200}
2013
+ onClose={() => this.setState({ ultraplanLightbox: null })}
2014
+ />
2015
+ )}
2016
+ </div>
2017
+ );
2018
+ }
2019
+ }
2020
+
2021
+ export default TerminalPanel;