@qwen-code/qwen-code 0.22.3-nightly.20260831.3a0c4c6108 → 0.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (381) hide show
  1. package/README.md +30 -0
  2. package/bundled/computer-use/SKILL.md +116 -180
  3. package/bundled/goal-draft/SKILL.md +5 -1
  4. package/bundled/qc-helper/docs/configuration/model-providers.md +4 -0
  5. package/bundled/qc-helper/docs/configuration/settings.md +53 -50
  6. package/bundled/qc-helper/docs/features/_meta.ts +1 -0
  7. package/bundled/qc-helper/docs/features/channels/dingtalk.md +4 -2
  8. package/bundled/qc-helper/docs/features/channels/dws.md +6 -2
  9. package/bundled/qc-helper/docs/features/channels/overview.md +1 -0
  10. package/bundled/qc-helper/docs/features/commands.md +38 -1
  11. package/bundled/qc-helper/docs/features/computer-use.md +2 -2
  12. package/bundled/qc-helper/docs/features/goals.md +9 -3
  13. package/bundled/qc-helper/docs/features/headless.md +16 -1
  14. package/bundled/qc-helper/docs/features/hooks.md +2 -1
  15. package/bundled/qc-helper/docs/features/output-styles.md +38 -0
  16. package/bundled/qc-helper/docs/qwen-serve.md +15 -0
  17. package/bundled/review/SKILL.md +5 -5
  18. package/bundled/review/references/posting.md +2 -2
  19. package/chunks/{MaxSizedBox-IHRTWGSY.js → MaxSizedBox-B3D7545A.js} +41 -45
  20. package/chunks/{StandaloneSessionPicker-TLVWVTJ7.js → StandaloneSessionPicker-QUMO4LLQ.js} +64 -67
  21. package/chunks/{acpAgent-7I5LLPP3.js → acpAgent-2GTFCIEP.js} +771 -248
  22. package/chunks/{agent-4Z4NTJXD.js → agent-XKF5SZWU.js} +26 -30
  23. package/chunks/{agent-headless-TVUJXQWU.js → agent-headless-OC2IB55D.js} +26 -30
  24. package/chunks/{anthropicContentGenerator-VSSPG7XV.js → anthropicContentGenerator-L76MR5OR.js} +14 -14
  25. package/chunks/{artifact-tool-TEYW6I4A.js → artifact-tool-MYCL2QCS.js} +2 -3
  26. package/chunks/{askUserQuestion-PYNBWV63.js → askUserQuestion-THQZMG44.js} +2 -2
  27. package/chunks/{bridge-EVURP4NO.js → bridge-IHSBI2YJ.js} +42 -46
  28. package/chunks/{build-INBK7IXX.js → build-63BIOYWK.js} +1 -1
  29. package/chunks/{channel-management-service-IDBNYSFW.js → channel-management-service-4MTCEGJB.js} +4 -4
  30. package/chunks/{channel-settings-store-MZNXRKVI.js → channel-settings-store-BVKWAI2T.js} +50 -54
  31. package/chunks/{channel-worker-group-ZLP5SJHT.js → channel-worker-group-47F4ISUZ.js} +6 -6
  32. package/chunks/{channel-worker-manager-FG5377T2.js → channel-worker-manager-I5Y44GYR.js} +50 -9
  33. package/chunks/{channel-worker-supervisor-HDVE4ADS.js → channel-worker-supervisor-6VCLUXFE.js} +4 -4
  34. package/chunks/{chunk-3452WXOK.js → chunk-2M3EWQNG.js} +17 -0
  35. package/chunks/{chunk-HDMKCJHI.js → chunk-32LU3APX.js} +1 -1
  36. package/chunks/{chunk-BSJOBW4U.js → chunk-37JFWFCD.js} +1 -1
  37. package/chunks/{chunk-AN3KFCNH.js → chunk-3JQZVCBI.js} +2 -2
  38. package/chunks/{chunk-RGEV5AUD.js → chunk-3L724BJ5.js} +11 -8
  39. package/chunks/{chunk-GCUR24KK.js → chunk-47RYEQW5.js} +2 -2
  40. package/chunks/{chunk-CM4F4JBB.js → chunk-4BGDFKQE.js} +5 -5
  41. package/chunks/{chunk-ZBDYI7VM.js → chunk-4F7GQGXB.js} +10961 -4033
  42. package/chunks/{chunk-JMRE4WJQ.js → chunk-4HVH57J3.js} +81 -17
  43. package/chunks/{chunk-26SIKQIC.js → chunk-4LIFGNI4.js} +1 -1
  44. package/chunks/{chunk-U5RTYI7D.js → chunk-4M24B5J5.js} +13 -13
  45. package/chunks/{chunk-7XICSE62.js → chunk-4PSDSCW3.js} +3 -3
  46. package/chunks/{chunk-AYYKUUKP.js → chunk-4UANMABT.js} +73 -19
  47. package/chunks/{chunk-GS7XT345.js → chunk-54C6PIGT.js} +3 -3
  48. package/chunks/{chunk-UKB2TZAO.js → chunk-5EIOJGCR.js} +4 -4
  49. package/chunks/{chunk-64REQJJ2.js → chunk-5H5S4UY5.js} +3 -3
  50. package/chunks/chunk-5IENVM7Z.js +35 -0
  51. package/chunks/{chunk-JOWQD4LO.js → chunk-5Q5RC2WE.js} +1 -1
  52. package/chunks/{chunk-3NQCZMUB.js → chunk-5RTTI4GE.js} +73 -73
  53. package/chunks/{chunk-J4Y3QJHF.js → chunk-64QH2UC6.js} +11 -1
  54. package/chunks/{chunk-I75VKFCJ.js → chunk-65HWLGA7.js} +1 -1
  55. package/chunks/{chunk-W7KWB6AH.js → chunk-6A2D4QSO.js} +8 -5
  56. package/chunks/{chunk-OTTNXUT5.js → chunk-7IKXTGZT.js} +1 -1
  57. package/chunks/{chunk-LYSZVCCD.js → chunk-7JMGTOH7.js} +427 -129
  58. package/chunks/{chunk-YOFULAHO.js → chunk-7RB56BRJ.js} +3 -3
  59. package/chunks/{chunk-6VHIWUJP.js → chunk-ADYN7P2Y.js} +2 -2
  60. package/chunks/{chunk-7DDTI7Q3.js → chunk-AHYTURFB.js} +1 -1
  61. package/chunks/{chunk-TNMOFNT4.js → chunk-ALUYNJPM.js} +1395 -2079
  62. package/chunks/{chunk-H2A2GJGL.js → chunk-AZJLY2XZ.js} +5 -5
  63. package/chunks/{chunk-BE5FGT5Z.js → chunk-BA4WJC4L.js} +1 -1
  64. package/chunks/{chunk-H5GPPDGY.js → chunk-BFY33IB4.js} +16 -8
  65. package/chunks/{chunk-RY7DL5IF.js → chunk-BJXCYUGM.js} +1 -1
  66. package/chunks/{chunk-ND7TQQPE.js → chunk-C2VWOXHS.js} +6 -6
  67. package/chunks/{chunk-T4RMUTTT.js → chunk-C4TIXFDZ.js} +2 -2
  68. package/chunks/{chunk-B2RIIK3K.js → chunk-CVX63TFJ.js} +3 -1
  69. package/chunks/{chunk-SMJYTKTB.js → chunk-DQCKVAF5.js} +1 -1
  70. package/chunks/{chunk-RLSPPTWH.js → chunk-DSX7KQPM.js} +438 -181
  71. package/chunks/{chunk-PNIGAVY6.js → chunk-DTVQSSNM.js} +2 -2
  72. package/chunks/{chunk-67AY5D3M.js → chunk-DYTW3QVG.js} +23 -8
  73. package/chunks/{chunk-3CZGSTZX.js → chunk-EBDGRBZX.js} +22 -14
  74. package/chunks/{chunk-DJBQCO2E.js → chunk-EFTPIZIC.js} +412 -3
  75. package/chunks/{chunk-QE7DTCLX.js → chunk-EIY7SUPZ.js} +1 -1
  76. package/chunks/{chunk-6OO7QEWV.js → chunk-EVFDRBUM.js} +97 -77
  77. package/chunks/{chunk-QTMPM6RC.js → chunk-EWRW2WQC.js} +3 -3
  78. package/chunks/{chunk-IIFL7QDN.js → chunk-F33GFWPR.js} +34 -11
  79. package/chunks/{chunk-YPISTYEI.js → chunk-F47DITLZ.js} +11 -1
  80. package/chunks/{chunk-OE5AQVNB.js → chunk-F7NF2IOE.js} +6 -6
  81. package/chunks/{chunk-RT4QNQ5P.js → chunk-FD5SJOWT.js} +8 -5
  82. package/chunks/{chunk-ACZ4YRYK.js → chunk-FRICLXCZ.js} +3 -3
  83. package/chunks/{chunk-IBMUI5EV.js → chunk-FUO5V5KI.js} +11 -4
  84. package/chunks/{chunk-T3TL6S3B.js → chunk-G5PBOQWI.js} +8 -5
  85. package/chunks/{chunk-D7D3HSYQ.js → chunk-G7HBEEX7.js} +12 -7
  86. package/chunks/{chunk-FXUSWLBF.js → chunk-GH2S4GD5.js} +133 -8
  87. package/chunks/{chunk-XPDKSOVW.js → chunk-GXUTFQXK.js} +42 -44
  88. package/chunks/{chunk-OSTQZIOY.js → chunk-H43PSPYS.js} +2 -2
  89. package/chunks/{chunk-UVYKCRJZ.js → chunk-HJBHMANB.js} +11 -13
  90. package/chunks/{chunk-WLEYH7CD.js → chunk-HRPFBHW7.js} +4 -0
  91. package/chunks/{chunk-DBTMP3P4.js → chunk-I2TMJPCV.js} +1 -1
  92. package/chunks/{chunk-EU2B4P3D.js → chunk-I4NRYS6A.js} +4 -4
  93. package/chunks/{chunk-JPKTAQS3.js → chunk-I5N4EAS6.js} +1 -1
  94. package/chunks/{chunk-W4BDHLRT.js → chunk-IG4W5SJR.js} +2 -2
  95. package/chunks/{chunk-BXNKREX7.js → chunk-IPATA3T2.js} +2 -2
  96. package/chunks/{chunk-NKLP3DCK.js → chunk-IQAFKVXS.js} +1 -1
  97. package/chunks/{chunk-AYHQZBJ4.js → chunk-IRKQ4YYX.js} +3 -3
  98. package/chunks/{chunk-J3NNHTV6.js → chunk-J5TTWBZK.js} +6 -0
  99. package/chunks/{chunk-AVNATYLY.js → chunk-JJKNYRFY.js} +1 -1
  100. package/chunks/{chunk-ERHAMGAA.js → chunk-JR42V4UY.js} +1 -1
  101. package/chunks/{chunk-NT7LXVV5.js → chunk-JUARRUMA.js} +362 -1084
  102. package/chunks/{chunk-OKMDOATP.js → chunk-KEVYJSI4.js} +11 -11
  103. package/chunks/{chunk-AF3QB6OL.js → chunk-KGV55H53.js} +1 -1
  104. package/chunks/{chunk-SDCHI64N.js → chunk-KM3XVTMO.js} +10 -4
  105. package/chunks/{chunk-ERRJA23L.js → chunk-KMU3ZHH4.js} +1 -1
  106. package/chunks/chunk-KOGW3YWJ.js +2054 -0
  107. package/chunks/{chunk-6NWPR2EB.js → chunk-L26ONV2Y.js} +5 -5
  108. package/chunks/chunk-L34XSHIZ.js +28 -0
  109. package/chunks/{chunk-UXEW7TQS.js → chunk-LB3WQQJK.js} +1 -1
  110. package/chunks/{chunk-YNG7XAJU.js → chunk-LEPCWS5A.js} +1 -1
  111. package/chunks/{chunk-XLENZQXH.js → chunk-LHBNR6EU.js} +2 -2
  112. package/chunks/{chunk-AKNQMSL2.js → chunk-LOBDDFYK.js} +4 -28
  113. package/chunks/{chunk-L6CUJZDG.js → chunk-LU77UT4D.js} +2 -2
  114. package/chunks/{chunk-3EGEBDTW.js → chunk-M4KFODIP.js} +1 -1
  115. package/chunks/{chunk-JLSZT354.js → chunk-M4LBBSVP.js} +2 -0
  116. package/chunks/{chunk-YOMKOM7E.js → chunk-MP6YZ4RK.js} +6580 -5992
  117. package/chunks/chunk-N2TNM3QB.js +9 -0
  118. package/chunks/{chunk-GDXSXL3H.js → chunk-NFIDVZND.js} +1 -1
  119. package/chunks/{chunk-NT5XIL5H.js → chunk-NQ4L2CMD.js} +51 -6
  120. package/chunks/{chunk-OQYXJK2V.js → chunk-NRL5CUZT.js} +1 -1
  121. package/chunks/{chunk-FIWZOMBF.js → chunk-NSUKQ4DN.js} +6 -0
  122. package/chunks/chunk-NUHOLAQ6.js +59 -0
  123. package/chunks/{chunk-BBYTY46C.js → chunk-NVVJTUSL.js} +266 -105
  124. package/chunks/{chunk-CAZADEU7.js → chunk-NXKOVOM5.js} +9 -9
  125. package/chunks/{chunk-5Q372OFJ.js → chunk-O4KNCAX4.js} +57 -10
  126. package/chunks/{chunk-GOXKNSDZ.js → chunk-O5CD7T4T.js} +40 -9
  127. package/chunks/{chunk-XIQ5HQ2F.js → chunk-OBTWL6ZW.js} +1 -1
  128. package/chunks/{chunk-5MK45KZ3.js → chunk-OHOO527W.js} +1 -1
  129. package/chunks/{chunk-CETB5XY4.js → chunk-ORFIYTI2.js} +1 -1
  130. package/chunks/{chunk-7E7UCJHS.js → chunk-OSHQMOBS.js} +18 -17
  131. package/chunks/{chunk-YDQ4OCDK.js → chunk-OSSTATJF.js} +89 -1
  132. package/chunks/chunk-P6UIF2OW.js +400 -0
  133. package/chunks/{chunk-V4HN35IF.js → chunk-PCRBLMIN.js} +16 -2
  134. package/chunks/{chunk-L2OKAIUK.js → chunk-QI27MKNQ.js} +23 -15
  135. package/chunks/{chunk-FHPYRXRH.js → chunk-QJGYU5PG.js} +1 -1
  136. package/chunks/{chunk-IVUWTA2D.js → chunk-QJVZLILI.js} +1 -1
  137. package/chunks/{chunk-TBJ3SNS3.js → chunk-QKDNS6FU.js} +1 -1
  138. package/chunks/{chunk-YKADANK6.js → chunk-QQD2GART.js} +10 -3
  139. package/chunks/{chunk-ED7DD7MV.js → chunk-RAFQIHN2.js} +1 -1
  140. package/chunks/{chunk-TV7BJ7TX.js → chunk-RJUVTJEZ.js} +1 -1
  141. package/chunks/{chunk-RVCGAHC7.js → chunk-RM4WT2XB.js} +4 -4
  142. package/chunks/{chunk-6YXNJXQW.js → chunk-RN3YGDCA.js} +3 -3
  143. package/chunks/{chunk-SMRDCANI.js → chunk-S6H3ELPG.js} +1 -1
  144. package/chunks/{chunk-MBZ5ORJB.js → chunk-SI7WDR3U.js} +281 -2
  145. package/chunks/{chunk-5FGWVPCM.js → chunk-SRF4KTAG.js} +4 -4
  146. package/chunks/{chunk-LFAR7CPW.js → chunk-STCVJXQB.js} +23 -23
  147. package/chunks/{chunk-JDIO45X7.js → chunk-SULZPKTA.js} +1 -1
  148. package/chunks/{chunk-KUDI54QQ.js → chunk-SX2QIMJV.js} +5 -5
  149. package/chunks/{chunk-VYSZUQGU.js → chunk-TJYRTS4S.js} +2 -2
  150. package/chunks/{chunk-JOTYTYYW.js → chunk-TMKTOTMQ.js} +3 -3
  151. package/chunks/{chunk-FPMQT2YY.js → chunk-TQHPVKO6.js} +4 -4
  152. package/chunks/{chunk-GN422P4J.js → chunk-TSZSGQ3N.js} +1 -1
  153. package/chunks/{chunk-IXEZHTDR.js → chunk-U4DJ5XB3.js} +292 -38
  154. package/chunks/{chunk-MZ5A5PQW.js → chunk-UAKRDON5.js} +4 -4
  155. package/chunks/{chunk-NGKLMNWN.js → chunk-UM2FFKXN.js} +2 -2
  156. package/chunks/{chunk-5ICKESC3.js → chunk-UPFRILIL.js} +2 -2
  157. package/chunks/{chunk-RAEEQEC5.js → chunk-UUASLXHW.js} +54 -5
  158. package/chunks/chunk-V5U2NZNJ.js +29 -0
  159. package/chunks/{chunk-P5Y23G2L.js → chunk-V7RNNPGC.js} +1 -18
  160. package/chunks/{chunk-ZYPJ7HVZ.js → chunk-VBWD6C27.js} +1 -1
  161. package/chunks/{chunk-MJBHSZEJ.js → chunk-VNAYZAFX.js} +3 -3
  162. package/chunks/chunk-VPSIC437.js +780 -0
  163. package/chunks/{chunk-AAX236AR.js → chunk-VWTSRH6C.js} +52 -11
  164. package/chunks/{chunk-PDXYZBBQ.js → chunk-VYIUNFEA.js} +2 -2
  165. package/chunks/{chunk-BY24DZ4J.js → chunk-WP4AX3XD.js} +5 -7
  166. package/chunks/{chunk-X7C7KFWA.js → chunk-XLXAZLDR.js} +1 -1
  167. package/chunks/{chunk-ZQ3FKEWA.js → chunk-YPWZTR7F.js} +3 -3
  168. package/chunks/{chunk-IXHV5MIC.js → chunk-ZDFQGHZH.js} +1 -1
  169. package/chunks/chunk-ZJ2LM2SI.js +198 -0
  170. package/chunks/{chunk-PWR2NQBS.js → chunk-ZKFTS3OV.js} +3 -3
  171. package/chunks/{chunk-HMJ2P3SV.js → chunk-ZL4HFSL6.js} +91 -29
  172. package/chunks/{chunk-ID33ZRWH.js → chunk-ZTPGUFQV.js} +28 -6
  173. package/chunks/chunk-bdqvmfwv-ZTSOWAFE.js +17446 -0
  174. package/chunks/{config-utils-NNUPVGEC.js → config-utils-LVSYDLHZ.js} +42 -46
  175. package/chunks/{contextCommand-S3TPCDM5.js → contextCommand-TZD7UAJK.js} +40 -44
  176. package/chunks/{core-runtime-NASPCSQX.js → core-runtime-B4UKKIAQ.js} +42 -46
  177. package/chunks/{create-sub-session-36TNCHCP.js → create-sub-session-LUPWEUHR.js} +2 -2
  178. package/chunks/{create-sub-session-DS4BJLYZ.js → create-sub-session-NJ24B4US.js} +41 -44
  179. package/chunks/{cron-create-QXHTYUTO.js → cron-create-CRSPET3H.js} +1 -1
  180. package/chunks/{cron-delete-WV2BM42M.js → cron-delete-DB77SZTU.js} +1 -1
  181. package/chunks/{cron-list-7KVNBLZ7.js → cron-list-U2JNYWV6.js} +1 -1
  182. package/chunks/{daemon-UCVUHPJD.js → daemon-RKDGBFLK.js} +385 -19
  183. package/chunks/{daemon-git-worktree-guard-ATXVQPS3.js → daemon-git-worktree-guard-O2HPOBAB.js} +40 -44
  184. package/chunks/{daemon-status-provider-UI3GBTMO.js → daemon-status-provider-GRRVCJFW.js} +47 -51
  185. package/chunks/{daemon-trust-policy-SUCBJ2CA.js → daemon-trust-policy-YJL442BK.js} +46 -50
  186. package/chunks/{daemon-trust-policy-monitor-3LM5RQNS.js → daemon-trust-policy-monitor-JL7F4Y4Q.js} +46 -50
  187. package/chunks/{deferred-core-runtime-SCOJLVYG.js → deferred-core-runtime-S32AYVZI.js} +39 -43
  188. package/chunks/{devtools-JCG4K2NZ.js → devtools-VDRJYPZF.js} +1 -1
  189. package/chunks/{discovery-X2NV535U.js → discovery-TUM3ZQ6U.js} +2 -2
  190. package/chunks/{display-image-Z4VBQDEJ.js → display-image-73C7XNRK.js} +3 -3
  191. package/chunks/{dist-7WDZYMWV.js → dist-62OZ7QXB.js} +2 -2
  192. package/chunks/{dist-FLJLHASF.js → dist-EDHQIBYD.js} +7 -7
  193. package/chunks/{dist-S3BKCTWF.js → dist-GT64AAUR.js} +1 -1
  194. package/chunks/{dist-GPSRNVVP.js → dist-JVXT4VUJ.js} +2 -2
  195. package/chunks/{dist-LY66XNUL.js → dist-L6URO6CK.js} +3 -3
  196. package/chunks/{dist-5423MG3D.js → dist-LXFYIJNG.js} +734 -128
  197. package/chunks/{dist-SDKHGH5O.js → dist-PDGNRVPY.js} +4 -4
  198. package/chunks/{dist-WAUO5OMN.js → dist-QAF5DO3Y.js} +363 -73
  199. package/chunks/{dist-WIVVPE7M.js → dist-ZCJLKQSP.js} +1 -1
  200. package/chunks/{earlyInputCapture-INWJ2STR.js → earlyInputCapture-BBPCIVZG.js} +38 -42
  201. package/chunks/{edit-B7ZRRGAE.js → edit-SUGXY63Y.js} +26 -30
  202. package/chunks/{en-E4AYTX6H.js → en-2RATMNX7.js} +2 -0
  203. package/chunks/{enter-worktree-SPZHEETQ.js → enter-worktree-B6USKSIK.js} +5 -5
  204. package/chunks/{enterPlanMode-S554IKJ2.js → enterPlanMode-MDX4RVVL.js} +26 -30
  205. package/chunks/{environment-25ADH4Y6.js → environment-VN6RXDVN.js} +41 -45
  206. package/chunks/{errors-G2I6LFTW.js → errors-UEY36PIT.js} +40 -44
  207. package/chunks/{exit-worktree-AWUXAMAM.js → exit-worktree-DLQ73SJH.js} +8 -6
  208. package/chunks/{exitPlanMode-ZFH4OYPM.js → exitPlanMode-EPHIEDAA.js} +26 -30
  209. package/chunks/{fast-path-WZHVZ2ER.js → fast-path-Y73R42LV.js} +3 -3
  210. package/chunks/{fast-path-settings-NILM6QZL.js → fast-path-settings-MFUR3IWK.js} +3 -3
  211. package/chunks/{glob-UOVDMBUP.js → glob-DMGH7EZN.js} +27 -31
  212. package/chunks/goal-tools-3RF3PXCL.js +99 -0
  213. package/chunks/{grep-LHYJ5V2N.js → grep-AJVLCVXC.js} +2 -2
  214. package/chunks/{handleAutoUpdate-4MZ45DZY.js → handleAutoUpdate-HVWQT2AU.js} +42 -46
  215. package/chunks/{i18n-KWUEI4DS.js → i18n-5OR7NTRZ.js} +39 -43
  216. package/chunks/{image-gen-YZDVO5YS.js → image-gen-VOIDOHOB.js} +1 -1
  217. package/chunks/{initializer-2NBROGMG.js → initializer-JE5RQSOE.js} +46 -50
  218. package/chunks/{installationInfo-YKUSY3ZB.js → installationInfo-KO3CCSCK.js} +38 -42
  219. package/chunks/{list-W2WV3COM.js → list-3IORSFIY.js} +49 -53
  220. package/chunks/{list-agents-PMVMHNY7.js → list-agents-SBMONIUK.js} +3 -3
  221. package/chunks/{llm-NPPHLIJI.js → llm-K26SUDVK.js} +155 -99
  222. package/chunks/{llm-content-generator-YK3WN6XW.js → llm-content-generator-TT6EAUD4.js} +5 -6
  223. package/chunks/{loadedSettingsAdapter-2P7DFWUR.js → loadedSettingsAdapter-KLLFZF3M.js} +46 -50
  224. package/chunks/{loggingContentGenerator-QYYYGU6V.js → loggingContentGenerator-EYQBA4M4.js} +43 -47
  225. package/chunks/{loop-wakeup-EBM4F5MZ.js → loop-wakeup-QA6SHCZT.js} +2 -2
  226. package/chunks/{ls-F6TRX3DD.js → ls-HEJNCEYO.js} +1 -1
  227. package/chunks/{lsp-QYTOS2FI.js → lsp-WOQKNZP6.js} +1 -1
  228. package/chunks/{managed-npm-update-UMC4NBWW.js → managed-npm-update-HIJTODQT.js} +38 -42
  229. package/chunks/{mcp-OFI6XDP2.js → mcp-A2UEHETW.js} +46 -50
  230. package/chunks/{monitor-QX3BM3JY.js → monitor-DKNZQAB2.js} +28 -32
  231. package/chunks/{node-QKLNSZMX.js → node-UETAYMMO.js} +3 -3
  232. package/chunks/{nonInteractiveCli-NVRMD5MN.js → nonInteractiveCli-YA47F2F4.js} +86 -89
  233. package/chunks/{notebook-edit-AAILDPSV.js → notebook-edit-MGHTRL2D.js} +26 -30
  234. package/chunks/{openaiContentGenerator-53PB3CMN.js → openaiContentGenerator-ZJIEQ3ZJ.js} +15 -17
  235. package/chunks/{pidfile-5ACKG2LI.js → pidfile-ETHAZNMY.js} +38 -42
  236. package/chunks/{processUtils-2BCDO3DZ.js → processUtils-UY3SAJJZ.js} +2 -2
  237. package/chunks/{prompt-terminal-ledger-3RKW73A2.js → prompt-terminal-ledger-GZ747VYE.js} +39 -43
  238. package/chunks/{qwenContentGenerator-N4LLWDPH.js → qwenContentGenerator-VI4KATRY.js} +39 -43
  239. package/chunks/{read-file-DPAKXHYE.js → read-file-P7F4P7LV.js} +6 -8
  240. package/chunks/{read-mcp-resource-R4NO75DW.js → read-mcp-resource-GLAGB6R7.js} +1 -1
  241. package/chunks/{record-artifact-2EAYLAL5.js → record-artifact-SWVR7NSU.js} +3 -3
  242. package/chunks/renderer-selection-M4UN63VJ.js +99 -0
  243. package/chunks/{report-findings-Y4MSHDS3.js → report-findings-AL5YW3KI.js} +4 -4
  244. package/chunks/{request-shutdown-DWRMGTMB.js → request-shutdown-5YK4IZ54.js} +5 -5
  245. package/chunks/{resumeHistoryUtils-3JQORXAK.js → resumeHistoryUtils-DPZKFW24.js} +44 -48
  246. package/chunks/{ripGrep-AHF5QCI7.js → ripGrep-C7LJKUPZ.js} +9 -11
  247. package/chunks/{run-qwen-serve-3LKV7KDC.js → run-qwen-serve-OGTEEUR2.js} +132 -81
  248. package/chunks/{runtime-66F4W3IA.js → runtime-LNBLEMZS.js} +51 -55
  249. package/chunks/{scheduled-tasks-2NVKS5Q2.js → scheduled-tasks-FLDYZQOF.js} +44 -48
  250. package/chunks/{scheduler-JNV7T3ZO.js → scheduler-73YXGUGW.js} +40 -44
  251. package/chunks/{sdk-exporters-grpc-G5IT4XS4.js → sdk-exporters-grpc-MXTVSE3C.js} +2 -2
  252. package/chunks/{sdk-exporters-http-MFIWD23D.js → sdk-exporters-http-3JO5TJNU.js} +3 -3
  253. package/chunks/{sdk-impl-2RXJ4Q6X.js → sdk-impl-HZAUUTHJ.js} +5 -5
  254. package/chunks/{send-message-WPZRCJOB.js → send-message-JC7NJTY6.js} +7 -7
  255. package/chunks/{serve-GP2UNRP7.js → serve-3UR2H4CV.js} +46 -50
  256. package/chunks/{server-7W6C3SOW.js → server-AOYZVVOM.js} +1736 -502
  257. package/chunks/{session-PZLBAQGG.js → session-UAWFNFGI.js} +90 -93
  258. package/chunks/session-attachments-root-ZCGXQQTR.js +104 -0
  259. package/chunks/{session-pr-refresh-OIVL3U3Z.js → session-pr-refresh-CT2INROL.js} +131 -65
  260. package/chunks/{settings-ZOHIQWYK.js → settings-BHRGDASJ.js} +45 -49
  261. package/chunks/{shell-FWZT6IUR.js → shell-YHOGC7TO.js} +26 -30
  262. package/chunks/{skill-RTQC2YGA.js → skill-ZGBKNCHQ.js} +71 -49
  263. package/chunks/{skill-settings-AKMIXFSJ.js → skill-settings-AKSP665O.js} +45 -49
  264. package/chunks/{spawnChannel-ZP23JL6O.js → spawnChannel-N25MBB6F.js} +40 -44
  265. package/chunks/{standalone-update-P2Q5H4ZU.js → standalone-update-XGPWJDRN.js} +40 -44
  266. package/chunks/start-opentui-ui-FZ4USOU7.js +55342 -0
  267. package/chunks/{startInteractiveUI-NSA6QPQZ.js → startInteractiveUI-E2WQJUOA.js} +2920 -4542
  268. package/chunks/{syntheticOutput-5URSQLIS.js → syntheticOutput-HJNZSEHN.js} +2 -2
  269. package/chunks/{task-create-3EXVDG3G.js → task-create-6RSD54S5.js} +7 -7
  270. package/chunks/{task-list-PIBYNSE7.js → task-list-IQSACPOM.js} +31 -7
  271. package/chunks/{task-stop-IV3BYWJC.js → task-stop-HE2LRQNW.js} +1 -1
  272. package/chunks/{task-update-H5BPDS5Y.js → task-update-XAJ2NYOA.js} +7 -7
  273. package/chunks/{team-create-53T42W37.js → team-create-SOKMYSQU.js} +28 -32
  274. package/chunks/{team-delete-X3WPELS6.js → team-delete-NGNNKGMG.js} +1 -1
  275. package/chunks/{team-plan-approval-D45ZC5OE.js → team-plan-approval-U7ZWXYAY.js} +26 -30
  276. package/chunks/{terminal-image-renderer-FCRUWT6C.js → terminal-image-renderer-KKM4OBLO.js} +40 -44
  277. package/chunks/{theme-manager-MHNPEDP7.js → theme-manager-GQHF3A7T.js} +38 -42
  278. package/chunks/{todoWrite-A5IOZZ3P.js → todoWrite-5UTVUXHA.js} +36 -6
  279. package/chunks/{tool-search-6RPBGGUX.js → tool-search-IAI2RVWT.js} +10 -12
  280. package/chunks/{total-session-admission-MGV56XDK.js → total-session-admission-G4CGCSTG.js} +43 -47
  281. package/chunks/{trustedFolders-QJYEFMTU.js → trustedFolders-D2I3FDPB.js} +39 -43
  282. package/chunks/{update-relaunch-ZDMQX63C.js → update-relaunch-5RWKZAL3.js} +5 -5
  283. package/chunks/{updateCheck-4QZWCGP6.js → updateCheck-ZXOQDFEI.js} +42 -46
  284. package/chunks/{useAutoAcceptIndicator-DLIQN256.js → useAutoAcceptIndicator-6EK4QGAH.js} +49 -53
  285. package/chunks/{validateNonInterActiveAuth-HGTG7AEK.js → validateNonInterActiveAuth-QPFEKATS.js} +82 -86
  286. package/chunks/{version-CPAZMC4B.js → version-JKNG7YDH.js} +1 -1
  287. package/chunks/{web-fetch-N4K5M3M4.js → web-fetch-X3AHIIHW.js} +8 -11
  288. package/chunks/{web-search-4VZKM5SF.js → web-search-K2FMOGS5.js} +6 -7
  289. package/chunks/{web-shell-static-PW7OEDQO.js → web-shell-static-POZHGGXE.js} +4 -4
  290. package/chunks/{workflow-2ALQKTHG.js → workflow-TOLPAK5G.js} +38 -38
  291. package/chunks/{workspace-providers-status-5JM4CB6R.js → workspace-providers-status-PCJK3RC7.js} +50 -54
  292. package/chunks/{workspace-registration-store-RNMFVCH7.js → workspace-registration-store-KQWVVW4Y.js} +1 -1
  293. package/chunks/{workspace-registry-6EULAPZC.js → workspace-registry-YNIOB6HJ.js} +43 -47
  294. package/chunks/{workspace-runtime-coordinator-IRI2DRCJ.js → workspace-runtime-coordinator-WG2RNEN7.js} +43 -47
  295. package/chunks/{workspace-service-SETHN4WE.js → workspace-service-G4ZNBOFH.js} +51 -55
  296. package/chunks/{workspace-skills-status-4D4EUEQU.js → workspace-skills-status-FMTPPMWC.js} +47 -51
  297. package/chunks/{workspace-trust-reconciler-4LR3CDL4.js → workspace-trust-reconciler-IBDFQBQS.js} +53 -57
  298. package/chunks/wrapper-JH3IFHT2.js +35 -0
  299. package/chunks/{write-file-45GWPSOI.js → write-file-YTLFY2S5.js} +28 -32
  300. package/chunks/{zh-2BQ7P6OD.js → zh-25DF7OGK.js} +2 -0
  301. package/chunks/{zh-TW-UFXRZTXX.js → zh-TW-5EDMZVGK.js} +2 -0
  302. package/chunks/{zoom-image-K6IQUKRC.js → zoom-image-IFXSN74N.js} +6 -8
  303. package/cli.js +17 -13
  304. package/locales/en.js +3 -0
  305. package/locales/zh-TW.js +3 -0
  306. package/locales/zh.js +3 -0
  307. package/package.json +3 -3
  308. package/web-shell/assets/{abnfDiagram-VCTEODGH-C80OZcPP.js → abnfDiagram-VCTEODGH-Cxf7xE_Z.js} +1 -1
  309. package/web-shell/assets/{arc-AUqStYgf.js → arc-ESi1eNkE.js} +1 -1
  310. package/web-shell/assets/{architectureDiagram-5GKGNRK7-CQYOdYla.js → architectureDiagram-5GKGNRK7-D9l7-bDo.js} +1 -1
  311. package/web-shell/assets/{blockDiagram-NRAW4CY4-lYKlFysy.js → blockDiagram-NRAW4CY4-Bc8DEasw.js} +1 -1
  312. package/web-shell/assets/{c4Diagram-UCG6FXSJ-BoS23iIp.js → c4Diagram-UCG6FXSJ-Dimb2Hmh.js} +1 -1
  313. package/web-shell/assets/channel-B7ohGDil.js +1 -0
  314. package/web-shell/assets/{chunk-2Q5K7J3B-DLLooL1E.js → chunk-2Q5K7J3B-jVDmOpAQ.js} +1 -1
  315. package/web-shell/assets/{chunk-5VM5RSS4-kPfJxScY.js → chunk-5VM5RSS4-DbG_SwdB.js} +1 -1
  316. package/web-shell/assets/{chunk-F27PBJKO-CVGFBqkD.js → chunk-F27PBJKO-QEc4cY1v.js} +1 -1
  317. package/web-shell/assets/{chunk-G27WJ6UU-CnM_kOVV.js → chunk-G27WJ6UU-iJ36lQ3X.js} +1 -1
  318. package/web-shell/assets/{chunk-JWPE2WC7-Cj-ajOkT.js → chunk-JWPE2WC7-DuArnVtF.js} +1 -1
  319. package/web-shell/assets/{chunk-LCL6LL3I-8L5c-wFo.js → chunk-LCL6LL3I-DxOf1zwL.js} +1 -1
  320. package/web-shell/assets/{chunk-POPQ4Y6H-DsXTxpvL.js → chunk-POPQ4Y6H-lVLu9Ild.js} +1 -1
  321. package/web-shell/assets/{chunk-SVP7TREG-DU5GE1_z.js → chunk-SVP7TREG-C6XYlIer.js} +1 -1
  322. package/web-shell/assets/{chunk-XXDRQBXY-D2IIWZKt.js → chunk-XXDRQBXY-CiG2j2Ji.js} +1 -1
  323. package/web-shell/assets/classDiagram-DTDB5LWJ-DdFpqpfD.js +1 -0
  324. package/web-shell/assets/classDiagram-v2-JRS7N3AN-DdFpqpfD.js +1 -0
  325. package/web-shell/assets/{cose-bilkent-JH36ORCC-CF_txUJr.js → cose-bilkent-JH36ORCC-DGVHMMVm.js} +1 -1
  326. package/web-shell/assets/{cynefin-OW5HDTMX-DEZ-My-Z.js → cynefin-OW5HDTMX-D6cgpCnH.js} +1 -1
  327. package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BV7EKUS6.js → cynefinDiagram-5FMLGOSQ-BKv4Z-UX.js} +1 -1
  328. package/web-shell/assets/{dagre-3AP2YEHR-JGIX0G4H.js → dagre-3AP2YEHR-B4ABMIG-.js} +1 -1
  329. package/web-shell/assets/{diagram-S7CK7UJ4-DdUY7q6A.js → diagram-S7CK7UJ4-DgCkp_Lm.js} +1 -1
  330. package/web-shell/assets/{diagram-UQ7AKVKN-fhzRZ19v.js → diagram-UQ7AKVKN-FG0FNokz.js} +1 -1
  331. package/web-shell/assets/{diagram-VSXAHHWV-BOgOex6q.js → diagram-VSXAHHWV-JgkP9qg-.js} +1 -1
  332. package/web-shell/assets/{diagram-VX7I27RA-C0NknIz6.js → diagram-VX7I27RA-ADh2x83l.js} +1 -1
  333. package/web-shell/assets/{diagram-Z3DM3KII-C__3mUBX.js → diagram-Z3DM3KII-yXqoYF1J.js} +1 -1
  334. package/web-shell/assets/{ebnfDiagram-PWID7BFC-BvPhqycH.js → ebnfDiagram-PWID7BFC-Duk83Ek_.js} +1 -1
  335. package/web-shell/assets/{erDiagram-SSCWMZ5O-BqzoNoL9.js → erDiagram-SSCWMZ5O-DMdvxySG.js} +1 -1
  336. package/web-shell/assets/{flowDiagram-A5DVABFB-CJKOre47.js → flowDiagram-A5DVABFB-DHjVgSji.js} +1 -1
  337. package/web-shell/assets/{ganttDiagram-EL5Y4UJY-C5xZjrp0.js → ganttDiagram-EL5Y4UJY-DMM9DkCE.js} +1 -1
  338. package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-C0EjwuPK.js → gitGraphDiagram-WWUBYQGX-t_ug9vO8.js} +1 -1
  339. package/web-shell/assets/index-BGZRqbRo.css +36 -0
  340. package/web-shell/assets/index-DRri_6_x.js +2067 -0
  341. package/web-shell/assets/{index-C5M93syE.js → index-zqvnpGHv.js} +1 -1
  342. package/web-shell/assets/{infoDiagram-RXCK75RN-BUwzsYOs.js → infoDiagram-RXCK75RN-eT1fANNm.js} +1 -1
  343. package/web-shell/assets/{ishikawaDiagram-5VMMS53U-EDJ_DH3V.js → ishikawaDiagram-5VMMS53U-k3evzZNn.js} +1 -1
  344. package/web-shell/assets/{journeyDiagram-EYS64GPL-BnfcOsS0.js → journeyDiagram-EYS64GPL-CGim3EAi.js} +1 -1
  345. package/web-shell/assets/{kanban-definition-3QL26DDD-D_ofTVGu.js → kanban-definition-3QL26DDD-WHfJo-22.js} +1 -1
  346. package/web-shell/assets/{layout-CBuQFdfZ.js → layout-DkqIaFlJ.js} +1 -1
  347. package/web-shell/assets/{linear-DRIHtmGv.js → linear-Bdkd3mCz.js} +1 -1
  348. package/web-shell/assets/{mermaid.core-CmR5wZH6.js → mermaid.core-CGw0LkT_.js} +6 -6
  349. package/web-shell/assets/{mindmap-definition-FBJOCRG2-BV374olC.js → mindmap-definition-FBJOCRG2-C9V4rBvo.js} +1 -1
  350. package/web-shell/assets/{pegDiagram-XKGWAZYB-Bpy1SplK.js → pegDiagram-XKGWAZYB-CwoI2T5G.js} +1 -1
  351. package/web-shell/assets/{pieDiagram-E7YTZNPT-CeZx4hR2.js → pieDiagram-E7YTZNPT-DaTmBmPG.js} +1 -1
  352. package/web-shell/assets/{quadrantDiagram-AXDQQJYC-COYKs14h.js → quadrantDiagram-AXDQQJYC-plh6MyGI.js} +1 -1
  353. package/web-shell/assets/{railroadDiagram-O6MQD6OU-5g2pOeTs.js → railroadDiagram-O6MQD6OU-D_b-S0iK.js} +1 -1
  354. package/web-shell/assets/{requirementDiagram-EFPCY7ZU-Yn8uPGtF.js → requirementDiagram-EFPCY7ZU-zUzTN7VE.js} +1 -1
  355. package/web-shell/assets/{sankeyDiagram-P5KCCOFB-CTayAGq6.js → sankeyDiagram-P5KCCOFB-m6AhoD0l.js} +1 -1
  356. package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-BFWDKzUU.js → sequenceDiagram-WJ2MYXX4-Cwhzsine.js} +1 -1
  357. package/web-shell/assets/{sizeCapture-X5ZJPWSS-CtErUbj4.js → sizeCapture-X5ZJPWSS-CcZuKIae.js} +1 -1
  358. package/web-shell/assets/{stateDiagram-HBIQ2CUA-Co3HFzOd.js → stateDiagram-HBIQ2CUA-CFoiJwD_.js} +1 -1
  359. package/web-shell/assets/stateDiagram-v2-4QOOHH4V--H8HdEmk.js +1 -0
  360. package/web-shell/assets/{swimlanes-XN3QIQJK-CDZuxzOj.js → swimlanes-XN3QIQJK-CgS9hcaV.js} +1 -1
  361. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-ShE9OIgf.js +8 -0
  362. package/web-shell/assets/{timeline-definition-24CTP7MA-UcNHj8At.js → timeline-definition-24CTP7MA-Dzzc05t9.js} +1 -1
  363. package/web-shell/assets/{vennDiagram-4TSXK5OY-JKR9pVFG.js → vennDiagram-4TSXK5OY-DemK0f7Y.js} +1 -1
  364. package/web-shell/assets/{wardleyDiagram-VM6X3IG4-C4SU-yIW.js → wardleyDiagram-VM6X3IG4-CquLxtMr.js} +1 -1
  365. package/web-shell/assets/{xychartDiagram-S5SC5T6Z-D_yoWGZ4.js → xychartDiagram-S5SC5T6Z-BTBKTM5g.js} +1 -1
  366. package/web-shell/index.html +2 -2
  367. package/chunks/chunk-4P7PPAHN.js +0 -3097
  368. package/chunks/chunk-7J6OTNGO.js +0 -424
  369. package/chunks/chunk-LMMHS3RS.js +0 -135
  370. package/chunks/chunk-MZYWNU66.js +0 -149
  371. package/chunks/chunk-T4EFG2P5.js +0 -113
  372. package/chunks/chunk-XZA32HII.js +0 -19
  373. package/chunks/goal-tools-7TNK5ZHC.js +0 -411
  374. package/web-shell/assets/channel-B0ovOJeK.js +0 -1
  375. package/web-shell/assets/classDiagram-DTDB5LWJ-DMll2-6_.js +0 -1
  376. package/web-shell/assets/classDiagram-v2-JRS7N3AN-DMll2-6_.js +0 -1
  377. package/web-shell/assets/index-B_IPzA0h.js +0 -2020
  378. package/web-shell/assets/index-D1OKGQlM.css +0 -36
  379. package/web-shell/assets/stateDiagram-v2-4QOOHH4V-C3gdRjPm.js +0 -1
  380. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-C34TGCPZ.js +0 -8
  381. /package/chunks/{chunk-FOGQO4FG.js → chunk-JA5CBKRP.js} +0 -0
@@ -4,9 +4,9 @@ import {
4
4
  require_dist,
5
5
  require_follow_redirects,
6
6
  require_form_data
7
- } from "./chunk-XIQ5HQ2F.js";
7
+ } from "./chunk-OBTWL6ZW.js";
8
8
  import "./chunk-K6KS3LTN.js";
9
- import "./chunk-7E7UCJHS.js";
9
+ import "./chunk-OSHQMOBS.js";
10
10
  import {
11
11
  ChannelBase,
12
12
  isTerminalTaskLifecycleType,
@@ -14,14 +14,14 @@ import {
14
14
  sanitizePromptText,
15
15
  sanitizeSenderName,
16
16
  truncateUtf16Units
17
- } from "./chunk-IXEZHTDR.js";
17
+ } from "./chunk-U4DJ5XB3.js";
18
18
  import "./chunk-IW6RQPQB.js";
19
19
  import "./chunk-CQ35AJ4Z.js";
20
20
  import "./chunk-DMTGGOSA.js";
21
21
  import "./chunk-YQ3U5MUC.js";
22
22
  import {
23
23
  wrapper_default
24
- } from "./chunk-J3NNHTV6.js";
24
+ } from "./chunk-J5TTWBZK.js";
25
25
  import "./chunk-RVIGZBIT.js";
26
26
  import {
27
27
  init_esbuild_shims
@@ -39,8 +39,8 @@ init_esbuild_shims();
39
39
  init_esbuild_shims();
40
40
  import { mkdirSync, rmSync, writeFileSync } from "node:fs";
41
41
  import { randomUUID as randomUUID5 } from "node:crypto";
42
- import { basename as basename2, join } from "node:path";
43
- import { tmpdir as tmpdir2 } from "node:os";
42
+ import { basename as basename3, join } from "node:path";
43
+ import { tmpdir as tmpdir3 } from "node:os";
44
44
  import { Buffer as Buffer2 } from "node:buffer";
45
45
 
46
46
  // node_modules/dingtalk-stream-sdk-nodejs/dist/index.mjs
@@ -6177,8 +6177,15 @@ __name(uploadDingTalkImage, "uploadDingTalkImage");
6177
6177
 
6178
6178
  // packages/channels/dingtalk/dist/outbound-file.js
6179
6179
  init_esbuild_shims();
6180
+ import { closeSync as closeSync2, constants, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, realpathSync as realpathSync2, statSync } from "node:fs";
6181
+ import { tmpdir as tmpdir2 } from "node:os";
6182
+ import { basename as basename2, extname as extname2, isAbsolute as isAbsolute2, relative as relative2, sep } from "node:path";
6180
6183
  var FILE_OPENING = "[FILE:";
6184
+ var MEDIA_UPLOAD_API2 = "https://oapi.dingtalk.com/media/upload";
6185
+ var MEDIA_UPLOAD_TIMEOUT_MS2 = 3e4;
6181
6186
  var MAX_FILE_PATH_CHARS = 4096;
6187
+ var MAX_FILE_BYTES = 20 * 1024 * 1024;
6188
+ var AUTH_ERROR_CODES2 = /* @__PURE__ */ new Set([40014, 42001]);
6182
6189
  var MAX_FILES_PER_RESPONSE = 5;
6183
6190
  var FILE_UNAVAILABLE_NOTICE = "[File delivery unavailable]";
6184
6191
  var OutboundFileProjector = class {
@@ -6277,6 +6284,104 @@ function withFileUnavailableNotice(text) {
6277
6284
  return `${safe}${safe ? "\n" : ""}${FILE_UNAVAILABLE_NOTICE}`;
6278
6285
  }
6279
6286
  __name(withFileUnavailableNotice, "withFileUnavailableNotice");
6287
+ function safeFileName(filePath) {
6288
+ return basename2(filePath).replace(/[\p{Cc}\p{Cf}[\]]+/gu, "_").slice(0, 200) || "file";
6289
+ }
6290
+ __name(safeFileName, "safeFileName");
6291
+ function isInside2(filePath, directory) {
6292
+ const child = relative2(directory, filePath);
6293
+ return child === "" || !isAbsolute2(child) && child !== ".." && !child.startsWith(`..${sep}`);
6294
+ }
6295
+ __name(isInside2, "isInside");
6296
+ function readValidatedFile(filePath, workspaceDir) {
6297
+ if (!isAbsolute2(filePath))
6298
+ throw new Error("File path must be absolute");
6299
+ let realPath;
6300
+ try {
6301
+ realPath = realpathSync2(filePath);
6302
+ } catch {
6303
+ throw new Error("File not found");
6304
+ }
6305
+ const roots = [
6306
+ workspaceDir,
6307
+ tmpdir2(),
6308
+ ...process.platform === "win32" ? [] : ["/tmp"]
6309
+ ].map((root) => realpathSync2(root));
6310
+ if (!roots.some((root) => isInside2(realPath, root))) {
6311
+ throw new Error("File path outside allowed directories");
6312
+ }
6313
+ if (!statSync(realPath).isFile())
6314
+ throw new Error("Not a regular file");
6315
+ const descriptor = openSync2(realPath, constants.O_RDONLY | constants.O_NONBLOCK | (constants.O_NOFOLLOW ?? 0));
6316
+ try {
6317
+ const stats = fstatSync2(descriptor);
6318
+ if (!stats.isFile())
6319
+ throw new Error("Not a regular file");
6320
+ if (stats.size === 0)
6321
+ throw new Error("File is empty");
6322
+ if (stats.size > MAX_FILE_BYTES)
6323
+ throw new Error("File is too large");
6324
+ const data = Buffer.allocUnsafe(stats.size + 1);
6325
+ let bytesRead = 0;
6326
+ while (bytesRead < data.length) {
6327
+ const count = readSync2(descriptor, data, bytesRead, data.length - bytesRead, bytesRead);
6328
+ if (count === 0)
6329
+ break;
6330
+ bytesRead += count;
6331
+ }
6332
+ if (bytesRead !== stats.size)
6333
+ throw new Error("File changed while read");
6334
+ const fileName = safeFileName(realPath);
6335
+ return {
6336
+ data: data.subarray(0, bytesRead),
6337
+ fileName,
6338
+ fileType: extname2(fileName).slice(1).toLowerCase() || "file"
6339
+ };
6340
+ } finally {
6341
+ closeSync2(descriptor);
6342
+ }
6343
+ }
6344
+ __name(readValidatedFile, "readValidatedFile");
6345
+ function sanitizeApiMessage2(message, accessToken) {
6346
+ const value = String(message ?? "");
6347
+ return (accessToken ? value.replaceAll(accessToken, "[redacted]") : value).replace(/[\r\n\t]+/g, " ").slice(0, 200);
6348
+ }
6349
+ __name(sanitizeApiMessage2, "sanitizeApiMessage");
6350
+ async function uploadDingTalkFile(file, accessToken) {
6351
+ const form = new FormData();
6352
+ form.append("media", new Blob([file.data], { type: "application/octet-stream" }), file.fileName);
6353
+ let response;
6354
+ try {
6355
+ const url2 = new URL(MEDIA_UPLOAD_API2);
6356
+ url2.searchParams.set("access_token", accessToken);
6357
+ url2.searchParams.set("type", "file");
6358
+ response = await fetch(url2, {
6359
+ method: "POST",
6360
+ body: form,
6361
+ signal: AbortSignal.timeout(MEDIA_UPLOAD_TIMEOUT_MS2)
6362
+ });
6363
+ } catch {
6364
+ throw new DingTalkMediaUploadError("DingTalk file upload failed: network request failed", false);
6365
+ }
6366
+ let payload;
6367
+ try {
6368
+ const parsed = await response.json();
6369
+ payload = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
6370
+ } catch {
6371
+ throw new DingTalkMediaUploadError(`DingTalk file upload failed: HTTP ${response.status} invalid JSON response`, response.status === 401);
6372
+ }
6373
+ const errcode = typeof payload["errcode"] === "number" ? payload["errcode"] : void 0;
6374
+ if (!response.ok || errcode !== void 0 && errcode !== 0) {
6375
+ const detail = sanitizeApiMessage2(payload["errmsg"], accessToken);
6376
+ throw new DingTalkMediaUploadError(`DingTalk file upload failed: HTTP ${response.status}${errcode === void 0 ? "" : ` errcode=${errcode}`}${detail ? ` ${detail}` : ""}`, response.status === 401 || errcode !== void 0 && AUTH_ERROR_CODES2.has(errcode));
6377
+ }
6378
+ const mediaId = typeof payload["media_id"] === "string" ? payload["media_id"] : typeof payload["mediaId"] === "string" ? payload["mediaId"] : void 0;
6379
+ if (!mediaId) {
6380
+ throw new DingTalkMediaUploadError("DingTalk file upload failed: response did not include a MediaID", false);
6381
+ }
6382
+ return mediaId;
6383
+ }
6384
+ __name(uploadDingTalkFile, "uploadDingTalkFile");
6280
6385
 
6281
6386
  // packages/channels/dingtalk/dist/DingtalkConnectionManager.js
6282
6387
  init_esbuild_shims();
@@ -6590,6 +6695,25 @@ var STATUS_CARD_TEMPLATE_ID = "675cde2f-f526-40cb-b828-f5b2b57b8b77.schema";
6590
6695
  var QUESTION_CARD_TEMPLATE_ID = "c2a6355b-9724-4f7e-9653-d33fcb3311bb.schema";
6591
6696
  var DINGTALK_API = "https://api.dingtalk.com";
6592
6697
  var CARD_FETCH_TIMEOUT_MS = 1e4;
6698
+ function isRetryableStatus(status) {
6699
+ return status === 408 || status === 425 || status === 429 || status >= 500 && status <= 599;
6700
+ }
6701
+ __name(isRetryableStatus, "isRetryableStatus");
6702
+ var DingtalkCardRequestError = class extends Error {
6703
+ static {
6704
+ __name(this, "DingtalkCardRequestError");
6705
+ }
6706
+ retryable;
6707
+ constructor(message, retryable) {
6708
+ super(message);
6709
+ this.retryable = retryable;
6710
+ this.name = "DingtalkCardRequestError";
6711
+ }
6712
+ };
6713
+ function isRetryableDingtalkCardError(error) {
6714
+ return !(error instanceof DingtalkCardRequestError) || error.retryable;
6715
+ }
6716
+ __name(isRetryableDingtalkCardError, "isRetryableDingtalkCardError");
6593
6717
  function stringifyCardParamMap(cardParamMap) {
6594
6718
  return Object.fromEntries(Object.entries(cardParamMap).map(([key, value]) => [
6595
6719
  key,
@@ -6638,7 +6762,7 @@ var DingtalkInteractiveCardClient = class {
6638
6762
  if (Array.isArray(deliveries)) {
6639
6763
  const failure = deliveries.find((entry) => entry !== null && typeof entry === "object" && entry.success === false);
6640
6764
  if (failure) {
6641
- throw new Error(`${input.templateId}: ${typeof failure.errorMsg === "string" && failure.errorMsg.trim() ? failure.errorMsg.trim() : "DingTalk card delivery failed"}`);
6765
+ throw new DingtalkCardRequestError(`${input.templateId}: ${typeof failure.errorMsg === "string" && failure.errorMsg.trim() ? failure.errorMsg.trim() : "DingTalk card delivery failed"}`, false);
6642
6766
  }
6643
6767
  }
6644
6768
  }
@@ -6663,21 +6787,28 @@ var DingtalkInteractiveCardClient = class {
6663
6787
  });
6664
6788
  }
6665
6789
  async request(path, method, body, templateId) {
6666
- const token = await this.options.getAccessToken();
6667
- const response = await this.fetch(`${DINGTALK_API}${path}`, {
6668
- method,
6669
- headers: {
6670
- "Content-Type": "application/json",
6671
- "x-acs-dingtalk-access-token": token
6672
- },
6673
- body: JSON.stringify(body),
6674
- signal: AbortSignal.timeout(CARD_FETCH_TIMEOUT_MS)
6675
- });
6676
- if (!response.ok) {
6677
- const detail = (await response.text().catch(() => "")).slice(0, 300);
6678
- throw new Error(`DingTalk Card OpenAPI ${method} ${path} failed${templateId ? ` for ${templateId}` : ""}: HTTP ${response.status}${detail ? ` ${detail}` : ""}`);
6790
+ for (let attempt = 0; ; attempt++) {
6791
+ const token = await this.options.getAccessToken();
6792
+ const response = await this.fetch(`${DINGTALK_API}${path}`, {
6793
+ method,
6794
+ headers: {
6795
+ "Content-Type": "application/json",
6796
+ "x-acs-dingtalk-access-token": token
6797
+ },
6798
+ body: JSON.stringify(body),
6799
+ signal: AbortSignal.timeout(CARD_FETCH_TIMEOUT_MS)
6800
+ });
6801
+ if (response.status === 401 && attempt === 0) {
6802
+ this.options.invalidateAccessToken(token);
6803
+ await response.body?.cancel();
6804
+ continue;
6805
+ }
6806
+ if (!response.ok) {
6807
+ const detail = (await response.text().catch(() => "")).slice(0, 300);
6808
+ throw new DingtalkCardRequestError(`DingTalk Card OpenAPI ${method} ${path} failed${templateId ? ` for ${templateId}` : ""}: HTTP ${response.status}${detail ? ` ${detail}` : ""}`, isRetryableStatus(response.status));
6809
+ }
6810
+ return response.json().catch(() => void 0);
6679
6811
  }
6680
- return response.json().catch(() => void 0);
6681
6812
  }
6682
6813
  };
6683
6814
 
@@ -6804,8 +6935,11 @@ init_esbuild_shims();
6804
6935
  import { randomUUID as randomUUID2 } from "node:crypto";
6805
6936
  var FLUSH_INTERVAL_MS = 500;
6806
6937
  var STATUS_REFRESH_INTERVAL_MS = 1e3;
6938
+ var CONTENT_SYNC_INTERVAL_SECONDS = 5;
6807
6939
  var BREAKER_PROBE_INTERVAL_MS = 3e4;
6808
6940
  var MAX_CONSECUTIVE_STATUS_FAILURES = 3;
6941
+ var INITIAL_RETRY_INTERVAL_MS = 1e3;
6942
+ var MAX_RETRY_INTERVAL_MS = 3e4;
6809
6943
  var CONTENT_LIMIT = 2e4;
6810
6944
  var TRUNCATION_MARKER = "[Earlier output truncated]\n";
6811
6945
  function boundContent(content) {
@@ -6823,10 +6957,13 @@ var StatusCardController = class {
6823
6957
  recordsByOutTrack = /* @__PURE__ */ new Map();
6824
6958
  segmentIdsByRun = /* @__PURE__ */ new Map();
6825
6959
  terminalSegmentIds = /* @__PURE__ */ new Set();
6960
+ disposed = false;
6826
6961
  constructor(options) {
6827
6962
  this.options = options;
6828
6963
  }
6829
6964
  ensure(segment, target) {
6965
+ if (this.disposed)
6966
+ return;
6830
6967
  if (this.terminalSegmentIds.has(segment.segmentId))
6831
6968
  return;
6832
6969
  if (!this.recordsBySegment.has(segment.segmentId)) {
@@ -6834,6 +6971,8 @@ var StatusCardController = class {
6834
6971
  }
6835
6972
  }
6836
6973
  replace(segment, target, content) {
6974
+ if (this.disposed)
6975
+ return;
6837
6976
  if (this.terminalSegmentIds.has(segment.segmentId))
6838
6977
  return;
6839
6978
  const record = this.recordsBySegment.get(segment.segmentId);
@@ -6844,22 +6983,27 @@ var StatusCardController = class {
6844
6983
  if (record.terminal)
6845
6984
  return;
6846
6985
  record.content = boundContent(content);
6986
+ record.contentVersion++;
6847
6987
  if (record.streamFailed)
6848
6988
  return;
6849
- record.pendingSnapshot = sanitizeStreamingImageMarkers(record.content);
6989
+ record.hasPendingWrite = true;
6850
6990
  this.scheduleFlush(record);
6851
6991
  }
6852
6992
  /**
6853
6993
  * Whether a created, still-running status card is displaying content for
6854
6994
  * this segment. Awaits the in-flight creation so a boundary decision made
6855
6995
  * while creation is pending does not race it. A latched stream failure
6856
- * means the card can never show further content, so it is not live.
6996
+ * means the card can never show further content, so it is not live. A
6997
+ * creation that is backing off for a retry is not awaited either (see
6998
+ * `awaitDelivery`).
6857
6999
  */
6858
7000
  async isCardLive(segmentId) {
7001
+ if (this.disposed)
7002
+ return false;
6859
7003
  const record = this.recordsBySegment.get(segmentId);
6860
7004
  if (!record || record.terminal || record.streamFailed)
6861
7005
  return false;
6862
- return record.ready;
7006
+ return this.awaitDelivery(record);
6863
7007
  }
6864
7008
  /**
6865
7009
  * Drain any pending snapshot so callers can treat the card's current
@@ -6868,23 +7012,64 @@ var StatusCardController = class {
6868
7012
  * caller can fall back instead of claiming delivery.
6869
7013
  */
6870
7014
  async flushPending(segmentId) {
7015
+ if (this.disposed)
7016
+ return false;
6871
7017
  const record = this.recordsBySegment.get(segmentId);
6872
7018
  if (!record || record.terminal)
6873
7019
  return false;
6874
- if (!await record.ready)
7020
+ if (!await this.awaitDelivery(record))
6875
7021
  return false;
6876
7022
  while (!record.terminal && !record.streamFailed) {
6877
7023
  if (record.flushTimer) {
6878
7024
  clearTimeout(record.flushTimer);
6879
7025
  record.flushTimer = void 0;
6880
7026
  }
7027
+ if (record.streamRetryTimer) {
7028
+ clearTimeout(record.streamRetryTimer);
7029
+ record.streamRetryTimer = void 0;
7030
+ }
7031
+ const failureVersion = record.streamFailureVersion;
6881
7032
  this.flush(record);
6882
7033
  await record.writeChain;
6883
- if (record.pendingSnapshot === void 0)
7034
+ if (record.streamFailureVersion !== failureVersion)
7035
+ return false;
7036
+ if (!record.hasPendingWrite)
6884
7037
  break;
6885
7038
  }
6886
7039
  return !record.terminal && !record.streamFailed;
6887
7040
  }
7041
+ abandon(segmentId) {
7042
+ const record = this.recordsBySegment.get(segmentId);
7043
+ if (!record || record.terminal)
7044
+ return;
7045
+ record.terminal = true;
7046
+ record.hasPendingWrite = false;
7047
+ void record.ready.then((ready) => {
7048
+ if (!ready)
7049
+ return;
7050
+ void this.options.client.updateInstance({
7051
+ outTrackId: record.outTrackId,
7052
+ cardParamMap: {
7053
+ flowStatus: 3,
7054
+ hasAction: "false",
7055
+ stop_action: "false"
7056
+ }
7057
+ }).catch(() => {
7058
+ });
7059
+ });
7060
+ this.removeRecord(record);
7061
+ }
7062
+ /**
7063
+ * Resolves once the card is known to be delivered (or not) without waiting
7064
+ * through a creation backoff: `creationAttempt` is the failed attempt until
7065
+ * the retry actually starts, so a boundary reached mid-backoff falls back
7066
+ * to text while the retry keeps running for later output.
7067
+ */
7068
+ async awaitDelivery(record) {
7069
+ if (!await record.creationAttempt)
7070
+ return false;
7071
+ return record.ready;
7072
+ }
6888
7073
  createRecord(segment, target, initialContent = "") {
6889
7074
  const outTrackId = `qwen-status-${randomUUID2()}`;
6890
7075
  const record = {
@@ -6897,13 +7082,21 @@ var StatusCardController = class {
6897
7082
  content: boundContent(initialContent),
6898
7083
  startedAt: Date.now(),
6899
7084
  lastStatusSecond: 0,
7085
+ lastContentSyncSecond: 0,
6900
7086
  ready: Promise.resolve(false),
7087
+ creationAttempt: Promise.resolve(false),
6901
7088
  terminal: false,
6902
7089
  streamFailed: false,
7090
+ streamFailureVersion: 0,
7091
+ createRetryAttempt: 0,
7092
+ streamRetryAttempt: 0,
7093
+ terminalRetryAttempt: 0,
6903
7094
  consecutiveStatusFailures: 0,
6904
7095
  stopClaimed: false,
6905
7096
  forbiddenActors: /* @__PURE__ */ new Set(),
6906
7097
  lastWriteAt: Date.now(),
7098
+ contentVersion: 0,
7099
+ hasPendingWrite: false,
6907
7100
  writeChain: Promise.resolve()
6908
7101
  };
6909
7102
  this.recordsBySegment.set(record.segmentId, record);
@@ -6925,6 +7118,8 @@ var StatusCardController = class {
6925
7118
  void this.finalize(segmentId, boundContent(error), "Failed", true);
6926
7119
  }
6927
7120
  cancelRun(runId, reason) {
7121
+ if (this.disposed)
7122
+ return;
6928
7123
  for (const segmentId of [...this.segmentIdsByRun.get(runId) ?? []]) {
6929
7124
  const record = this.recordsBySegment.get(segmentId);
6930
7125
  if (!record)
@@ -6933,6 +7128,8 @@ var StatusCardController = class {
6933
7128
  }
6934
7129
  }
6935
7130
  claimStop(outTrackId, actorId) {
7131
+ if (this.disposed)
7132
+ return { kind: "ignored", actorId };
6936
7133
  const record = this.recordsByOutTrack.get(outTrackId);
6937
7134
  if (!record || record.terminal || record.stopClaimed) {
6938
7135
  return { kind: "ignored", actorId };
@@ -6961,44 +7158,72 @@ var StatusCardController = class {
6961
7158
  };
6962
7159
  }
6963
7160
  async create(record, target) {
6964
- try {
6965
- const initialContent = sanitizeStreamingImageMarkers(record.content);
6966
- await this.options.client.createAndDeliver({
6967
- templateId: STATUS_CARD_TEMPLATE_ID,
6968
- outTrackId: record.outTrackId,
6969
- target,
6970
- cardParamMap: {
6971
- content: initialContent,
6972
- flowStatus: 2,
6973
- statusLine: this.statusLine(record, "Running").text,
6974
- hasAction: "true",
6975
- stop_action: "true"
6976
- }
7161
+ for (; ; ) {
7162
+ let settleAttempt;
7163
+ record.creationAttempt = new Promise((resolve) => {
7164
+ settleAttempt = resolve;
6977
7165
  });
7166
+ try {
7167
+ await this.options.client.createAndDeliver({
7168
+ templateId: STATUS_CARD_TEMPLATE_ID,
7169
+ outTrackId: record.outTrackId,
7170
+ target,
7171
+ cardParamMap: {
7172
+ content: sanitizeStreamingImageMarkers(record.content),
7173
+ flowStatus: 2,
7174
+ statusLine: this.statusLine(record, "Running").text,
7175
+ hasAction: "true",
7176
+ stop_action: "true"
7177
+ }
7178
+ });
7179
+ settleAttempt(true);
7180
+ break;
7181
+ } catch (error) {
7182
+ settleAttempt(false);
7183
+ this.options.onError?.("status card creation", error);
7184
+ if (this.disposed || record.terminal || !isRetryableDingtalkCardError(error)) {
7185
+ return false;
7186
+ }
7187
+ if (!await this.waitForCreationRetry(record))
7188
+ return false;
7189
+ }
7190
+ }
7191
+ if (this.disposed)
7192
+ return false;
7193
+ if (this.recordsBySegment.get(record.segmentId) !== record)
7194
+ return true;
7195
+ try {
6978
7196
  await this.options.client.openOrUpdateStream({
6979
7197
  outTrackId: record.outTrackId,
6980
7198
  key: "content",
6981
- content: initialContent,
7199
+ content: sanitizeStreamingImageMarkers(record.content),
6982
7200
  finalize: false
6983
7201
  });
6984
- return true;
6985
7202
  } catch (error) {
6986
- this.options.onError?.("status card creation", error);
6987
- await this.options.client.updateInstance({
6988
- outTrackId: record.outTrackId,
6989
- cardParamMap: {
6990
- flowStatus: 3,
6991
- statusLine: "Unavailable",
6992
- hasAction: "false",
6993
- stop_action: "false"
6994
- }
6995
- }).catch(() => {
6996
- });
6997
- return false;
7203
+ this.handleStreamFailure(record, error);
6998
7204
  }
7205
+ return true;
7206
+ }
7207
+ /**
7208
+ * Sleeps for the next creation backoff. Resolves false when finalization or
7209
+ * disposal abandons the creation so `ready` settles without waiting.
7210
+ */
7211
+ waitForCreationRetry(record) {
7212
+ const delay = this.retryDelay(record.createRetryAttempt++);
7213
+ return new Promise((resolve) => {
7214
+ const settle2 = /* @__PURE__ */ __name((resumed) => {
7215
+ if (record.createRetryTimer)
7216
+ clearTimeout(record.createRetryTimer);
7217
+ record.createRetryTimer = void 0;
7218
+ record.abandonCreation = void 0;
7219
+ resolve(resumed);
7220
+ }, "settle");
7221
+ record.abandonCreation = () => settle2(false);
7222
+ record.createRetryTimer = setTimeout(() => settle2(true), delay);
7223
+ });
6999
7224
  }
7000
7225
  scheduleFlush(record) {
7001
- if (record.flushTimer || record.inFlight || record.terminal)
7226
+ if (record.flushTimer || record.streamRetryTimer || record.inFlight || record.terminal)
7002
7227
  return;
7003
7228
  const delay = Math.max(0, FLUSH_INTERVAL_MS - (Date.now() - record.lastWriteAt));
7004
7229
  record.flushTimer = setTimeout(() => {
@@ -7007,42 +7232,44 @@ var StatusCardController = class {
7007
7232
  }, delay);
7008
7233
  }
7009
7234
  flush(record) {
7010
- if (record.terminal || record.inFlight || record.pendingSnapshot === void 0)
7235
+ if (this.disposed || record.terminal || record.streamFailed || record.inFlight || !record.hasPendingWrite)
7011
7236
  return;
7012
- const content = record.pendingSnapshot;
7013
- record.pendingSnapshot = void 0;
7237
+ record.hasPendingWrite = false;
7238
+ let sentVersion;
7239
+ let contentWritten = false;
7014
7240
  const write = record.writeChain.then(async () => {
7015
7241
  const ready = await record.ready;
7016
- if (!ready || record.terminal)
7242
+ if (!ready || record.terminal || record.streamFailed)
7017
7243
  return;
7244
+ sentVersion = record.contentVersion;
7018
7245
  await this.options.client.openOrUpdateStream({
7019
7246
  outTrackId: record.outTrackId,
7020
7247
  key: "content",
7021
- content,
7248
+ content: sanitizeStreamingImageMarkers(record.content),
7022
7249
  finalize: false
7023
7250
  });
7251
+ contentWritten = true;
7252
+ record.streamRetryAttempt = 0;
7024
7253
  await this.updateRunningStatus(record);
7025
- }).catch((error) => {
7026
- record.streamFailed = true;
7027
- record.pendingSnapshot = void 0;
7028
- if (record.statusTimer) {
7029
- clearTimeout(record.statusTimer);
7030
- record.statusTimer = void 0;
7031
- }
7032
- this.options.onError?.("status card streaming", error);
7033
- });
7254
+ }).catch((error) => this.handleStreamFailure(record, error));
7034
7255
  const tracked = write.finally(() => {
7035
7256
  if (record.inFlight === tracked) {
7036
7257
  record.inFlight = void 0;
7037
7258
  }
7038
7259
  record.lastWriteAt = Date.now();
7039
- if (record.pendingSnapshot !== void 0)
7260
+ if (contentWritten && record.contentVersion === sentVersion) {
7261
+ record.hasPendingWrite = false;
7262
+ }
7263
+ if (record.hasPendingWrite && record.contentVersion !== sentVersion) {
7040
7264
  this.scheduleFlush(record);
7265
+ }
7041
7266
  });
7042
7267
  record.inFlight = tracked;
7043
7268
  record.writeChain = tracked;
7044
7269
  }
7045
7270
  async finalize(segmentId, content, state, isError, retainedContent) {
7271
+ if (this.disposed)
7272
+ return false;
7046
7273
  const record = this.recordsBySegment.get(segmentId);
7047
7274
  if (!record || record.terminal)
7048
7275
  return false;
@@ -7057,58 +7284,165 @@ var StatusCardController = class {
7057
7284
  if (record.flushTimer)
7058
7285
  clearTimeout(record.flushTimer);
7059
7286
  record.flushTimer = void 0;
7287
+ if (record.streamRetryTimer)
7288
+ clearTimeout(record.streamRetryTimer);
7289
+ record.streamRetryTimer = void 0;
7060
7290
  if (record.statusTimer)
7061
7291
  clearTimeout(record.statusTimer);
7062
7292
  record.statusTimer = void 0;
7063
- record.pendingSnapshot = void 0;
7293
+ record.hasPendingWrite = false;
7294
+ record.abandonCreation?.();
7295
+ if (!await record.ready) {
7296
+ this.removeRecord(record);
7297
+ return false;
7298
+ }
7299
+ await record.writeChain;
7300
+ const retained = content || (retainedContent ? retainedContent(record.content) : record.content);
7301
+ record.terminalIntent = {
7302
+ content: boundContent(sanitizeStreamingImageMarkers(retained)),
7303
+ isError,
7304
+ statusLine: this.statusLine(record, state).text,
7305
+ streamFinalizeSettled: false
7306
+ };
7307
+ return this.attemptFinalization(record);
7308
+ }
7309
+ async attemptFinalization(record) {
7310
+ if (this.disposed)
7311
+ return false;
7312
+ if (this.recordsBySegment.get(record.segmentId) !== record)
7313
+ return false;
7314
+ const intent = record.terminalIntent;
7315
+ if (!intent)
7316
+ return false;
7317
+ if (!intent.streamFinalizeSettled) {
7318
+ try {
7319
+ await this.options.client.openOrUpdateStream({
7320
+ outTrackId: record.outTrackId,
7321
+ key: "content",
7322
+ content: "",
7323
+ finalize: true,
7324
+ isError: intent.isError
7325
+ });
7326
+ intent.streamFinalizeSettled = true;
7327
+ } catch (error) {
7328
+ if (!isRetryableDingtalkCardError(error)) {
7329
+ intent.streamFinalizeSettled = true;
7330
+ }
7331
+ this.options.onError?.("status card finalization", error);
7332
+ }
7333
+ }
7334
+ if (this.disposed)
7335
+ return false;
7064
7336
  try {
7065
- if (!await record.ready)
7066
- return false;
7067
- await record.writeChain;
7068
- const retained = content || (retainedContent ? retainedContent(record.content) : record.content);
7069
- const finalContent = boundContent(sanitizeStreamingImageMarkers(retained));
7070
- await this.options.client.openOrUpdateStream({
7071
- outTrackId: record.outTrackId,
7072
- key: "content",
7073
- content: "",
7074
- finalize: true,
7075
- isError
7076
- });
7077
7337
  await this.options.client.updateInstance({
7078
7338
  outTrackId: record.outTrackId,
7079
7339
  cardParamMap: {
7080
7340
  blockList: JSON.stringify([
7081
7341
  {
7082
7342
  type: 0,
7083
- markdown: finalContent
7343
+ markdown: intent.content
7084
7344
  }
7085
7345
  ]),
7086
- content: finalContent,
7087
- copy_content: finalContent,
7346
+ content: intent.content,
7347
+ copy_content: intent.content,
7088
7348
  flowStatus: 3,
7089
- statusLine: this.statusLine(record, state).text,
7349
+ statusLine: intent.statusLine,
7090
7350
  hasAction: "false",
7091
7351
  stop_action: "false"
7092
7352
  }
7093
7353
  });
7094
7354
  record.content = "";
7355
+ this.removeRecord(record);
7095
7356
  return true;
7096
7357
  } catch (error) {
7097
7358
  this.options.onError?.("status card finalization", error);
7098
- return false;
7099
- } finally {
7100
- if (this.recordsBySegment.get(segmentId) === record) {
7101
- this.recordsBySegment.delete(segmentId);
7102
- }
7103
- if (this.recordsByOutTrack.get(record.outTrackId) === record) {
7104
- this.recordsByOutTrack.delete(record.outTrackId);
7359
+ if (isRetryableDingtalkCardError(error)) {
7360
+ this.scheduleTerminalRetry(record);
7361
+ return true;
7362
+ } else {
7363
+ this.removeRecord(record);
7105
7364
  }
7106
- const segmentIds = this.segmentIdsByRun.get(record.runId);
7107
- segmentIds?.delete(segmentId);
7108
- if (segmentIds?.size === 0) {
7109
- this.segmentIdsByRun.delete(record.runId);
7365
+ return false;
7366
+ }
7367
+ }
7368
+ scheduleStreamRetry(record) {
7369
+ if (this.disposed || record.terminal || record.streamFailed || record.streamRetryTimer) {
7370
+ return;
7371
+ }
7372
+ const delay = this.retryDelay(record.streamRetryAttempt++);
7373
+ record.streamRetryTimer = setTimeout(() => {
7374
+ record.streamRetryTimer = void 0;
7375
+ if (this.disposed || record.terminal || record.streamFailed)
7376
+ return;
7377
+ this.flush(record);
7378
+ }, delay);
7379
+ }
7380
+ scheduleTerminalRetry(record) {
7381
+ if (this.disposed || !record.terminalIntent || record.terminalRetryTimer) {
7382
+ return;
7383
+ }
7384
+ const delay = this.retryDelay(record.terminalRetryAttempt++);
7385
+ record.terminalRetryTimer = setTimeout(() => {
7386
+ record.terminalRetryTimer = void 0;
7387
+ if (this.disposed)
7388
+ return;
7389
+ void this.attemptFinalization(record);
7390
+ }, delay);
7391
+ }
7392
+ handleStreamFailure(record, error) {
7393
+ record.streamFailureVersion++;
7394
+ if (!this.disposed && !record.terminal && isRetryableDingtalkCardError(error)) {
7395
+ record.hasPendingWrite = true;
7396
+ this.scheduleStreamRetry(record);
7397
+ } else if (!record.terminal) {
7398
+ record.streamFailed = true;
7399
+ record.hasPendingWrite = false;
7400
+ if (record.statusTimer) {
7401
+ clearTimeout(record.statusTimer);
7402
+ record.statusTimer = void 0;
7110
7403
  }
7111
7404
  }
7405
+ this.options.onError?.("status card streaming", error);
7406
+ }
7407
+ retryDelay(attempt) {
7408
+ return Math.min(INITIAL_RETRY_INTERVAL_MS * 2 ** Math.min(attempt, 10), MAX_RETRY_INTERVAL_MS);
7409
+ }
7410
+ removeRecord(record) {
7411
+ record.abandonCreation?.();
7412
+ if (record.flushTimer)
7413
+ clearTimeout(record.flushTimer);
7414
+ if (record.streamRetryTimer)
7415
+ clearTimeout(record.streamRetryTimer);
7416
+ if (record.terminalRetryTimer)
7417
+ clearTimeout(record.terminalRetryTimer);
7418
+ if (record.statusTimer)
7419
+ clearTimeout(record.statusTimer);
7420
+ record.flushTimer = void 0;
7421
+ record.streamRetryTimer = void 0;
7422
+ record.terminalRetryTimer = void 0;
7423
+ record.statusTimer = void 0;
7424
+ if (this.recordsBySegment.get(record.segmentId) === record) {
7425
+ this.recordsBySegment.delete(record.segmentId);
7426
+ }
7427
+ if (this.recordsByOutTrack.get(record.outTrackId) === record) {
7428
+ this.recordsByOutTrack.delete(record.outTrackId);
7429
+ }
7430
+ const segmentIds = this.segmentIdsByRun.get(record.runId);
7431
+ segmentIds?.delete(record.segmentId);
7432
+ if (segmentIds?.size === 0) {
7433
+ this.segmentIdsByRun.delete(record.runId);
7434
+ }
7435
+ }
7436
+ dispose() {
7437
+ if (this.disposed)
7438
+ return;
7439
+ this.disposed = true;
7440
+ for (const record of [...this.recordsBySegment.values()]) {
7441
+ record.terminal = true;
7442
+ record.hasPendingWrite = false;
7443
+ this.removeRecord(record);
7444
+ }
7445
+ this.terminalSegmentIds.clear();
7112
7446
  }
7113
7447
  statusLine(record, state) {
7114
7448
  const second = Math.max(0, Math.floor((Date.now() - record.startedAt) / 1e3));
@@ -7119,17 +7453,23 @@ var StatusCardController = class {
7119
7453
  };
7120
7454
  }
7121
7455
  async updateRunningStatus(record) {
7122
- if (record.terminal || record.streamFailed)
7456
+ if (this.disposed || record.terminal || record.streamFailed)
7123
7457
  return;
7124
7458
  const status = this.statusLine(record, "Running");
7125
7459
  if (status.second === record.lastStatusSecond)
7126
7460
  return;
7461
+ const syncContent = status.second - record.lastContentSyncSecond >= CONTENT_SYNC_INTERVAL_SECONDS;
7127
7462
  try {
7128
7463
  await this.options.client.updateInstance({
7129
7464
  outTrackId: record.outTrackId,
7130
- cardParamMap: { statusLine: status.text }
7465
+ cardParamMap: {
7466
+ ...syncContent ? { content: sanitizeStreamingImageMarkers(record.content) } : {},
7467
+ statusLine: status.text
7468
+ }
7131
7469
  });
7132
7470
  record.lastStatusSecond = status.second;
7471
+ if (syncContent)
7472
+ record.lastContentSyncSecond = status.second;
7133
7473
  record.consecutiveStatusFailures = 0;
7134
7474
  if (record.statusTimer) {
7135
7475
  clearTimeout(record.statusTimer);
@@ -7142,13 +7482,13 @@ var StatusCardController = class {
7142
7482
  }
7143
7483
  }
7144
7484
  scheduleStatusRefresh(record, intervalMs = STATUS_REFRESH_INTERVAL_MS) {
7145
- if (record.terminal || record.streamFailed || record.statusTimer)
7485
+ if (this.disposed || record.terminal || record.streamFailed || record.statusTimer)
7146
7486
  return;
7147
7487
  const elapsed = Math.max(0, Date.now() - record.startedAt);
7148
7488
  const delay = Math.max(50, intervalMs - elapsed % intervalMs);
7149
7489
  record.statusTimer = setTimeout(() => {
7150
7490
  record.statusTimer = void 0;
7151
- if (record.terminal || record.streamFailed)
7491
+ if (this.disposed || record.terminal || record.streamFailed)
7152
7492
  return;
7153
7493
  const refresh = record.writeChain.then(() => this.updateRunningStatus(record));
7154
7494
  record.writeChain = refresh;
@@ -7628,6 +7968,7 @@ var DingtalkInteractionPresenter = class {
7628
7968
  if (!fallbackText2 || !this.options.sendFallback)
7629
7969
  return false;
7630
7970
  await this.sendFallback(run, presentation.context.target.chatId, fallbackText2, presentation.context.sessionId);
7971
+ statusCards?.abandon(statusContext.segmentId);
7631
7972
  return true;
7632
7973
  }
7633
7974
  if (reason === "input_requested") {
@@ -7639,6 +7980,7 @@ var DingtalkInteractionPresenter = class {
7639
7980
  if (!fallbackText2 || !this.options.sendFallback)
7640
7981
  return false;
7641
7982
  await this.sendFallback(run, presentation.context.target.chatId, fallbackText2, presentation.context.sessionId);
7983
+ statusCards?.abandon(statusContext.segmentId);
7642
7984
  return true;
7643
7985
  }
7644
7986
  statusCards?.ensure(statusContext, this.cardTarget(statusContext.target));
@@ -7649,6 +7991,7 @@ var DingtalkInteractionPresenter = class {
7649
7991
  if (!fallbackText || !this.options.sendFallback)
7650
7992
  return false;
7651
7993
  await this.sendFallback(run, presentation.context.target.chatId, fallbackText, presentation.context.sessionId);
7994
+ statusCards?.abandon(statusContext.segmentId);
7652
7995
  return true;
7653
7996
  });
7654
7997
  }
@@ -8048,9 +8391,102 @@ var EMOTION_RETRY_BASE_DELAY_MS = 250;
8048
8391
  var GROUP_MSG_API = "https://api.dingtalk.com/v1.0/robot/groupMessages/send";
8049
8392
  var DIRECT_MSG_API = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend";
8050
8393
  var PROACTIVE_MSG_KEY = "sampleMarkdown";
8394
+ var PROACTIVE_FILE_MSG_KEY = "sampleFile";
8051
8395
  var TOKEN_API = "https://oapi.dingtalk.com/gettoken";
8052
8396
  var PROACTIVE_FETCH_TIMEOUT_MS = 15e3;
8397
+ var ROBOT_MESSAGE_HOSTS = /* @__PURE__ */ new Set(["api.dingtalk.com", "oapi.dingtalk.com"]);
8398
+ var PERMANENT_TOKEN_ERROR_CODES = /* @__PURE__ */ new Set([
8399
+ 40001,
8400
+ 40013,
8401
+ 40089,
8402
+ 40096,
8403
+ 90002,
8404
+ 90003
8405
+ ]);
8053
8406
  var REPLY_FETCH_TIMEOUT_MS = 15e3;
8407
+ function presentInboundError(error) {
8408
+ const parts = [];
8409
+ let status;
8410
+ try {
8411
+ if (error instanceof Error) {
8412
+ if (typeof error.name === "string")
8413
+ parts.push(error.name);
8414
+ if (typeof error.message === "string")
8415
+ parts.push(error.message);
8416
+ } else if (typeof error === "string") {
8417
+ parts.push(error);
8418
+ }
8419
+ if (typeof error === "object" && error !== null) {
8420
+ const record = error;
8421
+ if (typeof record["code"] === "string")
8422
+ parts.push(record["code"]);
8423
+ if (typeof record["status"] === "number")
8424
+ status = record["status"];
8425
+ const body = record["body"];
8426
+ if (typeof body === "string") {
8427
+ parts.push(body);
8428
+ } else if (typeof body === "object" && body !== null) {
8429
+ const bodyRecord = body;
8430
+ for (const key of ["code", "errorKind", "message"]) {
8431
+ if (typeof bodyRecord[key] === "string")
8432
+ parts.push(bodyRecord[key]);
8433
+ }
8434
+ }
8435
+ }
8436
+ } catch {
8437
+ return {
8438
+ status: "Processing failed",
8439
+ nextStep: "Try again. If it keeps failing, contact the bot administrator."
8440
+ };
8441
+ }
8442
+ const diagnostic = parts.join(" ").slice(0, 2e3).toLowerCase();
8443
+ if (status === 401 || status === 403 || /unauthor|forbidden|authentication|credential|invalid.?token/.test(diagnostic)) {
8444
+ return {
8445
+ status: "Bot configuration error",
8446
+ nextStep: "Contact the bot administrator."
8447
+ };
8448
+ }
8449
+ if (status === 408 || status === 504 || /timeout|timed?\s+out|deadline/.test(diagnostic)) {
8450
+ return {
8451
+ status: "Request timed out",
8452
+ nextStep: "Try again. For a large request, split it into smaller parts."
8453
+ };
8454
+ }
8455
+ if (/cancel|abort/.test(diagnostic)) {
8456
+ return {
8457
+ status: "Request was cancelled",
8458
+ nextStep: "Send the request again if you still need it."
8459
+ };
8460
+ }
8461
+ if (status === 429 || /overload|rate.?limit|queue.?full|too many|busy|pending prompts full/.test(diagnostic)) {
8462
+ return {
8463
+ status: "Service is busy",
8464
+ nextStep: "Try again in a moment."
8465
+ };
8466
+ }
8467
+ if (status === 502 || status === 503 || /unavailable|econn|enotfound|etimedout|network|socket|fetch failed|connection|session[_ ](?:not[ _]found|closing)|workspace[_ ]draining|transport closed/.test(diagnostic)) {
8468
+ return {
8469
+ status: "Service is temporarily unavailable",
8470
+ nextStep: "Try again in a moment. If it keeps failing, contact the bot administrator."
8471
+ };
8472
+ }
8473
+ return {
8474
+ status: "Processing failed",
8475
+ nextStep: "Try again. If it keeps failing, contact the bot administrator."
8476
+ };
8477
+ }
8478
+ __name(presentInboundError, "presentInboundError");
8479
+ function formatInboundErrorMessage(error, reference) {
8480
+ const presentation = presentInboundError(error);
8481
+ return [
8482
+ "**Unable to process this message**",
8483
+ "",
8484
+ `**Status:** ${presentation.status}`,
8485
+ `**Next step:** ${presentation.nextStep}`,
8486
+ `**Reference:** \`${reference}\``
8487
+ ].join("\n");
8488
+ }
8489
+ __name(formatInboundErrorMessage, "formatInboundErrorMessage");
8054
8490
  var GENERATED_MEDIA_EXT = {
8055
8491
  "image/jpeg": "jpg",
8056
8492
  "image/png": "png",
@@ -8070,6 +8506,15 @@ var IMAGE_INSTRUCTIONS = [
8070
8506
  "",
8071
8507
  "Only use a real image file inside the workspace or system temporary directory."
8072
8508
  ].join("\n");
8509
+ var FILE_INSTRUCTIONS = [
8510
+ "",
8511
+ "When the user explicitly asks for a completed local file, send it by writing this on its own line:",
8512
+ "`[FILE: /absolute/path/to/file]` (without the backticks)",
8513
+ "",
8514
+ "Use at most five non-empty files inside the workspace or system temporary directory.",
8515
+ "File paths containing ] are not supported.",
8516
+ "Do not claim delivery succeeded; DingTalk shows successful files separately and reports failures in the final text."
8517
+ ].join("\n");
8073
8518
  function collectNonBotMentionIds(data) {
8074
8519
  if (!Array.isArray(data.atUsers) || typeof data.chatbotUserId !== "string") {
8075
8520
  return [];
@@ -8151,6 +8596,9 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8151
8596
  } else if (!this.config.instructions.includes("[IMAGE:")) {
8152
8597
  this.config.instructions += IMAGE_INSTRUCTIONS;
8153
8598
  }
8599
+ if (config.blockStreaming !== "on" && !this.config.instructions.includes("[FILE:")) {
8600
+ this.config.instructions += FILE_INSTRUCTIONS;
8601
+ }
8154
8602
  this.interactiveCardConfig = parseDingtalkInteractiveCardConfig(config.interactiveCards);
8155
8603
  if (!config.clientId || !config.clientSecret) {
8156
8604
  throw new Error(`Channel "${name}" requires clientId and clientSecret for DingTalk.`);
@@ -8164,7 +8612,12 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8164
8612
  if (this.interactiveCardConfig.enabled) {
8165
8613
  this.interactiveCardClient = new DingtalkInteractiveCardClient({
8166
8614
  robotCode: config.clientId,
8167
- getAccessToken: /* @__PURE__ */ __name(() => this.getProactiveToken(), "getAccessToken")
8615
+ getAccessToken: /* @__PURE__ */ __name(() => this.getProactiveToken(), "getAccessToken"),
8616
+ invalidateAccessToken: /* @__PURE__ */ __name((token) => {
8617
+ if (this.proactiveToken?.token === token) {
8618
+ this.proactiveToken = void 0;
8619
+ }
8620
+ }, "invalidateAccessToken")
8168
8621
  });
8169
8622
  if (this.interactiveCardConfig.statusCard.enabled && config.blockStreaming !== "on") {
8170
8623
  this.statusCardController = new StatusCardController({
@@ -8383,24 +8836,135 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8383
8836
  static isUnroutableGroupMessage(isGroup, conversationId) {
8384
8837
  return isGroup && !conversationId;
8385
8838
  }
8386
- projectOutgoingFileText(text, streamed) {
8839
+ resolveSessionWebhook(chatId) {
8840
+ const value = this.webhooks.get(chatId);
8841
+ if (!value)
8842
+ return void 0;
8843
+ try {
8844
+ const url2 = new URL(value);
8845
+ return url2.protocol === "https:" && url2.port === "" && ROBOT_MESSAGE_HOSTS.has(url2.hostname) ? url2.toString() : void 0;
8846
+ } catch {
8847
+ return void 0;
8848
+ }
8849
+ }
8850
+ async uploadOutboundFile(filePath) {
8851
+ const file = readValidatedFile(filePath, this.config.cwd);
8852
+ for (let attempt = 0; attempt < 2; attempt++) {
8853
+ const token = await this.getProactiveToken();
8854
+ try {
8855
+ return { file, mediaId: await uploadDingTalkFile(file, token) };
8856
+ } catch (error) {
8857
+ if (error instanceof DingTalkMediaUploadError && error.authFailure && attempt === 0) {
8858
+ this.proactiveToken = void 0;
8859
+ continue;
8860
+ }
8861
+ throw error;
8862
+ }
8863
+ }
8864
+ throw new Error("DingTalk file upload returned no MediaID");
8865
+ }
8866
+ async deliverFiles(paths, send, preflight) {
8867
+ const notices = [];
8868
+ for (const filePath of paths) {
8869
+ const displayName = safeFileName(filePath);
8870
+ try {
8871
+ preflight?.();
8872
+ const { file, mediaId } = await this.uploadOutboundFile(filePath);
8873
+ await send(file, mediaId);
8874
+ } catch (error) {
8875
+ process.stderr.write(`[DingTalk:${this.name}] outbound file delivery failed (${sanitizeLogText(displayName, 200)}): ${sanitizeLogText(error instanceof Error ? error.message : String(error), 300)}
8876
+ `);
8877
+ notices.push(`[File delivery failed: ${displayName}]`);
8878
+ }
8879
+ }
8880
+ return notices;
8881
+ }
8882
+ async sendSessionFile(chatId, file, mediaId) {
8883
+ const webhook = this.resolveSessionWebhook(chatId);
8884
+ if (!webhook)
8885
+ throw new Error("DingTalk session webhook unavailable");
8886
+ let response;
8887
+ try {
8888
+ response = await fetch(webhook, {
8889
+ method: "POST",
8890
+ redirect: "error",
8891
+ headers: { "Content-Type": "application/json" },
8892
+ body: JSON.stringify({
8893
+ msgtype: "file",
8894
+ file: {
8895
+ mediaId,
8896
+ fileName: file.fileName,
8897
+ fileType: file.fileType
8898
+ }
8899
+ }),
8900
+ signal: AbortSignal.timeout(REPLY_FETCH_TIMEOUT_MS)
8901
+ });
8902
+ } catch {
8903
+ throw new Error("DingTalk file delivery failed: network request failed");
8904
+ }
8905
+ const body = await response.text().catch(() => "");
8906
+ if (!response.ok) {
8907
+ throw new Error(`DingTalk file delivery failed: HTTP ${response.status}`);
8908
+ }
8909
+ if (!body.trim())
8910
+ return;
8911
+ let data;
8912
+ try {
8913
+ const parsed = JSON.parse(body);
8914
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
8915
+ return;
8916
+ data = parsed;
8917
+ } catch {
8918
+ return;
8919
+ }
8920
+ const code = data["errcode"] ?? data["code"];
8921
+ if (code !== void 0 && String(code) !== "0") {
8922
+ throw new Error(`DingTalk file delivery failed: API code ${code}`);
8923
+ }
8924
+ }
8925
+ appendFileNotices(text, notices) {
8926
+ if (notices.length === 0)
8927
+ return text;
8928
+ const prefix = text.trimEnd();
8929
+ return `${prefix}${prefix ? "\n" : ""}${notices.join("\n")}`;
8930
+ }
8931
+ async prepareReplyOutput(chatId, text, streamed) {
8932
+ return this.prepareFileOutput(text, (file, mediaId) => this.sendSessionFile(chatId, file, mediaId), streamed, () => {
8933
+ if (!this.resolveSessionWebhook(chatId)) {
8934
+ throw new Error("DingTalk session webhook unavailable");
8935
+ }
8936
+ });
8937
+ }
8938
+ async prepareFileOutput(text, send, streamed, preflight) {
8387
8939
  const projection = projectFileText(text);
8388
8940
  const streamedMarkers = streamed ? streamed.result("").markerCount : 0;
8389
- if (projection.markerCount === 0 && streamedMarkers === 0) {
8390
- return projection.text;
8391
- }
8392
- process.stderr.write(`[DingTalk:${this.name}] file markers redacted (final=${projection.markerCount}, streamed=${streamedMarkers})
8941
+ if (projection.markerCount > 0 || streamedMarkers > 0) {
8942
+ process.stderr.write(`[DingTalk:${this.name}] file markers projected (final=${projection.markerCount}, streamed=${streamedMarkers})
8393
8943
  `);
8394
- return withFileUnavailableNotice(projection.text);
8944
+ }
8945
+ if (this.config.blockStreaming === "on" && (projection.markerCount > 0 || streamedMarkers > 0)) {
8946
+ return this.prepareOutgoingText(withFileUnavailableNotice(projection.text));
8947
+ }
8948
+ const notices = [];
8949
+ if (projection.invalidMarkers > 0) {
8950
+ notices.push("[File delivery failed: invalid marker]");
8951
+ }
8952
+ if (projection.excessMarkers > 0) {
8953
+ notices.push("[File delivery failed: response file limit exceeded]");
8954
+ }
8955
+ if (streamedMarkers > projection.markerCount) {
8956
+ notices.push(FILE_UNAVAILABLE_NOTICE);
8957
+ }
8958
+ notices.push(...await this.deliverFiles(projection.paths, send, preflight));
8959
+ return this.prepareOutgoingText(this.appendFileNotices(projection.text, notices));
8395
8960
  }
8396
- async prepareOutgoingText(text, streamed) {
8397
- const fileSafeText = this.projectOutgoingFileText(text, streamed);
8398
- const markers = findImageMarkers(fileSafeText);
8961
+ async prepareOutgoingText(text) {
8962
+ const markers = findImageMarkers(text);
8399
8963
  if (markers.length === 0)
8400
- return fileSafeText;
8964
+ return text;
8401
8965
  const replacements = [];
8402
8966
  for (const marker of markers) {
8403
- const fileName = basename2(marker.path).replace(/[\r\n[\]]+/g, "_").slice(0, 100) || "image";
8967
+ const fileName = basename3(marker.path).replace(/[\r\n[\]]+/g, "_").slice(0, 100) || "image";
8404
8968
  try {
8405
8969
  const image = readValidatedImage(marker.path, {
8406
8970
  workspaceDir: this.config.cwd
@@ -8429,16 +8993,18 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8429
8993
  replacements.push(`[Image delivery failed: ${fileName}]`);
8430
8994
  }
8431
8995
  }
8432
- return replaceImageMarkers(fileSafeText, markers, replacements);
8996
+ return replaceImageMarkers(text, markers, replacements);
8433
8997
  }
8434
- async sendReply(chatId, text, atUserId, sourceLabel) {
8998
+ async sendReply(chatId, text, atUserId, sourceLabel, prepared = false) {
8435
8999
  const webhook = this.webhooks.get(chatId);
8436
9000
  if (!webhook) {
8437
9001
  process.stderr.write(`[DingTalk:${this.name}] No webhook for chatId ${chatId}, cannot send.
8438
9002
  `);
8439
9003
  return;
8440
9004
  }
8441
- const outgoingText = await this.prepareOutgoingText(text);
9005
+ const outgoingText = prepared ? text : await this.prepareReplyOutput(chatId, text);
9006
+ if (!outgoingText.trim())
9007
+ return;
8442
9008
  const mentionPrefix = atUserId ? `@${atUserId}
8443
9009
 
8444
9010
  ` : "";
@@ -8517,7 +9083,9 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8517
9083
  async pushProactive(target, text, sourceLabel) {
8518
9084
  if (!text.trim())
8519
9085
  return;
8520
- const outgoingText = await this.prepareOutgoingText(text);
9086
+ const outgoingText = await this.prepareFileOutput(text, (file, mediaId) => this.sendProactiveFile(target, file, mediaId));
9087
+ if (!outgoingText.trim())
9088
+ return;
8521
9089
  const sourcePrefix = sourceLabel ? `${escapeDingTalkMarkdown(sourceLabel)}
8522
9090
 
8523
9091
  ` : "";
@@ -8551,7 +9119,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8551
9119
  const errmsg = sanitizeLogText(String(data.errmsg ?? ""), 200);
8552
9120
  process.stderr.write(`[DingTalk:${this.name}] access token request failed: gettoken errcode=${data.errcode} ${errmsg}
8553
9121
  `);
8554
- throw new Error(`DingTalk access token request failed: gettoken errcode=${data.errcode}${errmsg ? ` ${errmsg}` : ""}`);
9122
+ throw new DingtalkCardRequestError(`DingTalk access token request failed: gettoken errcode=${data.errcode}${errmsg ? ` ${errmsg}` : ""}`, !PERMANENT_TOKEN_ERROR_CODES.has(Number(data.errcode)));
8555
9123
  }
8556
9124
  this.proactiveToken = {
8557
9125
  token: data.access_token,
@@ -8577,6 +9145,12 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8577
9145
  }, "\u5361\u7247\u64CD\u4F5C", "\u4F60\u65E0\u6743\u64CD\u4F5C\u8FD9\u5F20\u5361\u7247\uFF0C\u4EC5\u4EFB\u52A1\u53D1\u8D77\u4EBA\u53EF\u4EE5\u63D0\u4EA4\u6216\u505C\u6B62\u3002", "card interaction feedback");
8578
9146
  }
8579
9147
  async sendProactiveChunk(target, title, text, chunkLabel) {
9148
+ return this.sendProactivePayload(target, PROACTIVE_MSG_KEY, { title, text }, chunkLabel);
9149
+ }
9150
+ async sendProactiveFile(target, file, mediaId) {
9151
+ return this.sendProactivePayload(target, PROACTIVE_FILE_MSG_KEY, { mediaId, fileName: file.fileName, fileType: file.fileType }, `file ${file.fileName}`);
9152
+ }
9153
+ async sendProactivePayload(target, msgKey, msgParam, chunkLabel) {
8580
9154
  const targetKind = target.isGroup === true ? "group" : "dm";
8581
9155
  for (let attempt = 0; ; attempt++) {
8582
9156
  const token = await this.getProactiveToken();
@@ -8592,8 +9166,8 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8592
9166
  body: JSON.stringify({
8593
9167
  robotCode: this.config.clientId,
8594
9168
  ...targetBody,
8595
- msgKey: PROACTIVE_MSG_KEY,
8596
- msgParam: JSON.stringify({ title, text })
9169
+ msgKey,
9170
+ msgParam: JSON.stringify(msgParam)
8597
9171
  }),
8598
9172
  signal: AbortSignal.timeout(PROACTIVE_FETCH_TIMEOUT_MS)
8599
9173
  });
@@ -8614,6 +9188,27 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8614
9188
  `);
8615
9189
  throw new Error(`DingTalk proactive send failed: HTTP ${resp.status}${detail ? ` ${detail}` : ""}`);
8616
9190
  }
9191
+ if (target.isGroup === true) {
9192
+ if (msgKey !== PROACTIVE_FILE_MSG_KEY) {
9193
+ await resp.body?.cancel();
9194
+ return;
9195
+ }
9196
+ let data;
9197
+ try {
9198
+ const parsed = await resp.json();
9199
+ data = parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
9200
+ } catch {
9201
+ throw new Error("DingTalk file delivery failed: invalid JSON response");
9202
+ }
9203
+ const code = data["errcode"] ?? data["code"];
9204
+ if (code !== void 0 && String(code) !== "0") {
9205
+ throw new Error(`DingTalk file delivery failed: API code ${code}`);
9206
+ }
9207
+ if (typeof data["processQueryKey"] !== "string" || !data["processQueryKey"].trim()) {
9208
+ throw new Error("DingTalk file delivery failed: missing processQueryKey");
9209
+ }
9210
+ return;
9211
+ }
8617
9212
  if (target.isGroup === false) {
8618
9213
  let data;
8619
9214
  try {
@@ -8633,6 +9228,9 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8633
9228
  `);
8634
9229
  throw new Error("DingTalk proactive send failed: direct recipient rate limited");
8635
9230
  }
9231
+ if (msgKey === PROACTIVE_FILE_MSG_KEY && !data.processQueryKey?.trim()) {
9232
+ throw new Error("DingTalk file delivery failed: missing processQueryKey");
9233
+ }
8636
9234
  return;
8637
9235
  }
8638
9236
  await resp.body?.cancel();
@@ -8697,6 +9295,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8697
9295
  if (this.dedupTimer) {
8698
9296
  clearInterval(this.dedupTimer);
8699
9297
  }
9298
+ this.statusCardController?.dispose();
8700
9299
  this.activeReactionKeys.clear();
8701
9300
  this.sessionReactionKeys.clear();
8702
9301
  if (this.connectionManager) {
@@ -8975,7 +9574,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8975
9574
  }
8976
9575
  await this.sendReply(chatId, text, void 0, sourceLabel);
8977
9576
  }
8978
- async sendResponseMessage(chatId, text, sessionId, sourceLabel) {
9577
+ async sendResponseMessage(chatId, text, sessionId, sourceLabel, prepared = false) {
8979
9578
  let outgoingText = text;
8980
9579
  let consumesMention = true;
8981
9580
  if (this.config.blockStreaming === "on") {
@@ -8988,7 +9587,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8988
9587
  const atUserId = consumesMention && this.atSender ? this.sessionMentionTargets.get(sessionId) : void 0;
8989
9588
  if (atUserId)
8990
9589
  this.sessionMentionTargets.delete(sessionId);
8991
- await this.sendReply(chatId, outgoingText, atUserId, sourceLabel ?? this.getResponseSourceLabel(sessionId));
9590
+ await this.sendReply(chatId, outgoingText, atUserId, sourceLabel ?? this.getResponseSourceLabel(sessionId), prepared);
8992
9591
  }
8993
9592
  projectBlockStreamChunk(text, sessionId) {
8994
9593
  let state = this.blockFileProjectors.get(sessionId);
@@ -9019,13 +9618,13 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9019
9618
  const streamed = segment ? this.fileProjectors.get(segment.runId)?.projector : void 0;
9020
9619
  if (segment)
9021
9620
  this.fileProjectors.delete(segment.runId);
9022
- const outgoingText = await this.prepareOutgoingText(text, streamed);
9621
+ const outgoingText = await this.prepareReplyOutput(chatId, text, streamed);
9023
9622
  if (segment && this.interactionPresenter) {
9024
9623
  if (await this.interactionPresenter.closeOutput(segment.segmentId, outgoingText, "completed", segment)) {
9025
9624
  return;
9026
9625
  }
9027
9626
  }
9028
- await this.sendResponseMessage(chatId, outgoingText, sessionId, segment?.sourceLabel);
9627
+ await this.sendResponseMessage(chatId, outgoingText, sessionId, segment?.sourceLabel, true);
9029
9628
  }
9030
9629
  onOutputSegmentEnd(_chatId, _sessionId, segment, reason) {
9031
9630
  if (reason === "completed" || reason === "failed" || reason === "cancelled") {
@@ -9291,9 +9890,9 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9291
9890
  let filePath;
9292
9891
  let safeName;
9293
9892
  try {
9294
- dir = join(tmpdir2(), "channel-files", randomUUID5());
9893
+ dir = join(tmpdir3(), "channel-files", randomUUID5());
9295
9894
  mkdirSync(dir, { recursive: true });
9296
- safeName = basename2(typeof fileName === "string" ? fileName : "") || `dingtalk_${mediaType}_${Date.now()}.${GENERATED_MEDIA_EXT[media.mimeType] ?? "bin"}`;
9895
+ safeName = basename3(typeof fileName === "string" ? fileName : "") || `dingtalk_${mediaType}_${Date.now()}.${GENERATED_MEDIA_EXT[media.mimeType] ?? "bin"}`;
9297
9896
  filePath = join(dir, safeName);
9298
9897
  writeFileSync(filePath, media.buffer);
9299
9898
  } catch (error) {
@@ -9397,10 +9996,17 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9397
9996
  }
9398
9997
  }) : this.handleInbound(envelope);
9399
9998
  processMessage.catch((err) => {
9400
- process.stderr.write(`[DingTalk:${this.name}] Error handling message: ${err}
9999
+ const reference = randomUUID5().slice(0, 8);
10000
+ let errorSummary = "Unknown error";
10001
+ try {
10002
+ errorSummary = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
10003
+ } catch {
10004
+ }
10005
+ process.stderr.write(`[DingTalk:${this.name}] Error handling message ref=${reference}: ${sanitizeLogText(errorSummary, 300)}
9401
10006
  `);
10007
+ const fallbackMessage = formatInboundErrorMessage(err, reference);
9402
10008
  const sourceLabel = this.getInboundErrorSourceLabel(envelope);
9403
- const delivery = sourceLabel ? this.sendThreadMessage(chatId, envelope.threadId, "Sorry, something went wrong processing your message.", sourceLabel) : this.sendMessage(chatId, "Sorry, something went wrong processing your message.");
10009
+ const delivery = sourceLabel ? this.sendThreadMessage(chatId, envelope.threadId, fallbackMessage, sourceLabel) : this.sendMessage(chatId, fallbackMessage);
9404
10010
  delivery.catch(() => {
9405
10011
  });
9406
10012
  });