@qwen-code/qwen-code 0.19.5 → 0.19.6

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 (233) hide show
  1. package/bundled/dataviz/SKILL.md +50 -0
  2. package/bundled/dataviz/references/anti-patterns.md +12 -0
  3. package/bundled/dataviz/references/choosing-a-form.md +16 -0
  4. package/bundled/dataviz/references/palette.md +57 -0
  5. package/bundled/dataviz/scripts/validate_palette.js +328 -0
  6. package/bundled/loop/SKILL.md +1 -1
  7. package/bundled/qc-helper/docs/configuration/settings.md +9 -8
  8. package/bundled/qc-helper/docs/features/headless.md +2 -2
  9. package/bundled/qc-helper/docs/features/scheduled-tasks.md +4 -2
  10. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +1 -1
  11. package/chunks/{MaxSizedBox-5JV77KRA.js → MaxSizedBox-SK7CUWZQ.js} +14 -14
  12. package/chunks/{StandaloneSessionPicker-MGUGB6PH.js → StandaloneSessionPicker-G44HGSAP.js} +25 -25
  13. package/chunks/{acpAgent-4F36XM3X.js → acpAgent-PKCTYWJV.js} +346 -131
  14. package/chunks/{agent-IWBUZI6A.js → agent-IYMHUXWB.js} +11 -11
  15. package/chunks/{agent-headless-JUTICAYO.js → agent-headless-L2DAW6I5.js} +11 -11
  16. package/chunks/{anthropicContentGenerator-WL3LJOUB.js → anthropicContentGenerator-H5ZOEENQ.js} +2 -2
  17. package/chunks/{artifact-tool-W76WC2JX.js → artifact-tool-SLYPWG3C.js} +15 -2
  18. package/chunks/{askUserQuestion-J3P6TH3V.js → askUserQuestion-OKPTECON.js} +1 -1
  19. package/chunks/{bridge-DHZHQ4UV.js → bridge-DF3IJQ5V.js} +17 -16
  20. package/chunks/{channel-worker-supervisor-EVPAYNZ5.js → channel-worker-supervisor-JUYQ5Z4R.js} +5 -5
  21. package/chunks/chunk-2INJBYLJ.js +949 -0
  22. package/chunks/chunk-3RW4AZJV.js +5063 -0
  23. package/chunks/{chunk-NSSVORTQ.js → chunk-3UC7ZC43.js} +16 -12
  24. package/chunks/chunk-3VJ7MT3N.js +111 -0
  25. package/chunks/{chunk-DRS2HTNT.js → chunk-3X76L4UF.js} +5 -5
  26. package/chunks/{chunk-PPFWEV7G.js → chunk-4RQIB5UZ.js} +62 -62
  27. package/chunks/{chunk-EROWZQN7.js → chunk-57NRQM3P.js} +6 -6
  28. package/chunks/{chunk-L7OJ3ZO3.js → chunk-5ES5YPED.js} +1 -1
  29. package/chunks/{chunk-RNGAT2Y2.js → chunk-5WQF27GW.js} +1 -1
  30. package/chunks/{chunk-7DMQRPC7.js → chunk-6BEOH4KK.js} +1 -1
  31. package/chunks/{chunk-CXBG27SF.js → chunk-6IAWPIQ6.js} +3 -2
  32. package/chunks/{chunk-DM4E337C.js → chunk-6QVRLKTZ.js} +4 -4
  33. package/chunks/{chunk-RM3PGSGL.js → chunk-6SHO7WFF.js} +15 -2
  34. package/chunks/{chunk-LHMZCIKL.js → chunk-7Z6UEJA4.js} +3 -1
  35. package/chunks/{chunk-SBMHB6N5.js → chunk-A34EPIUV.js} +12 -12
  36. package/chunks/{chunk-6QTCOQX7.js → chunk-AGZF43UV.js} +1967 -1399
  37. package/chunks/{chunk-QHYITL6P.js → chunk-BOAWGUY6.js} +5 -11
  38. package/chunks/{chunk-TN6RT6EJ.js → chunk-C2QKQZEQ.js} +16 -4
  39. package/chunks/{chunk-BC4R5C5R.js → chunk-CEYA7K7C.js} +32 -6
  40. package/chunks/{chunk-R6RI2HIC.js → chunk-CLQPBI4H.js} +40 -13
  41. package/chunks/{chunk-OQHLUA2Y.js → chunk-DBF3HTLT.js} +3 -3
  42. package/chunks/{chunk-SJBIFVD2.js → chunk-DMSNJDWG.js} +5 -1
  43. package/chunks/{chunk-KKQWC6WS.js → chunk-DNV4FSN5.js} +1 -1
  44. package/chunks/chunk-DXXNMPJH.js +5468 -0
  45. package/chunks/{chunk-CBJE2PLG.js → chunk-FDY3XOTM.js} +2 -2
  46. package/chunks/{chunk-NDY7OENU.js → chunk-FPHA7WIZ.js} +2 -2
  47. package/chunks/{chunk-MNOXKSM2.js → chunk-FZ5NVRVK.js} +1 -1
  48. package/chunks/{chunk-UJT42DB6.js → chunk-GQBRGBLS.js} +5 -5
  49. package/chunks/{chunk-Y4UQT3PM.js → chunk-HCFSKO6K.js} +1 -1
  50. package/chunks/{chunk-2Z43HUXT.js → chunk-HLKG6CZN.js} +3 -2
  51. package/chunks/{chunk-WALEWZ44.js → chunk-IUSKVKH5.js} +1 -1
  52. package/chunks/{chunk-XKSCTXPK.js → chunk-J6ABRKAB.js} +2 -1
  53. package/chunks/{chunk-DX3TKXNT.js → chunk-JA5KWZTJ.js} +1 -1
  54. package/chunks/{chunk-CHY5C5T4.js → chunk-JN2VJ33O.js} +171 -79
  55. package/chunks/{chunk-YTFBURQD.js → chunk-KYTQOCDE.js} +1 -1
  56. package/chunks/{chunk-BPFJQGY7.js → chunk-LM3YCCZJ.js} +164 -5
  57. package/chunks/{chunk-ZISMVA6U.js → chunk-LXFCHX4X.js} +1371 -24
  58. package/chunks/{chunk-6KPZJJ6U.js → chunk-MBWLP5OT.js} +9 -9
  59. package/chunks/{chunk-IMAMNLY6.js → chunk-MHQKYQDS.js} +3 -3
  60. package/chunks/{chunk-M5ITDKSM.js → chunk-MJKEQSZI.js} +1 -1
  61. package/chunks/{chunk-MTNTVOJR.js → chunk-MJKMIQMK.js} +5 -2
  62. package/chunks/{chunk-CSPSJU5R.js → chunk-MX7CTJHR.js} +16 -16
  63. package/chunks/{chunk-HISPEX42.js → chunk-N2IJLN2L.js} +7 -7
  64. package/chunks/{chunk-YCU7QV7Q.js → chunk-N4YJQTRL.js} +4 -0
  65. package/chunks/{chunk-R3UWLLRQ.js → chunk-NUK2PFSU.js} +1 -1
  66. package/chunks/{chunk-YXK4GPYO.js → chunk-NVFJSIAX.js} +29 -0
  67. package/chunks/{chunk-4MCC4XHH.js → chunk-O2RJARYU.js} +38 -37
  68. package/chunks/{chunk-JKGCBO3O.js → chunk-OAYOHSGP.js} +3 -3
  69. package/chunks/{chunk-G4M7FPNY.js → chunk-OBVBTAX5.js} +1 -1
  70. package/chunks/{chunk-JJ6B3ZD3.js → chunk-OIFSBXSP.js} +2 -2
  71. package/chunks/{chunk-NNEJEBCF.js → chunk-QOKV6AO4.js} +30 -21
  72. package/chunks/{chunk-DG573EOO.js → chunk-RZORUN6X.js} +1 -1
  73. package/chunks/{chunk-RSBQS6M4.js → chunk-SL2P3JUA.js} +1 -1
  74. package/chunks/{chunk-K4I4STSL.js → chunk-SOT7OMGL.js} +2 -2
  75. package/chunks/{chunk-MDBNFHIO.js → chunk-SRNPMG7J.js} +3 -3
  76. package/chunks/{chunk-SJVPSHXU.js → chunk-UNXGEDX2.js} +4 -4
  77. package/chunks/{chunk-WZ724G6K.js → chunk-UTL7KABL.js} +5 -5
  78. package/chunks/{chunk-UY2TCIZS.js → chunk-V5VTULL5.js} +2 -2
  79. package/chunks/{chunk-Z7XNVNPM.js → chunk-V6NH3CUC.js} +1 -1
  80. package/chunks/{chunk-J3ERRYYI.js → chunk-WXUDZHOJ.js} +2 -2
  81. package/chunks/{chunk-2CAII5HD.js → chunk-XH7H6YG4.js} +1 -1
  82. package/chunks/{chunk-XKZXGIRM.js → chunk-YSU33ACT.js} +2 -2
  83. package/chunks/{chunk-6QVQZAW6.js → chunk-YTWX5TT2.js} +1 -1
  84. package/chunks/{chunk-5B2WNM6V.js → chunk-ZI4MGBB5.js} +1 -1
  85. package/chunks/{chunk-2YH27UNF.js → chunk-ZO5EA3XJ.js} +1 -1
  86. package/chunks/{computer-use-ON3JQUHW.js → computer-use-5S3NVXRA.js} +11 -11
  87. package/chunks/{contextCommand-OGCG7W6N.js → contextCommand-DPBALZFK.js} +13 -13
  88. package/chunks/{cron-create-6YTCOX6P.js → cron-create-7JYUDTUY.js} +20 -5
  89. package/chunks/{cron-delete-E3NIFSUK.js → cron-delete-YPULQQAK.js} +2 -2
  90. package/chunks/{cron-list-Q64MNQNE.js → cron-list-HJIW5MHP.js} +2 -2
  91. package/chunks/{daemon-EEB2RYOL.js → daemon-7XYW4BC3.js} +102 -0
  92. package/chunks/{daemon-status-provider-P72STMLB.js → daemon-status-provider-2EWTHT7Y.js} +20 -19
  93. package/chunks/{dist-AP5V4WYU.js → dist-AAO65DPC.js} +2 -2
  94. package/chunks/{dist-X4ZDE726.js → dist-ABQ7VWRR.js} +3 -3
  95. package/chunks/{dist-SNXOUPYS.js → dist-AW5ZYMUI.js} +2 -2
  96. package/chunks/{dist-Z57Q4YF5.js → dist-BV56HW3W.js} +276 -95
  97. package/chunks/{dist-IZP2VV4C.js → dist-JPSVN367.js} +2 -2
  98. package/chunks/{earlyInputCapture-DAFHSGVW.js → earlyInputCapture-GGPV4IFT.js} +11 -11
  99. package/chunks/{edit-3QFNCSZH.js → edit-HJ7ISN4C.js} +12 -12
  100. package/chunks/{en-M4EBUBNU.js → en-XR3S5VWY.js} +1 -0
  101. package/chunks/{enter-worktree-62EQQMLD.js → enter-worktree-2BQT675D.js} +11 -11
  102. package/chunks/{enterPlanMode-VUQSE4EG.js → enterPlanMode-SJXHJ3WD.js} +11 -11
  103. package/chunks/{errors-PW75PZXE.js → errors-EVGER4AZ.js} +13 -13
  104. package/chunks/{exit-worktree-VVNH7OVY.js → exit-worktree-RPDDOSPM.js} +11 -11
  105. package/chunks/{exitPlanMode-RUYRCYZW.js → exitPlanMode-BQEROAJ7.js} +11 -11
  106. package/chunks/{fast-path-TFRJRTTR.js → fast-path-FX2ICJ2O.js} +3 -3
  107. package/chunks/{fast-path-settings-UQLRFDQP.js → fast-path-settings-RCRXH2JG.js} +2 -2
  108. package/chunks/{gemini-XW7ZDUVR.js → gemini-EHUXCOUI.js} +69 -64
  109. package/chunks/{geminiContentGenerator-MZDVHVZH.js → geminiContentGenerator-YDUUKAM2.js} +1 -1
  110. package/chunks/{glob-WAY2PUWA.js → glob-3VIGV2DL.js} +11 -11
  111. package/chunks/{grep-W6CBKSYC.js → grep-4D3S4NUC.js} +11 -11
  112. package/chunks/{initializer-HK2XE6P2.js → initializer-QZTZSSLW.js} +16 -16
  113. package/chunks/{list-RVLIIKKL.js → list-WQ24EAMK.js} +18 -18
  114. package/chunks/{loadedSettingsAdapter-C63OUYZC.js → loadedSettingsAdapter-XV74KOSR.js} +16 -16
  115. package/chunks/{loop-wakeup-G2EHBRGR.js → loop-wakeup-34YK7T7O.js} +3 -3
  116. package/chunks/{ls-IDHUVSAG.js → ls-MPD5OJUX.js} +1 -1
  117. package/chunks/{lsp-FSRYXGFT.js → lsp-72PWTDW7.js} +1 -1
  118. package/chunks/{workspace-skills-status-ONEPXJV6.js → mcp-CO3MKM7N.js} +20 -16
  119. package/chunks/{monitor-FOG36ABM.js → monitor-GB56T65A.js} +11 -11
  120. package/chunks/{nonInteractiveCli-6BYQSJTB.js → nonInteractiveCli-HNZRIM5I.js} +46 -44
  121. package/chunks/{notebook-edit-GC6NXRCX.js → notebook-edit-VMXAAE3R.js} +12 -12
  122. package/chunks/{openaiContentGenerator-EXR3ZL3Z.js → openaiContentGenerator-GM77FLII.js} +6 -6
  123. package/chunks/{pidfile-FNZM2DDH.js → pidfile-HFXSHR64.js} +11 -11
  124. package/chunks/{qwenContentGenerator-A7B6J4U7.js → qwenContentGenerator-QSCXQIKJ.js} +13 -13
  125. package/chunks/{read-file-6JL4ULMY.js → read-file-SVH6CGQY.js} +3 -3
  126. package/chunks/{read-mcp-resource-PIJF24RO.js → read-mcp-resource-OWOBJY72.js} +1 -1
  127. package/chunks/record-artifact-URK3YUDJ.js +343 -0
  128. package/chunks/{ripGrep-DIUGLJE5.js → ripGrep-JD5O2FLX.js} +11 -11
  129. package/chunks/{run-qwen-serve-CME3AKM4.js → run-qwen-serve-FADLRJUN.js} +67 -28
  130. package/chunks/{scheduler-L7F6GDDT.js → scheduler-Q65SB7DJ.js} +11 -11
  131. package/chunks/{send-message-33PYFMCT.js → send-message-L7OLQEKH.js} +2 -2
  132. package/chunks/{serve-SRCBOJGP.js → serve-6ZXAMQ4M.js} +18 -18
  133. package/chunks/{server-QSQ45QFR.js → server-WKDQA6XR.js} +1184 -490
  134. package/chunks/{session-5DG6NXHZ.js → session-STWOX7RA.js} +48 -46
  135. package/chunks/{settings-3EEQI4MN.js → settings-LC4CCWQQ.js} +15 -15
  136. package/chunks/{shell-B7FNYF5S.js → shell-FEG3RLPW.js} +11 -11
  137. package/chunks/{skill-AAOGHD5O.js → skill-XTXAMDAP.js} +4 -4
  138. package/chunks/{spawnChannel-3CBN3ZLK.js → spawnChannel-B6JJPBPV.js} +15 -15
  139. package/chunks/{src-T5A7P7FS.js → src-HITDGVRM.js} +47 -21
  140. package/chunks/{startInteractiveUI-2FGEQ6AS.js → startInteractiveUI-IT423PW4.js} +354 -152
  141. package/chunks/{syntheticOutput-YOSWIHDJ.js → syntheticOutput-J3MLCQAR.js} +2 -2
  142. package/chunks/{task-create-NHS2NGB3.js → task-create-ELEBZ7H2.js} +3 -3
  143. package/chunks/{task-list-5UIB564R.js → task-list-IEUZLF3Y.js} +1 -1
  144. package/chunks/{task-stop-HGXZ2VZ3.js → task-stop-QEZW3UDY.js} +1 -1
  145. package/chunks/{task-update-IYYWUILG.js → task-update-DW36J5P5.js} +3 -3
  146. package/chunks/{team-create-KDF6W6PV.js → team-create-DAG6SNHZ.js} +11 -11
  147. package/chunks/{team-delete-FEKJCU4P.js → team-delete-SVITIMBO.js} +1 -1
  148. package/chunks/{team-plan-approval-PSFKQX7M.js → team-plan-approval-DRDY5OPC.js} +11 -11
  149. package/chunks/{theme-manager-5XOA2AO7.js → theme-manager-N67EZC6B.js} +11 -11
  150. package/chunks/{todoWrite-TKMVZ2HT.js → todoWrite-SFFQHZYY.js} +2 -2
  151. package/chunks/{tool-search-LFRILZXC.js → tool-search-CMDJ5HGM.js} +4 -4
  152. package/chunks/{trustedFolders-7HQY6T6X.js → trustedFolders-JD4QX6UJ.js} +12 -12
  153. package/chunks/{validateNonInterActiveAuth-UC27B7BA.js → validateNonInterActiveAuth-ADDCGZ6A.js} +43 -41
  154. package/chunks/version-VAONYVE5.js +10 -0
  155. package/chunks/{web-fetch-J4PIW36Q.js → web-fetch-SXAXJHIO.js} +2 -2
  156. package/chunks/{workflow-KUTESS6L.js → workflow-DG2BR42M.js} +20 -13
  157. package/chunks/{workspace-providers-status-LJT5AQDS.js → workspace-providers-status-XGW5OZTD.js} +18 -18
  158. package/chunks/{workspace-service-YOBYVDXH.js → workspace-service-GX3GGZLU.js} +23 -23
  159. package/chunks/workspace-skills-status-LFK5WV2V.js +68 -0
  160. package/chunks/{write-file-FJYBZUHP.js → write-file-UR7FXWOU.js} +12 -12
  161. package/chunks/yargs-B64EYTCF.js +10 -0
  162. package/chunks/{zh-SLZNSSZB.js → zh-FSVJTXA4.js} +1 -0
  163. package/chunks/{zh-TW-P53C2SL5.js → zh-TW-66MG4LWL.js} +1 -0
  164. package/cli-entry.js +81 -8
  165. package/cli.js +348 -55
  166. package/locales/en.js +1 -0
  167. package/locales/zh-TW.js +1 -0
  168. package/locales/zh.js +1 -0
  169. package/node_modules/@qwen-code/audio-capture/package.json +1 -1
  170. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-arm64/@qwen-code+audio-capture.node +0 -0
  171. package/node_modules/@qwen-code/audio-capture/prebuilds/darwin-x64/@qwen-code+audio-capture.node +0 -0
  172. package/node_modules/@qwen-code/audio-capture/prebuilds/win32-x64/@qwen-code+audio-capture.node +0 -0
  173. package/package.json +3 -3
  174. package/web-shell/assets/{arc-D_rAuMDd.js → arc-CUpe0ibu.js} +1 -1
  175. package/web-shell/assets/{architectureDiagram-3BPJPVTR-DUCzbHVo.js → architectureDiagram-3BPJPVTR-JvyrY_mK.js} +1 -1
  176. package/web-shell/assets/{blockDiagram-GPEHLZMM-BEEBt1LL.js → blockDiagram-GPEHLZMM-CK3Y_vom.js} +1 -1
  177. package/web-shell/assets/{c4Diagram-AAUBKEIU-5ZJ_DeFL.js → c4Diagram-AAUBKEIU-DprSnyrf.js} +1 -1
  178. package/web-shell/assets/channel-BAxQ2-aZ.js +1 -0
  179. package/web-shell/assets/{chunk-2J33WTMH-Cfw7EiLn.js → chunk-2J33WTMH-DJtRJPmu.js} +1 -1
  180. package/web-shell/assets/{chunk-4BX2VUAB-FGuZNCZY.js → chunk-4BX2VUAB-ON6Q2-BG.js} +1 -1
  181. package/web-shell/assets/{chunk-55IACEB6-CaBwYPBF.js → chunk-55IACEB6-c60ou5HZ.js} +1 -1
  182. package/web-shell/assets/{chunk-727SXJPM-BlR04OFz.js → chunk-727SXJPM-BamtPKxx.js} +1 -1
  183. package/web-shell/assets/{chunk-AQP2D5EJ-D3_mYJH5.js → chunk-AQP2D5EJ-CsVgpu-T.js} +1 -1
  184. package/web-shell/assets/{chunk-FMBD7UC4-7D4q4SbB.js → chunk-FMBD7UC4-vZrpjAx4.js} +1 -1
  185. package/web-shell/assets/{chunk-ND2GUHAM-BjX_Iwmr.js → chunk-ND2GUHAM-qxyNOd5t.js} +1 -1
  186. package/web-shell/assets/{chunk-QZHKN3VN-C3Hz_ZQh.js → chunk-QZHKN3VN-BvTJSM_S.js} +1 -1
  187. package/web-shell/assets/classDiagram-4FO5ZUOK-Cvd_xhZI.js +1 -0
  188. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-Cvd_xhZI.js +1 -0
  189. package/web-shell/assets/{cose-bilkent-S5V4N54A-Ax4UycaT.js → cose-bilkent-S5V4N54A-1tXB4pju.js} +1 -1
  190. package/web-shell/assets/{dagre-BM42HDAG-C6hmPtGt.js → dagre-BM42HDAG-DglBzme8.js} +1 -1
  191. package/web-shell/assets/{diagram-2AECGRRQ-tXZnxjmw.js → diagram-2AECGRRQ-DEJpqsWz.js} +1 -1
  192. package/web-shell/assets/{diagram-5GNKFQAL-99dwIzQG.js → diagram-5GNKFQAL-CsQ1NrMG.js} +1 -1
  193. package/web-shell/assets/{diagram-KO2AKTUF-Bqhn0-2s.js → diagram-KO2AKTUF-Z-3codAi.js} +1 -1
  194. package/web-shell/assets/{diagram-LMA3HP47-DzThVSvo.js → diagram-LMA3HP47-mBuPTA2i.js} +1 -1
  195. package/web-shell/assets/{diagram-OG6HWLK6-DPE8vjln.js → diagram-OG6HWLK6-tcA3K3s9.js} +1 -1
  196. package/web-shell/assets/{erDiagram-TEJ5UH35-KzUKgQCV.js → erDiagram-TEJ5UH35-D9bXFRyZ.js} +1 -1
  197. package/web-shell/assets/{flowDiagram-I6XJVG4X-DBN-DXw5.js → flowDiagram-I6XJVG4X-Ck0Py04s.js} +1 -1
  198. package/web-shell/assets/{ganttDiagram-6RSMTGT7-DuBsP9u8.js → ganttDiagram-6RSMTGT7-rOevCekE.js} +1 -1
  199. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-BjWHMyKR.js → gitGraphDiagram-PVQCEYII-CoPQaLj0.js} +1 -1
  200. package/web-shell/assets/index-Cr7MYW6T.css +5 -0
  201. package/web-shell/assets/index-DCHPAUp3.js +730 -0
  202. package/web-shell/assets/{infoDiagram-5YYISTIA-BVux0vP6.js → infoDiagram-5YYISTIA-a77CUKoI.js} +1 -1
  203. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-2qzw7f--.js → ishikawaDiagram-YF4QCWOH-DlLgUAO-.js} +1 -1
  204. package/web-shell/assets/{journeyDiagram-JHISSGLW-Dnl65sxL.js → journeyDiagram-JHISSGLW-BXR5kVAZ.js} +1 -1
  205. package/web-shell/assets/{kanban-definition-UN3LZRKU-BElSQYtY.js → kanban-definition-UN3LZRKU-h5CoHZg7.js} +1 -1
  206. package/web-shell/assets/{linear-BjoycSSY.js → linear-BkaREbyD.js} +1 -1
  207. package/web-shell/assets/{mermaid.core-xe6bvMRz.js → mermaid.core-Bkagz0ng.js} +5 -5
  208. package/web-shell/assets/{mindmap-definition-RKZ34NQL-D8DQgI4U.js → mindmap-definition-RKZ34NQL-D7EMKR_5.js} +1 -1
  209. package/web-shell/assets/{pieDiagram-4H26LBE5-Dwh7Gp7c.js → pieDiagram-4H26LBE5-DAmPOjsL.js} +1 -1
  210. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BXKNBln2.js → quadrantDiagram-W4KKPZXB-e4WFQkQu.js} +1 -1
  211. package/web-shell/assets/{requirementDiagram-4Y6WPE33-BzaC3cIA.js → requirementDiagram-4Y6WPE33-v1zo7OiV.js} +1 -1
  212. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-DP2t7eZk.js → sankeyDiagram-5OEKKPKP-Bstm4aW_.js} +1 -1
  213. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-XlFiWEYv.js → sequenceDiagram-3UESZ5HK-DzcZy6xN.js} +1 -1
  214. package/web-shell/assets/{stateDiagram-AJRCARHV-CupgUMJO.js → stateDiagram-AJRCARHV-BEJH6YbH.js} +1 -1
  215. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BopifCBI.js +1 -0
  216. package/web-shell/assets/{timeline-definition-PNZ67QCA-DstuGywa.js → timeline-definition-PNZ67QCA-TI1wH-Pm.js} +1 -1
  217. package/web-shell/assets/{vennDiagram-CIIHVFJN-CnbNp6zu.js → vennDiagram-CIIHVFJN-YaH8VDMS.js} +1 -1
  218. package/web-shell/assets/{wardley-L42UT6IY-DnvoHq6R.js → wardley-L42UT6IY-B80co7OP.js} +1 -1
  219. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-Cz0xHEWB.js → wardleyDiagram-YWT4CUSO-4fHNDEMl.js} +1 -1
  220. package/web-shell/assets/{xychartDiagram-2RQKCTM6-p36gfo88.js → xychartDiagram-2RQKCTM6-DT3q4Z3J.js} +1 -1
  221. package/web-shell/index.html +2 -2
  222. package/bundled/loop/SKILL.test.ts +0 -119
  223. package/bundled/loop/autonomous-loop.test.ts +0 -59
  224. package/bundled/loop/loop-task-file.test.ts +0 -1064
  225. package/bundled/loop/loop-tick-resolver.test.ts +0 -906
  226. package/chunks/chunk-EJ7BN3EN.js +0 -11396
  227. package/web-shell/assets/channel-B5ynH0q8.js +0 -1
  228. package/web-shell/assets/classDiagram-4FO5ZUOK-CK3ibywp.js +0 -1
  229. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CK3ibywp.js +0 -1
  230. package/web-shell/assets/index-9qfvU0_r.css +0 -5
  231. package/web-shell/assets/index-CWzDaQT5.js +0 -717
  232. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-By3E4QwN.js +0 -1
  233. package/chunks/{chunk-UFC57OYT.js → chunk-VRDMOSQS.js} +54 -54
@@ -7,8 +7,8 @@ import {
7
7
  sanitizeLogText,
8
8
  sanitizePromptText,
9
9
  sanitizeSenderName
10
- } from "./chunk-7DMQRPC7.js";
11
- import "./chunk-UFC57OYT.js";
10
+ } from "./chunk-6BEOH4KK.js";
11
+ import "./chunk-VRDMOSQS.js";
12
12
  import "./chunk-K5PGHDBN.js";
13
13
  import {
14
14
  wrapper_default
@@ -1114,7 +1114,7 @@ init_esbuild_shims();
1114
1114
 
1115
1115
  // packages/channels/qqbot/dist/QQChannel.js
1116
1116
  init_esbuild_shims();
1117
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "node:fs";
1117
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, renameSync, unlinkSync } from "node:fs";
1118
1118
  import { join as join2 } from "node:path";
1119
1119
 
1120
1120
  // packages/channels/qqbot/dist/types.js
@@ -1351,8 +1351,11 @@ async function fetchAccessToken(appId, appSecret) {
1351
1351
  signal: AbortSignal.timeout(FETCH_TIMEOUT)
1352
1352
  });
1353
1353
  if (!resp.ok) {
1354
- const body = await resp.text().catch(() => "");
1355
- throw new Error(`QQ Bot token request failed (HTTP ${resp.status}): ${body}`);
1354
+ await resp.body?.cancel().catch(() => {
1355
+ });
1356
+ process.stderr.write(`[QQ] Token request failed (HTTP ${resp.status})
1357
+ `);
1358
+ throw new Error(`QQ Bot token request failed (HTTP ${resp.status})`);
1356
1359
  }
1357
1360
  const data = await resp.json();
1358
1361
  if (!data.access_token) {
@@ -1364,6 +1367,27 @@ async function fetchAccessToken(appId, appSecret) {
1364
1367
  };
1365
1368
  }
1366
1369
  __name(fetchAccessToken, "fetchAccessToken");
1370
+ function validateGatewayUrl(url) {
1371
+ try {
1372
+ const parsed = new URL(url);
1373
+ if (parsed.protocol !== "wss:") {
1374
+ throw new Error(`QQ Bot gateway URL must use wss:// protocol, got: ${parsed.protocol}`);
1375
+ }
1376
+ if (!parsed.hostname.toLowerCase().endsWith(".qq.com")) {
1377
+ throw new Error(`QQ Bot gateway URL has unexpected hostname: ${parsed.hostname} (expected *.qq.com)`);
1378
+ }
1379
+ const clean = new URL(url);
1380
+ clean.username = "";
1381
+ clean.password = "";
1382
+ return clean.href;
1383
+ } catch (e) {
1384
+ if (e instanceof TypeError) {
1385
+ throw new Error("QQ Bot gateway URL is not a valid URL");
1386
+ }
1387
+ throw e;
1388
+ }
1389
+ }
1390
+ __name(validateGatewayUrl, "validateGatewayUrl");
1367
1391
  async function fetchGatewayUrl(accessToken, sandbox) {
1368
1392
  const gw = sandbox ? `${SANDBOX_HOST}/gateway` : `${API_HOST}/gateway`;
1369
1393
  const resp = await fetch(gw, {
@@ -1371,13 +1395,15 @@ async function fetchGatewayUrl(accessToken, sandbox) {
1371
1395
  signal: AbortSignal.timeout(FETCH_TIMEOUT)
1372
1396
  });
1373
1397
  if (!resp.ok) {
1398
+ await resp.body?.cancel().catch(() => {
1399
+ });
1374
1400
  throw new Error(`QQ Bot gateway request failed (HTTP ${resp.status})`);
1375
1401
  }
1376
1402
  const data = await resp.json();
1377
1403
  if (!data["url"]) {
1378
1404
  throw new Error("QQ Bot gateway response missing WebSocket URL");
1379
1405
  }
1380
- return data["url"];
1406
+ return validateGatewayUrl(data["url"]);
1381
1407
  }
1382
1408
  __name(fetchGatewayUrl, "fetchGatewayUrl");
1383
1409
  function getApiBase(sandbox) {
@@ -1402,32 +1428,7 @@ function isValidChatId(id) {
1402
1428
  return /^[A-Za-z0-9_-]+$/.test(id) && id.length <= 128;
1403
1429
  }
1404
1430
  __name(isValidChatId, "isValidChatId");
1405
- function hasLinkSyntax(text) {
1406
- const open = text.indexOf("[");
1407
- if (open === -1)
1408
- return false;
1409
- const mid = text.indexOf("](", open + 1);
1410
- if (mid === -1)
1411
- return false;
1412
- return text.indexOf(")", mid + 2) !== -1;
1413
- }
1414
- __name(hasLinkSyntax, "hasLinkSyntax");
1415
- function hasMarkdownSyntax(text) {
1416
- return /^#{1,6}\s/m.test(text) || text.includes("```") || /\*\*|__|~~/.test(text) || /`[^`]+`/.test(text) || hasLinkSyntax(text) || /^[-*+]\s/m.test(text) || /^\d+\.\s/m.test(text);
1417
- }
1418
- __name(hasMarkdownSyntax, "hasMarkdownSyntax");
1419
- function splitText(text) {
1420
- const MAX = 2e3;
1421
- if (text.length <= MAX)
1422
- return [text];
1423
- const chunks = [];
1424
- for (let i = 0; i < text.length; i += MAX) {
1425
- chunks.push(text.slice(i, i + MAX));
1426
- }
1427
- return chunks;
1428
- }
1429
- __name(splitText, "splitText");
1430
- var QQChannel = class extends ChannelBase {
1431
+ var QQChannel = class _QQChannel extends ChannelBase {
1431
1432
  static {
1432
1433
  __name(this, "QQChannel");
1433
1434
  }
@@ -1459,6 +1460,8 @@ var QQChannel = class extends ChannelBase {
1459
1460
  lastHeartbeatAck = 0;
1460
1461
  /** Debounce timer for saveQQState to avoid blocking event loop. */
1461
1462
  saveTimer = null;
1463
+ /** beforeExit hook to flush state when the event loop drains naturally. Does NOT fire for SIGKILL, OOM kills, or uncaughtException. */
1464
+ beforeExitHook = null;
1462
1465
  /** Timer for reconnectWithRetry fallback (unref'd so it doesn't block exit). */
1463
1466
  reconnectTimer = null;
1464
1467
  /** Guard against parallel reconnectWithRetry chains from stale close events. */
@@ -1469,6 +1472,10 @@ var QQChannel = class extends ChannelBase {
1469
1472
  replyMsgId = /* @__PURE__ */ new Map();
1470
1473
  /** msg_seq counter per user messageId, for multi-block streaming. */
1471
1474
  msgSeqMap = /* @__PURE__ */ new Map();
1475
+ /** Periodic cleanup timer for expired replyMsgId entries. */
1476
+ replyMsgIdCleanupTimer = null;
1477
+ /** 5-minute TTL for replyMsgId entries and seenMessages dedup. */
1478
+ static REPLY_MSG_ID_TTL_MS = 3e5;
1472
1479
  /** Path to persisted QQ routing state: chatTypeMap, replyMsgId, msgSeqMap. */
1473
1480
  qqStatePath;
1474
1481
  /**
@@ -1504,71 +1511,145 @@ var QQChannel = class extends ChannelBase {
1504
1511
  "## QQ Bot Channel",
1505
1512
  "",
1506
1513
  "\u4F60\u662F\u901A\u8FC7 QQ Bot \u4E0E\u7528\u6237\u5BF9\u8BDD\u7684 AI \u52A9\u624B\u3002",
1507
- "\u56DE\u590D\u63A7\u5236\u5728 2000 \u5B57\u7B26\u4EE5\u5185\uFF08\u8D85\u957F\u4F1A\u81EA\u52A8\u5206\u5757\uFF09\uFF0C\u652F\u6301 Markdown \u683C\u5F0F\u3002"
1514
+ "\u56DE\u590D\u63A7\u5236\u5728 2000 \u5B57\u7B26\u4EE5\u5185\uFF0C\u652F\u6301 Markdown \u683C\u5F0F\u3002"
1508
1515
  ].join("\n");
1509
1516
  }
1510
1517
  for (let attempt = 0; attempt < 3; attempt++) {
1511
1518
  try {
1512
1519
  await this.fetchToken();
1513
1520
  await this.connectGateway();
1521
+ if (this.beforeExitHook) {
1522
+ process.off("beforeExit", this.beforeExitHook);
1523
+ }
1524
+ this.beforeExitHook = () => this.flushQQState();
1525
+ process.on("beforeExit", this.beforeExitHook);
1526
+ this.startReplyMsgIdCleanup();
1514
1527
  return;
1515
1528
  } catch (e) {
1516
1529
  if (attempt < 2) {
1517
1530
  const msg = e instanceof Error ? e.message : String(e);
1518
- process.stderr.write(`[QQ:${this.name}] Connect attempt ${attempt + 1} failed: ${msg}, retrying...
1531
+ process.stderr.write(`[QQ:${this.name}] Connect attempt ${attempt + 1} failed: ${sanitizeLogText(msg, 200)}, retrying...
1519
1532
  `);
1520
1533
  await this.sleep(2e3);
1521
1534
  } else {
1522
- throw e;
1535
+ throw new Error(sanitizeLogText(e instanceof Error ? e.message : String(e), 200), { cause: e });
1523
1536
  }
1524
1537
  }
1525
1538
  }
1526
1539
  }
1527
1540
  async sendMessage(chatId, text) {
1541
+ if (text.trim() === "<noreply>") {
1542
+ process.stderr.write(`[QQ:${this.name}] <noreply> skipped for ${sanitizeLogText(chatId, 64)}
1543
+ `);
1544
+ return;
1545
+ }
1528
1546
  const route = await this.resolveRoute(chatId);
1529
1547
  if (!route)
1530
1548
  return;
1531
- const msgId = this.replyMsgId.get(chatId);
1532
- const useMarkdown = hasMarkdownSyntax(text);
1533
- for (const chunk of splitText(text)) {
1534
- try {
1535
- const body = useMarkdown ? { msg_type: 2, markdown: { content: chunk } } : { content: chunk, msg_type: 0 };
1536
- const nextSeq = msgId ? (this.msgSeqMap.get(msgId) ?? 0) + 1 : 0;
1537
- if (msgId) {
1538
- body["msg_id"] = msgId;
1539
- body["msg_seq"] = nextSeq;
1540
- }
1541
- let resp = await sendQQMessage(route.base, route.path, this.accessToken, body);
1542
- if (!resp.ok && useMarkdown) {
1543
- const errBody = await resp.text().catch(() => "");
1544
- process.stderr.write(`[QQ:${this.name}] Markdown rejected (HTTP ${resp.status}: ${errBody.slice(0, 100)}), retrying as plain text
1549
+ const entry = this.replyMsgId.get(chatId);
1550
+ const msgId = entry && Date.now() - entry.timestamp < _QQChannel.REPLY_MSG_ID_TTL_MS ? entry.msgId : void 0;
1551
+ if (entry && !msgId) {
1552
+ process.stderr.write(`[QQ:${this.name}] replyMsgId entry expired for ${sanitizeLogText(chatId, 64)}, reply context expired, sending without msg_id
1553
+ `);
1554
+ this.msgSeqMap.delete(entry.msgId);
1555
+ this.replyMsgId.delete(chatId);
1556
+ this.saveQQState();
1557
+ }
1558
+ let nextSeq = 0;
1559
+ let rollbackApplied = false;
1560
+ try {
1561
+ const body = {
1562
+ msg_type: 2,
1563
+ markdown: { content: text }
1564
+ };
1565
+ nextSeq = msgId ? (this.msgSeqMap.get(msgId) ?? 0) + 1 : 0;
1566
+ if (msgId) {
1567
+ this.msgSeqMap.set(msgId, nextSeq);
1568
+ body["msg_id"] = msgId;
1569
+ body["msg_seq"] = nextSeq;
1570
+ }
1571
+ const resp = await sendQQMessage(route.base, route.path, this.accessToken, body);
1572
+ if (!resp.ok) {
1573
+ const errBody = await resp.text().catch(() => "");
1574
+ process.stderr.write(`[QQ:${this.name}] Send failed (HTTP ${resp.status}: ${sanitizeLogText(errBody, 200)})
1575
+ `);
1576
+ if (resp.status === 429) {
1577
+ process.stderr.write(`[QQ:${this.name}] MESSAGE DROPPED: rate-limited (429) on markdown attempt for ${sanitizeLogText(chatId, 64)}
1545
1578
  `);
1546
- const plainBody = {
1547
- content: chunk,
1548
- msg_type: 0
1549
- };
1550
1579
  if (msgId) {
1551
- plainBody["msg_id"] = msgId;
1552
- plainBody["msg_seq"] = nextSeq;
1580
+ this.msgSeqMap.set(msgId, nextSeq - 1);
1581
+ this.saveQQState();
1553
1582
  }
1554
- resp = await sendQQMessage(route.base, route.path, this.accessToken, plainBody);
1583
+ return;
1555
1584
  }
1556
- if (!resp.ok) {
1557
- const errBody = await resp.text().catch(() => "");
1558
- process.stderr.write(`[QQ:${this.name}] Send HTTP ${resp.status} (msg_seq=${body["msg_seq"] ?? "-"}): ${errBody.slice(0, 200)}
1585
+ if (msgId) {
1586
+ this.msgSeqMap.set(msgId, nextSeq - 1);
1587
+ rollbackApplied = true;
1588
+ const activeBody = {
1589
+ content: text,
1590
+ msg_type: 0,
1591
+ msg_id: msgId,
1592
+ msg_seq: nextSeq
1593
+ };
1594
+ const activeResp = await sendQQMessage(route.base, route.path, this.accessToken, activeBody);
1595
+ if (activeResp.ok) {
1596
+ process.stderr.write(`[QQ:${this.name}] Active retry succeeded for ${sanitizeLogText(chatId, 64)}
1559
1597
  `);
1560
- break;
1598
+ const current = this.replyMsgId.get(chatId);
1599
+ if (current?.msgId === msgId) {
1600
+ this.msgSeqMap.set(msgId, nextSeq);
1601
+ }
1602
+ this.saveQQState();
1603
+ await activeResp.text().catch(() => "");
1604
+ return;
1605
+ }
1606
+ process.stderr.write(`[QQ:${this.name}] Active retry also failed (HTTP ${activeResp.status}: ${sanitizeLogText(await activeResp.text().catch(() => ""), 200)})
1607
+ `);
1608
+ if (activeResp.status === 429) {
1609
+ process.stderr.write(`[QQ:${this.name}] MESSAGE DROPPED: active retry rate-limited (HTTP 429) for ${sanitizeLogText(chatId, 64)}
1610
+ `);
1611
+ this.saveQQState();
1612
+ return;
1613
+ }
1614
+ process.stderr.write(`[QQ:${this.name}] MESSAGE DROPPED: both passive and active send failed for ${sanitizeLogText(chatId, 64)}
1615
+ `);
1616
+ this.saveQQState();
1617
+ return;
1561
1618
  }
1562
- if (msgId)
1563
- this.msgSeqMap.set(msgId, nextSeq);
1564
- } catch (e) {
1565
- process.stderr.write(`[QQ:${this.name}] Send error: ${e}
1619
+ const plainBody = {
1620
+ content: text,
1621
+ msg_type: 0
1622
+ };
1623
+ const fallbackRes = await sendQQMessage(route.base, route.path, this.accessToken, plainBody);
1624
+ if (!fallbackRes.ok) {
1625
+ const fbErrBody = await fallbackRes.text().catch(() => "");
1626
+ if (fallbackRes.status === 429) {
1627
+ process.stderr.write(`[QQ:${this.name}] MESSAGE DROPPED: rate-limited (429) on plain-text fallback for ${sanitizeLogText(chatId, 64)}
1566
1628
  `);
1567
- break;
1629
+ return;
1630
+ }
1631
+ process.stderr.write(`[QQ:${this.name}] MESSAGE DROPPED: plain-text fallback failed (HTTP ${fallbackRes.status}: ${sanitizeLogText(fbErrBody, 200)}) for ${sanitizeLogText(chatId, 64)}
1632
+ `);
1633
+ return;
1634
+ }
1635
+ process.stderr.write(`[QQ:${this.name}] Plain-text fallback succeeded for ${sanitizeLogText(chatId, 64)}
1636
+ `);
1637
+ await fallbackRes.text().catch(() => "");
1638
+ return;
1568
1639
  }
1640
+ await resp.text().catch(() => "");
1641
+ if (msgId)
1642
+ this.saveQQState();
1643
+ } catch (e) {
1644
+ if (msgId && !rollbackApplied) {
1645
+ this.msgSeqMap.set(msgId, nextSeq - 1);
1646
+ }
1647
+ if (msgId)
1648
+ this.saveQQState();
1649
+ process.stderr.write(`[QQ:${this.name}] Send error: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
1650
+ `);
1651
+ throw e;
1569
1652
  }
1570
- if (msgId)
1571
- this.saveQQState();
1572
1653
  }
1573
1654
  /**
1574
1655
  * Resolve API routing: handles disposed check, token refresh, chatId validation,
@@ -1594,6 +1675,7 @@ var QQChannel = class extends ChannelBase {
1594
1675
  this.disposed = true;
1595
1676
  this.stopHeartbeat();
1596
1677
  this.stopTokenRefresh();
1678
+ this.stopReplyMsgIdCleanup();
1597
1679
  if (this.seenCleanupTimer) {
1598
1680
  clearInterval(this.seenCleanupTimer);
1599
1681
  this.seenCleanupTimer = null;
@@ -1602,6 +1684,10 @@ var QQChannel = class extends ChannelBase {
1602
1684
  clearTimeout(this.reconnectTimer);
1603
1685
  this.reconnectTimer = null;
1604
1686
  }
1687
+ if (this.beforeExitHook) {
1688
+ process.off("beforeExit", this.beforeExitHook);
1689
+ this.beforeExitHook = null;
1690
+ }
1605
1691
  this.flushQQState();
1606
1692
  this.backupGlobalSessions();
1607
1693
  if (this.ws) {
@@ -1628,18 +1714,31 @@ var QQChannel = class extends ChannelBase {
1628
1714
  // ── State Persistence (cross-server context continuation) ──────
1629
1715
  /** Debounced state persistence to avoid blocking event loop. */
1630
1716
  saveQQState() {
1717
+ if (this.disposed)
1718
+ return;
1631
1719
  if (this.saveTimer)
1632
1720
  clearTimeout(this.saveTimer);
1721
+ const tmpPath = this.qqStatePath + ".tmp";
1633
1722
  this.saveTimer = setTimeout(() => {
1723
+ if (this.disposed)
1724
+ return;
1634
1725
  try {
1635
- writeFileSync2(this.qqStatePath, JSON.stringify({
1726
+ writeFileSync2(tmpPath, JSON.stringify({
1636
1727
  chatTypeMap: Array.from(this.chatTypeMap.entries()),
1637
1728
  replyMsgId: Array.from(this.replyMsgId.entries()),
1638
1729
  msgSeqMap: Array.from(this.msgSeqMap.entries())
1639
1730
  }), { mode: 384 });
1640
- } catch {
1731
+ renameSync(tmpPath, this.qqStatePath);
1732
+ } catch (e) {
1733
+ try {
1734
+ unlinkSync(tmpPath);
1735
+ } catch {
1736
+ }
1737
+ process.stderr.write(`[QQ:${this.name}] saveQQState write failed: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
1738
+ `);
1641
1739
  }
1642
1740
  }, 500);
1741
+ this.saveTimer.unref();
1643
1742
  }
1644
1743
  /** Flush pending state writes immediately (called on disconnect). */
1645
1744
  flushQQState() {
@@ -1647,35 +1746,78 @@ var QQChannel = class extends ChannelBase {
1647
1746
  clearTimeout(this.saveTimer);
1648
1747
  this.saveTimer = null;
1649
1748
  }
1749
+ const tmpPath = this.qqStatePath + ".tmp";
1650
1750
  try {
1651
- writeFileSync2(this.qqStatePath, JSON.stringify({
1751
+ writeFileSync2(tmpPath, JSON.stringify({
1652
1752
  chatTypeMap: Array.from(this.chatTypeMap.entries()),
1653
1753
  replyMsgId: Array.from(this.replyMsgId.entries()),
1654
1754
  msgSeqMap: Array.from(this.msgSeqMap.entries())
1655
- }));
1656
- } catch {
1755
+ }), { mode: 384 });
1756
+ renameSync(tmpPath, this.qqStatePath);
1757
+ } catch (e) {
1758
+ try {
1759
+ unlinkSync(tmpPath);
1760
+ } catch {
1761
+ }
1762
+ process.stderr.write(`[QQ:${this.name}] flushQQState write failed: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
1763
+ `);
1657
1764
  }
1658
1765
  }
1659
1766
  /**
1660
1767
  * Restore QQ routing state from disk.
1661
- * Trusts persisted JSON if the file is corrupt, new Map() may create
1662
- * entries with undefined values, causing get()===undefined to fall through
1663
- * to default routing (C2C). This is acceptable for a rare edge case.
1768
+ * Validates and filters every entry on restore corrupt or unexpected
1769
+ * entries (e.g. unknown chat types, oversized replyMsgIds, negative seqs)
1770
+ * are silently dropped so they don't propagate into runtime routing.
1664
1771
  */
1665
1772
  restoreQQState() {
1666
1773
  try {
1667
1774
  if (!existsSync2(this.qqStatePath))
1668
1775
  return false;
1669
1776
  const raw = JSON.parse(readFileSync2(this.qqStatePath, "utf-8"));
1670
- if (raw.chatTypeMap)
1671
- this.chatTypeMap = new Map(raw.chatTypeMap);
1672
- if (raw.replyMsgId)
1673
- this.replyMsgId = new Map(raw.replyMsgId);
1674
- if (raw.msgSeqMap)
1675
- this.msgSeqMap = new Map(raw.msgSeqMap);
1777
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
1778
+ process.stderr.write(`[QQ:${this.name}] Invalid QQ state file (not an object), ignoring
1779
+ `);
1780
+ return false;
1781
+ }
1782
+ if (raw.chatTypeMap && Array.isArray(raw.chatTypeMap)) {
1783
+ const rawCT = raw.chatTypeMap;
1784
+ this.chatTypeMap = new Map(rawCT.filter(([k, v]) => typeof k === "string" && k.length <= 256 && (v === "c2c" || v === "group")));
1785
+ const dropped = rawCT.length - this.chatTypeMap.size;
1786
+ if (dropped > 0)
1787
+ process.stderr.write(`[QQ:${this.name}] Dropped ${dropped} invalid chatTypeMap entries during restore
1788
+ `);
1789
+ }
1790
+ if (raw.replyMsgId && Array.isArray(raw.replyMsgId)) {
1791
+ const now = Date.now();
1792
+ const rawRM = raw.replyMsgId;
1793
+ this.replyMsgId = new Map(rawRM.map(([k, v]) => (
1794
+ // Old format: string -> { msgId: v, timestamp: now }
1795
+ // New format: { msgId, timestamp } -> pass through
1796
+ typeof v === "string" ? [k, { msgId: v, timestamp: now }] : [k, v]
1797
+ )).filter(([k, v]) => {
1798
+ if (typeof k !== "string" || k.length > 256)
1799
+ return false;
1800
+ if (typeof v !== "object" || v === null)
1801
+ return false;
1802
+ const entry = v;
1803
+ return typeof entry.msgId === "string" && entry.msgId.length <= 128 && typeof entry.timestamp === "number" && Number.isFinite(entry.timestamp) && entry.timestamp <= now + _QQChannel.REPLY_MSG_ID_TTL_MS;
1804
+ }));
1805
+ const dropped = rawRM.length - this.replyMsgId.size;
1806
+ if (dropped > 0)
1807
+ process.stderr.write(`[QQ:${this.name}] Dropped ${dropped} invalid replyMsgId entries during restore
1808
+ `);
1809
+ }
1810
+ if (raw.msgSeqMap && Array.isArray(raw.msgSeqMap)) {
1811
+ const rawMS = raw.msgSeqMap;
1812
+ this.msgSeqMap = new Map(rawMS.filter(([k, v]) => typeof k === "string" && k.length <= 256 && typeof v === "number" && Number.isSafeInteger(v) && v >= 0));
1813
+ const dropped = rawMS.length - this.msgSeqMap.size;
1814
+ if (dropped > 0)
1815
+ process.stderr.write(`[QQ:${this.name}] Dropped ${dropped} invalid msgSeqMap entries during restore
1816
+ `);
1817
+ }
1676
1818
  return true;
1677
1819
  } catch (e) {
1678
- process.stderr.write(`[QQ:${this.name}] Failed to restore QQ state: ${e instanceof Error ? e.message : String(e)}
1820
+ process.stderr.write(`[QQ:${this.name}] Failed to restore QQ state: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
1679
1821
  `);
1680
1822
  return false;
1681
1823
  }
@@ -1744,6 +1886,47 @@ var QQChannel = class extends ChannelBase {
1744
1886
  } catch {
1745
1887
  }
1746
1888
  }
1889
+ // ── ReplyMsgId helpers ────────────────────────────────────────
1890
+ /**
1891
+ * Set replyMsgId for a chat, cleaning up the previous entry's msgSeqMap
1892
+ * to prevent orphaned entries accumulating over time.
1893
+ */
1894
+ setReplyMsgId(chatId, msgId) {
1895
+ const oldEntry = this.replyMsgId.get(chatId);
1896
+ if (oldEntry && oldEntry.msgId !== msgId) {
1897
+ this.msgSeqMap.delete(oldEntry.msgId);
1898
+ }
1899
+ this.replyMsgId.set(chatId, { msgId, timestamp: Date.now() });
1900
+ this.saveQQState();
1901
+ }
1902
+ /**
1903
+ * Start periodic cleanup of expired replyMsgId entries.
1904
+ * Evicts entries older than 5 minutes every 60 seconds, and cascades
1905
+ * to msgSeqMap.
1906
+ */
1907
+ startReplyMsgIdCleanup() {
1908
+ this.stopReplyMsgIdCleanup();
1909
+ this.replyMsgIdCleanupTimer = setInterval(() => {
1910
+ const cutoff = Date.now() - _QQChannel.REPLY_MSG_ID_TTL_MS;
1911
+ let dirty = false;
1912
+ for (const [chatId, entry] of this.replyMsgId) {
1913
+ if (entry.timestamp < cutoff) {
1914
+ this.msgSeqMap.delete(entry.msgId);
1915
+ this.replyMsgId.delete(chatId);
1916
+ dirty = true;
1917
+ }
1918
+ }
1919
+ if (dirty)
1920
+ this.saveQQState();
1921
+ }, 6e4);
1922
+ this.replyMsgIdCleanupTimer.unref();
1923
+ }
1924
+ stopReplyMsgIdCleanup() {
1925
+ if (this.replyMsgIdCleanupTimer) {
1926
+ clearInterval(this.replyMsgIdCleanupTimer);
1927
+ this.replyMsgIdCleanupTimer = null;
1928
+ }
1929
+ }
1747
1930
  // ── Token ──────────────────────────────────────────────────────
1748
1931
  async fetchToken() {
1749
1932
  const safeName = this.name.replace(/[^A-Za-z0-9_-]/g, "_");
@@ -1785,7 +1968,7 @@ var QQChannel = class extends ChannelBase {
1785
1968
  this.fetchToken().catch((e) => {
1786
1969
  if (this.disposed)
1787
1970
  return;
1788
- process.stderr.write(`[QQ:${this.name}] Token refresh failed: ${e}, retrying in 60s
1971
+ process.stderr.write(`[QQ:${this.name}] Token refresh failed: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}, retrying in 60s
1789
1972
  `);
1790
1973
  this.scheduleTokenRefreshRetry();
1791
1974
  });
@@ -1800,7 +1983,7 @@ var QQChannel = class extends ChannelBase {
1800
1983
  this.fetchToken().catch((e) => {
1801
1984
  if (this.disposed)
1802
1985
  return;
1803
- process.stderr.write(`[QQ:${this.name}] Token refresh failed: ${e}, retrying in 60s
1986
+ process.stderr.write(`[QQ:${this.name}] Token refresh failed: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}, retrying in 60s
1804
1987
  `);
1805
1988
  this.scheduleTokenRefreshRetry();
1806
1989
  });
@@ -1834,7 +2017,7 @@ var QQChannel = class extends ChannelBase {
1834
2017
  const msg = JSON.parse(data.toString());
1835
2018
  this.handleGatewayMessage(msg, resolve);
1836
2019
  } catch (e) {
1837
- process.stderr.write(`[QQ:${this.name}] Malformed gateway message: ${e instanceof Error ? e.message : String(e)}
2020
+ process.stderr.write(`[QQ:${this.name}] Malformed gateway message: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
1838
2021
  `);
1839
2022
  }
1840
2023
  });
@@ -1874,7 +2057,7 @@ var QQChannel = class extends ChannelBase {
1874
2057
  }
1875
2058
  });
1876
2059
  this.ws.on("error", (e) => {
1877
- process.stderr.write(`[QQ:${this.name}] WebSocket error: ${e.message}
2060
+ process.stderr.write(`[QQ:${this.name}] WebSocket error: ${sanitizeLogText(e.message, 200)}
1878
2061
  `);
1879
2062
  if (!this.ws || this.ws.readyState !== wrapper_default.OPEN) {
1880
2063
  reject(e);
@@ -2002,7 +2185,7 @@ var QQChannel = class extends ChannelBase {
2002
2185
  } catch (e) {
2003
2186
  const msg = e instanceof Error ? e.message : String(e);
2004
2187
  const backoff = Math.min(1e3 * 2 ** (attempt + 1), 3e4);
2005
- process.stderr.write(`[QQ:${this.name}] RC: ${msg} (retry in ${backoff}ms, attempt ${attempt + 1}/${maxGwRetries})
2188
+ process.stderr.write(`[QQ:${this.name}] RC: ${sanitizeLogText(msg, 200)} (retry in ${backoff}ms, attempt ${attempt + 1}/${maxGwRetries})
2006
2189
  `);
2007
2190
  if (attempt < maxGwRetries - 1)
2008
2191
  await this.sleep(backoff);
@@ -2051,7 +2234,7 @@ var QQChannel = class extends ChannelBase {
2051
2234
  this.seenMessages.set(eventId, now);
2052
2235
  if (!this.seenCleanupTimer) {
2053
2236
  this.seenCleanupTimer = setInterval(() => {
2054
- const cutoff = Date.now() - 3e5;
2237
+ const cutoff = Date.now() - _QQChannel.REPLY_MSG_ID_TTL_MS;
2055
2238
  for (const [id, ts] of this.seenMessages) {
2056
2239
  if (ts < cutoff)
2057
2240
  this.seenMessages.delete(id);
@@ -2060,7 +2243,7 @@ var QQChannel = class extends ChannelBase {
2060
2243
  clearInterval(this.seenCleanupTimer);
2061
2244
  this.seenCleanupTimer = null;
2062
2245
  }
2063
- }, 6e4);
2246
+ }, 6e4).unref();
2064
2247
  }
2065
2248
  return false;
2066
2249
  }
@@ -2071,8 +2254,7 @@ var QQChannel = class extends ChannelBase {
2071
2254
  return;
2072
2255
  const chatId = event.author.user_openid || event.author.id;
2073
2256
  this.chatTypeMap.set(chatId, "c2c");
2074
- this.replyMsgId.set(chatId, event.id);
2075
- this.saveQQState();
2257
+ this.setReplyMsgId(chatId, event.id);
2076
2258
  this.handleInbound({
2077
2259
  channelName: this.name,
2078
2260
  senderId: chatId,
@@ -2083,7 +2265,7 @@ var QQChannel = class extends ChannelBase {
2083
2265
  isGroup: false,
2084
2266
  isMentioned: true,
2085
2267
  isReplyToBot: false
2086
- }).catch((e) => process.stderr.write(`[QQ:${this.name}] C2C handler error: ${e}
2268
+ }).catch((e) => process.stderr.write(`[QQ:${this.name}] C2C handler error: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
2087
2269
  `));
2088
2270
  }
2089
2271
  handleGroup(event) {
@@ -2096,8 +2278,7 @@ var QQChannel = class extends ChannelBase {
2096
2278
  }
2097
2279
  const chatId = event.group_openid;
2098
2280
  this.chatTypeMap.set(chatId, "group");
2099
- this.replyMsgId.set(chatId, event.id);
2100
- this.saveQQState();
2281
+ this.setReplyMsgId(chatId, event.id);
2101
2282
  const senderName = event.author.username || event.author.id || "QQ User";
2102
2283
  const cleanText = (event.content || "").replace(/<@[^>]{1,64}>/g, "").trim();
2103
2284
  if (!cleanText)
@@ -2123,7 +2304,7 @@ var QQChannel = class extends ChannelBase {
2123
2304
  // every group message is semantically a reply to the bot.
2124
2305
  isReplyToBot: true,
2125
2306
  ...isSlash ? {} : { alreadyPrefixed: true }
2126
- }).catch((e) => process.stderr.write(`[QQ:${this.name}] Group handler error: ${e}
2307
+ }).catch((e) => process.stderr.write(`[QQ:${this.name}] Group handler error: ${sanitizeLogText(e instanceof Error ? e.message : String(e), 200)}
2127
2308
  `));
2128
2309
  }
2129
2310
  };
@@ -12,8 +12,8 @@ import "./chunk-7RYW5LQV.js";
12
12
  import {
13
13
  ChannelBase,
14
14
  isTerminalTaskLifecycleType
15
- } from "./chunk-7DMQRPC7.js";
16
- import "./chunk-UFC57OYT.js";
15
+ } from "./chunk-6BEOH4KK.js";
16
+ import "./chunk-VRDMOSQS.js";
17
17
  import "./chunk-K5PGHDBN.js";
18
18
  import {
19
19
  require_minimal2 as require_minimal
@@ -8,42 +8,42 @@ import {
8
8
  stopAndGetCapturedInput,
9
9
  stopEarlyInputCapture
10
10
  } from "./chunk-LWGLBVWA.js";
11
- import "./chunk-6QTCOQX7.js";
11
+ import "./chunk-AGZF43UV.js";
12
12
  import "./chunk-5P5XGNYH.js";
13
- import "./chunk-K5PGHDBN.js";
14
13
  import "./chunk-SKAZWEV5.js";
14
+ import "./chunk-K5PGHDBN.js";
15
+ import "./chunk-CLQPBI4H.js";
15
16
  import "./chunk-QOMAHFYI.js";
16
17
  import "./chunk-G7OQ3RFJ.js";
17
18
  import "./chunk-LKWAVAB5.js";
18
- import "./chunk-L7OJ3ZO3.js";
19
- import "./chunk-R6RI2HIC.js";
19
+ import "./chunk-5ES5YPED.js";
20
20
  import "./chunk-2MPVVENX.js";
21
21
  import "./chunk-ZTQ26VBE.js";
22
- import "./chunk-SJBIFVD2.js";
22
+ import "./chunk-DMSNJDWG.js";
23
23
  import "./chunk-MLZQVCF3.js";
24
24
  import "./chunk-LQ7TMOCE.js";
25
25
  import "./chunk-E5A7LHNN.js";
26
- import "./chunk-BPFJQGY7.js";
26
+ import "./chunk-LM3YCCZJ.js";
27
27
  import "./chunk-GO6LNQXT.js";
28
28
  import "./chunk-B236XPGF.js";
29
- import "./chunk-YXK4GPYO.js";
29
+ import "./chunk-NVFJSIAX.js";
30
30
  import "./chunk-TOAUDIS7.js";
31
31
  import "./chunk-NPQWQYU6.js";
32
- import "./chunk-CHY5C5T4.js";
32
+ import "./chunk-JN2VJ33O.js";
33
33
  import "./chunk-E6US47KI.js";
34
34
  import "./chunk-UWCTAVOD.js";
35
35
  import "./chunk-OFEVLU4C.js";
36
36
  import "./chunk-OMX7CUOE.js";
37
37
  import "./chunk-MOUXUCXQ.js";
38
38
  import "./chunk-BZHLWC6T.js";
39
- import "./chunk-DG573EOO.js";
40
- import "./chunk-MTNTVOJR.js";
39
+ import "./chunk-RZORUN6X.js";
40
+ import "./chunk-MJKMIQMK.js";
41
41
  import "./chunk-TENOUWY2.js";
42
42
  import "./chunk-GLPV75ES.js";
43
43
  import "./chunk-22IFUCVR.js";
44
44
  import "./chunk-T42ACHFI.js";
45
45
  import "./chunk-SIUQ3YYX.js";
46
- import "./chunk-YTFBURQD.js";
46
+ import "./chunk-KYTQOCDE.js";
47
47
  import "./chunk-YPCPZSZB.js";
48
48
  import "./chunk-IRJWHZWU.js";
49
49
  import "./chunk-SYCJMSIJ.js";