@qwen-code/qwen-code 0.23.1-preview.2 → 0.23.2-nightly.20260909.2e212144d3

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 (335) hide show
  1. package/README.md +35 -15
  2. package/bundled/computer-use/SKILL.md +189 -116
  3. package/bundled/goal-draft/SKILL.md +23 -13
  4. package/bundled/qc-helper/docs/_meta.ts +1 -0
  5. package/bundled/qc-helper/docs/configuration/auth.md +1 -1
  6. package/bundled/qc-helper/docs/configuration/model-providers.md +66 -16
  7. package/bundled/qc-helper/docs/configuration/settings.md +50 -0
  8. package/bundled/qc-helper/docs/conversations-recovery.md +102 -0
  9. package/bundled/qc-helper/docs/features/_meta.ts +1 -0
  10. package/bundled/qc-helper/docs/features/channels/dingtalk.md +1 -1
  11. package/bundled/qc-helper/docs/features/channels/github.md +1 -9
  12. package/bundled/qc-helper/docs/features/channels/overview.md +27 -52
  13. package/bundled/qc-helper/docs/features/channels/qqbot.md +1 -2
  14. package/bundled/qc-helper/docs/features/commands.md +79 -17
  15. package/bundled/qc-helper/docs/features/computer-use.md +9 -7
  16. package/bundled/qc-helper/docs/features/cross-session-protocol.md +291 -0
  17. package/bundled/qc-helper/docs/features/followup-suggestions.md +2 -2
  18. package/bundled/qc-helper/docs/features/goals.md +17 -3
  19. package/bundled/qc-helper/docs/features/sub-agents.md +8 -0
  20. package/bundled/qc-helper/docs/qwen-serve.md +80 -48
  21. package/chunks/{MaxSizedBox-IYIQ43IZ.js → MaxSizedBox-ZBGWYJZW.js} +29 -28
  22. package/chunks/{StandaloneSessionPicker-AWB2OHX6.js → StandaloneSessionPicker-NR5ACIJZ.js} +48 -47
  23. package/chunks/{acp-startup-profiler-BAL4LJTN.js → acp-startup-profiler-KEU6VAYR.js} +2 -2
  24. package/chunks/{acpAgent-ZC57OLS4.js → acpAgent-DM6XRCDQ.js} +361 -210
  25. package/chunks/{agent-GEBPAEJS.js → agent-EF3IIYE3.js} +20 -20
  26. package/chunks/{agent-headless-63ZEYAJK.js → agent-headless-5J2KFYR4.js} +20 -20
  27. package/chunks/{anthropicContentGenerator-6XDHXIII.js → anthropicContentGenerator-VIW2FG7G.js} +32 -9
  28. package/chunks/{artifact-tool-P52OKKEF.js → artifact-tool-G5LHNECG.js} +1 -1
  29. package/chunks/{askUserQuestion-3KAYLLMM.js → askUserQuestion-R3TXY77M.js} +1 -1
  30. package/chunks/{bridge-MHWO5I5T.js → bridge-LEMQM6QE.js} +32 -31
  31. package/chunks/{channel-management-service-NFRZXQFO.js → channel-management-service-TGF6XFXT.js} +4 -4
  32. package/chunks/{channel-settings-store-T7PMIHKC.js → channel-settings-store-FV365JSF.js} +40 -39
  33. package/chunks/{channel-worker-group-O2BWK5F7.js → channel-worker-group-SQ5FRWOH.js} +7 -7
  34. package/chunks/{channel-worker-manager-4WP7VJOD.js → channel-worker-manager-TU4ZNWOE.js} +7 -7
  35. package/chunks/{channel-worker-supervisor-CCUXD6J5.js → channel-worker-supervisor-EMITFMCP.js} +4 -4
  36. package/chunks/{chunk-3SH53ANB.js → chunk-22GORRNY.js} +12 -0
  37. package/chunks/{chunk-OFB36ZBA.js → chunk-2HYOOFDS.js} +10 -7
  38. package/chunks/chunk-2Z3T52OC.js +82 -0
  39. package/chunks/{chunk-LYHYXJJ3.js → chunk-34VPADLG.js} +3 -3
  40. package/chunks/{chunk-C7M445SS.js → chunk-3A2IMUDH.js} +14 -2
  41. package/chunks/{chunk-P5Z7VD23.js → chunk-3O77M472.js} +294 -87
  42. package/chunks/{chunk-4OCYWXKF.js → chunk-43EUMPKQ.js} +3 -3
  43. package/chunks/{chunk-W4LL5RZO.js → chunk-4ALNJDHL.js} +52 -13
  44. package/chunks/{chunk-VMFPZXRT.js → chunk-4DIMJKWU.js} +64 -43
  45. package/chunks/{chunk-ZRVFHLLK.js → chunk-5DQ4YTIZ.js} +1 -1
  46. package/chunks/{chunk-VYCJITND.js → chunk-5HV2HPO7.js} +1 -1
  47. package/chunks/{chunk-22QOQKG4.js → chunk-5WBA3DEF.js} +1 -1
  48. package/chunks/{chunk-3K65MUKD.js → chunk-65I7S4Z3.js} +2 -1
  49. package/chunks/{chunk-I7UNCY24.js → chunk-6GAYNM3F.js} +3 -3
  50. package/chunks/{chunk-2C3XDBGL.js → chunk-6S7YYUUH.js} +4 -4
  51. package/chunks/{chunk-Y3C5COGI.js → chunk-6VIATHL7.js} +1 -1
  52. package/chunks/{chunk-XNC2TCUO.js → chunk-76I36BEM.js} +4 -4
  53. package/chunks/{chunk-B54PFQS5.js → chunk-7CLLH5TI.js} +1 -1
  54. package/chunks/{chunk-RGAQDQ3Z.js → chunk-7IDZFJAV.js} +18 -9
  55. package/chunks/{chunk-5Z4FCEPY.js → chunk-7K4GGN3D.js} +606 -109
  56. package/chunks/{chunk-WLZRMF3C.js → chunk-7KZVXJ4U.js} +353 -11
  57. package/chunks/{chunk-REDVV5NC.js → chunk-7WCJEY3A.js} +7 -7
  58. package/chunks/{chunk-I67KJGM6.js → chunk-A7QZIGRB.js} +3 -3
  59. package/chunks/{chunk-SHX2HIE7.js → chunk-ATBLEXXV.js} +7 -2
  60. package/chunks/{chunk-RH344FKI.js → chunk-AUTUFD5X.js} +1 -1
  61. package/chunks/chunk-AXMWHKXA.js +42 -0
  62. package/chunks/{chunk-WFXD5OZH.js → chunk-AXWTG6R7.js} +2 -5
  63. package/chunks/{chunk-TSLRORQR.js → chunk-BDAVT6K2.js} +1809 -1588
  64. package/chunks/{chunk-HWZOOSEB.js → chunk-BDP3NTWD.js} +3 -3
  65. package/chunks/{chunk-RD3VPM4E.js → chunk-BZUHZCUO.js} +2 -2
  66. package/chunks/{chunk-HPE4LEWX.js → chunk-C24ZDDNY.js} +1 -1
  67. package/chunks/{chunk-R7TKFIQO.js → chunk-CALNF3Z3.js} +1 -1
  68. package/chunks/{chunk-RPFJJ33Z.js → chunk-CALTQWTZ.js} +1 -1
  69. package/chunks/{chunk-BF3RUIVP.js → chunk-CH2YDT6X.js} +36 -38
  70. package/chunks/{chunk-LD53HMPV.js → chunk-CRZBDVP2.js} +1 -0
  71. package/chunks/{chunk-GEV66YGE.js → chunk-D6AGS266.js} +1 -1
  72. package/chunks/{chunk-EPZWBYQI.js → chunk-D7DFZAK2.js} +19 -11
  73. package/chunks/{chunk-5V4B3EWA.js → chunk-DARWOZY6.js} +1 -1
  74. package/chunks/{chunk-XX4MBBFW.js → chunk-DGNRLJ6S.js} +4 -4
  75. package/chunks/{chunk-UTVIIA7N.js → chunk-DVOCOIS5.js} +1 -1
  76. package/chunks/{chunk-RQNAO42A.js → chunk-E4LXNQAK.js} +1 -1
  77. package/chunks/{chunk-EGRFCIXD.js → chunk-EATP5QCN.js} +84 -25
  78. package/chunks/{chunk-3RMVM33U.js → chunk-EDSU3VUG.js} +12 -5
  79. package/chunks/{chunk-733KQL63.js → chunk-EE5ZD4XU.js} +3 -3
  80. package/chunks/{chunk-QQGAR64U.js → chunk-EN3Q2S3J.js} +4 -4
  81. package/chunks/{chunk-PLUAIHZO.js → chunk-EOLGAQ25.js} +17 -16
  82. package/chunks/{chunk-37SOBIA3.js → chunk-ERXNTINK.js} +1 -1
  83. package/chunks/{chunk-L36LLVA5.js → chunk-EYCW6UF2.js} +7 -7
  84. package/chunks/{chunk-ZELCTN6Y.js → chunk-F23YN37B.js} +10 -0
  85. package/chunks/{chunk-FPGTNKCP.js → chunk-F3M6P6IQ.js} +199 -1
  86. package/chunks/{chunk-B44JBZBB.js → chunk-F4SAL7WM.js} +91 -3
  87. package/chunks/{chunk-F47DITLZ.js → chunk-FAWTMDX7.js} +14 -0
  88. package/chunks/{chunk-SI6Q52UI.js → chunk-FEEVHJOR.js} +3 -3
  89. package/chunks/{chunk-75UQFGFE.js → chunk-FN4KHWCL.js} +1 -1
  90. package/chunks/{chunk-WQBR7LN5.js → chunk-FRS3P7MQ.js} +15 -2
  91. package/chunks/{chunk-5JLQWQK6.js → chunk-FV4DM2M4.js} +2 -2
  92. package/chunks/{chunk-Z6DDPSGJ.js → chunk-GNY7B3CA.js} +1 -1
  93. package/chunks/{chunk-FDOGGKAA.js → chunk-GSFV5RQW.js} +2 -0
  94. package/chunks/{chunk-XBVNNDPK.js → chunk-GSYD7MYP.js} +8 -3
  95. package/chunks/{chunk-ERMAXPXA.js → chunk-HIXUUCGY.js} +187 -12
  96. package/chunks/{chunk-EJNYBDYC.js → chunk-HNLMYDQE.js} +1 -1
  97. package/chunks/{chunk-3K456UJF.js → chunk-HSO6D4KX.js} +93 -28
  98. package/chunks/{chunk-ANVC5CSK.js → chunk-HUJJFSMO.js} +10 -10
  99. package/chunks/{chunk-C4NXRR7T.js → chunk-HW4MRP4V.js} +2 -2
  100. package/chunks/{chunk-PMGWY6ZP.js → chunk-HWLLUDIA.js} +113 -18
  101. package/chunks/{chunk-RCUWMVN3.js → chunk-HZ2HUXX7.js} +1 -1
  102. package/chunks/{chunk-7PMKXGRP.js → chunk-IKK6NNS6.js} +91 -31
  103. package/chunks/{chunk-IMWCUWQT.js → chunk-J3TJH52D.js} +1 -1
  104. package/chunks/{chunk-BNWIX6BM.js → chunk-JFAGT5YG.js} +3 -3
  105. package/chunks/{chunk-RSU3I6UL.js → chunk-JGTMTJSQ.js} +1 -1
  106. package/chunks/{chunk-LTCI6ZOJ.js → chunk-JYGIJA4W.js} +1 -1
  107. package/chunks/{chunk-537SQ2AI.js → chunk-KECCLCXM.js} +146 -24
  108. package/chunks/{chunk-KAZWXVI3.js → chunk-KEPC5BOL.js} +5 -5
  109. package/chunks/{chunk-HZS3JRQW.js → chunk-L5VHJYHH.js} +40 -2
  110. package/chunks/{chunk-KTLT7VCX.js → chunk-LKBOBUA2.js} +2 -2
  111. package/chunks/{chunk-TDHVOZ65.js → chunk-LOBKNYPR.js} +2 -2
  112. package/chunks/{chunk-QW7BUOSI.js → chunk-LOVGQ3HZ.js} +26 -9
  113. package/chunks/{chunk-5FYGZ7E3.js → chunk-MUF4UGPB.js} +2 -2
  114. package/chunks/chunk-N3Z6Q7KC.js +384 -0
  115. package/chunks/{chunk-JOV46WGX.js → chunk-NB3NDQQK.js} +1 -1
  116. package/chunks/chunk-NFXXBWSE.js +463 -0
  117. package/chunks/chunk-NOO4QFXM.js +171 -0
  118. package/chunks/{chunk-PQSCGZT2.js → chunk-NPKCVSXX.js} +26 -2
  119. package/chunks/{chunk-FXYNIZPW.js → chunk-NV4YYXFT.js} +51 -10
  120. package/chunks/{chunk-FWH4736Q.js → chunk-O6BFERWN.js} +3 -3
  121. package/chunks/{chunk-UKADFFL2.js → chunk-OFVAS4AR.js} +1 -1
  122. package/chunks/{chunk-C55CR5I4.js → chunk-OVTPETDL.js} +6 -6
  123. package/chunks/chunk-PLEBBGHL.js +1401 -0
  124. package/chunks/{chunk-Z6KFLEG7.js → chunk-PSPAM24S.js} +1 -0
  125. package/chunks/{chunk-RRCNEW2A.js → chunk-PWR6BQ3U.js} +58 -4
  126. package/chunks/{chunk-SHK2SIR5.js → chunk-QA2B26PL.js} +4 -4
  127. package/chunks/{chunk-NFIDVZND.js → chunk-QB3KS3N3.js} +2 -21
  128. package/chunks/{chunk-NUQFUXOG.js → chunk-QTNCGZHQ.js} +2 -0
  129. package/chunks/{chunk-QJVZLILI.js → chunk-R7OO56VZ.js} +1 -1
  130. package/chunks/{chunk-MFCWL4LI.js → chunk-SK6VACCM.js} +936 -481
  131. package/chunks/{chunk-SD7Y2PMC.js → chunk-SM66GFKJ.js} +2 -2
  132. package/chunks/{chunk-ADJD4LZF.js → chunk-SNMUO5Z7.js} +1 -1
  133. package/chunks/{chunk-NXWYCSPL.js → chunk-SOA4HKRJ.js} +1 -1
  134. package/chunks/{chunk-IRKQ4YYX.js → chunk-SVWWF5TZ.js} +29 -1
  135. package/chunks/{chunk-YLFICBYK.js → chunk-SYKPMH2X.js} +3 -3
  136. package/chunks/{chunk-5HBA2Z7V.js → chunk-TGNNLRC3.js} +2 -3
  137. package/chunks/{chunk-AX23QSX3.js → chunk-TRQNRP2H.js} +4 -4
  138. package/chunks/{chunk-AUJOWIT5.js → chunk-UQOP2APG.js} +4 -24
  139. package/chunks/{chunk-HY3DXYZK.js → chunk-UYDQYDW2.js} +1 -1
  140. package/chunks/{chunk-IGOIYZBG.js → chunk-VAWM3A5N.js} +2 -2
  141. package/chunks/{chunk-6KYWU726.js → chunk-VJJXG73H.js} +417 -292
  142. package/chunks/{chunk-ZNI3V2XA.js → chunk-VJWJOKOQ.js} +2 -2
  143. package/chunks/{chunk-AWDF462I.js → chunk-VR6Y23FW.js} +2 -2
  144. package/chunks/{chunk-T7TP5UQL.js → chunk-VX2NR3SD.js} +21 -6
  145. package/chunks/{chunk-65GHQ4FX.js → chunk-WDVV3LRM.js} +707 -216
  146. package/chunks/{chunk-KP5QK3FB.js → chunk-WEU6O6VN.js} +397 -54
  147. package/chunks/{chunk-OHOO527W.js → chunk-WG7BL3FY.js} +52 -2
  148. package/chunks/{chunk-VU7O7CGQ.js → chunk-XDNFODER.js} +1 -1
  149. package/chunks/{chunk-YHDGABDC.js → chunk-XKBFYTCD.js} +1 -1
  150. package/chunks/{chunk-RUMSY4ES.js → chunk-Y7YHAY32.js} +28 -10
  151. package/chunks/{chunk-7IKXTGZT.js → chunk-YI2YCNSP.js} +1 -1
  152. package/chunks/{chunk-B5FF3LRF.js → chunk-YIE6REQ5.js} +29 -17
  153. package/chunks/{chunk-E4VX6LXB.js → chunk-YZTGGCEE.js} +10 -2
  154. package/chunks/{chunk-TXAEXF2B.js → chunk-ZEFWBG2C.js} +737 -1136
  155. package/chunks/{chunk-AIMZIXZM.js → chunk-ZM2TCZZ7.js} +5 -7
  156. package/chunks/{chunk-ZT3XUGSU.js → chunk-ZZ7RVOTU.js} +135 -26
  157. package/chunks/{config-utils-F4CFJ4MW.js → config-utils-SXFK3G4X.js} +33 -32
  158. package/chunks/{contextCommand-OIIGGOMU.js → contextCommand-QFPD26QO.js} +31 -30
  159. package/chunks/{core-runtime-JEHLOGMB.js → core-runtime-VXKNBODM.js} +35 -33
  160. package/chunks/{create-sub-session-MVFBE5RA.js → create-sub-session-7WSQETFR.js} +30 -29
  161. package/chunks/{daemon-LCUELM6E.js → daemon-U2456K5H.js} +2 -2
  162. package/chunks/{daemon-git-worktree-guard-5FTKLJOU.js → daemon-git-worktree-guard-I4DCSDUS.js} +29 -28
  163. package/chunks/{daemon-status-provider-P6A5MPMW.js → daemon-status-provider-5UV56RI4.js} +36 -35
  164. package/chunks/{daemon-trust-policy-ZJ3NFYUO.js → daemon-trust-policy-DKIBWTKU.js} +36 -35
  165. package/chunks/{daemon-trust-policy-monitor-6SDLEW7S.js → daemon-trust-policy-monitor-CPSD7UKT.js} +36 -35
  166. package/chunks/{deferred-core-runtime-DWOXIU5S.js → deferred-core-runtime-D2RF35BL.js} +29 -28
  167. package/chunks/{discovery-TUM3ZQ6U.js → discovery-XP4RMDUM.js} +4 -2
  168. package/chunks/{dist-P6YWBITG.js → dist-6YDUH3BB.js} +817 -152
  169. package/chunks/{dist-T4PRA5EZ.js → dist-BNQVF565.js} +2 -8
  170. package/chunks/{dist-AI25RVRA.js → dist-F34J4FZX.js} +1 -1
  171. package/chunks/{dist-3H3WODVS.js → dist-F6JLAJLE.js} +1 -1
  172. package/chunks/{dist-NXW4DUUX.js → dist-K5GHMXIG.js} +2 -2
  173. package/chunks/{dist-YNQU4CKC.js → dist-NP7QKLVG.js} +2 -2
  174. package/chunks/{dist-VCAS67N5.js → dist-UFTFGI6I.js} +1 -1
  175. package/chunks/{dist-I74QLLQS.js → dist-XLV33CLY.js} +1 -2
  176. package/chunks/{dist-XINEKB5A.js → dist-ZDNJK74R.js} +3 -7
  177. package/chunks/{edit-WPVXLL3T.js → edit-4IBADZ3O.js} +20 -20
  178. package/chunks/{enter-worktree-5A6VW6BN.js → enter-worktree-YFTKHXHZ.js} +2 -2
  179. package/chunks/{enterPlanMode-JSODW7E2.js → enterPlanMode-YN3GPQU5.js} +20 -20
  180. package/chunks/{environment-5LLJ3I3W.js → environment-E272IJMF.js} +32 -31
  181. package/chunks/{errors-IQT3YZEP.js → errors-CVAH3RWQ.js} +31 -30
  182. package/chunks/{exit-worktree-QV7E7KP6.js → exit-worktree-NF2XEMES.js} +3 -3
  183. package/chunks/{exitPlanMode-DDVFYNW4.js → exitPlanMode-24J5IHGC.js} +20 -20
  184. package/chunks/{fast-path-PAUQQEVU.js → fast-path-M5IDBMXF.js} +4 -4
  185. package/chunks/{fast-path-settings-ISEJPRYE.js → fast-path-settings-SATXY3PD.js} +3 -3
  186. package/chunks/{glob-SQ7CTZ7F.js → glob-ERBD7JYP.js} +20 -20
  187. package/chunks/{goal-tools-UWZRCLQB.js → goal-tools-245ULLQT.js} +20 -20
  188. package/chunks/{handleAutoUpdate-RUPZZTSG.js → handleAutoUpdate-JDZHHZKK.js} +32 -31
  189. package/chunks/{i18n-SF5MPWEB.js → i18n-LA4D5IXM.js} +32 -29
  190. package/chunks/{image-gen-Q3RUTVKR.js → image-gen-XP4NNIYG.js} +4 -4
  191. package/chunks/{initializer-CK4WPYZG.js → initializer-SHPTSWUZ.js} +36 -35
  192. package/chunks/{installationInfo-IRPQEYRF.js → installationInfo-QEQEPB3G.js} +29 -28
  193. package/chunks/{list-E3PS3EBJ.js → list-IBHCQWTF.js} +39 -38
  194. package/chunks/{list-agents-I5TRH3J7.js → list-agents-EDPZCGKN.js} +5 -4
  195. package/chunks/{llm-JQKBOYAF.js → llm-JAWCQLA4.js} +81 -75
  196. package/chunks/{llm-content-generator-2QWGBW42.js → llm-content-generator-GOV3A23T.js} +23 -8
  197. package/chunks/{loadedSettingsAdapter-DGXGVYZS.js → loadedSettingsAdapter-RVE2GNVU.js} +36 -35
  198. package/chunks/{loggingContentGenerator-ZYURLJKK.js → loggingContentGenerator-SSHNN5YW.js} +22 -22
  199. package/chunks/{managed-npm-update-HTHR63EA.js → managed-npm-update-BHSTITQO.js} +29 -28
  200. package/chunks/{mcp-I7G2AEWS.js → mcp-6ZZ7P2HU.js} +36 -35
  201. package/chunks/{monitor-4R76BCRZ.js → monitor-RKK6GSHG.js} +20 -20
  202. package/chunks/{nonInteractiveCli-24OQ3VP2.js → nonInteractiveCli-UQHP3G6P.js} +76 -72
  203. package/chunks/{notebook-edit-PPSH7FEX.js → notebook-edit-YM47A7WO.js} +20 -20
  204. package/chunks/{open-with-auth-D6JD6LDS.js → open-with-auth-6MVIHMXB.js} +1 -1
  205. package/chunks/{openaiContentGenerator-K7V5EO7F.js → openaiContentGenerator-FHKDWNI2.js} +11 -11
  206. package/chunks/{pidfile-TGIUY2GG.js → pidfile-SIIEJEEH.js} +32 -29
  207. package/chunks/{processUtils-3USXUQWX.js → processUtils-JF7CWBJC.js} +2 -2
  208. package/chunks/{prompt-terminal-ledger-XHVZRXJI.js → prompt-terminal-ledger-FXXHAEQU.js} +30 -29
  209. package/chunks/{qwenContentGenerator-MPBOQB64.js → qwenContentGenerator-KFJ77JP6.js} +24 -24
  210. package/chunks/{qwenOAuth2-BS5D2LYV.js → qwenOAuth2-KX6LVYQ3.js} +4 -4
  211. package/chunks/{read-file-R256LDWQ.js → read-file-S2NOCBIL.js} +4 -4
  212. package/chunks/{resumeHistoryUtils-S43LTFHD.js → resumeHistoryUtils-QHHPSQWU.js} +33 -32
  213. package/chunks/{ripGrep-L7HPZ75Y.js → ripGrep-F6TNOJUO.js} +5 -5
  214. package/chunks/{run-qwen-serve-CTFL5R6U.js → run-qwen-serve-KYBDQRDD.js} +229 -79
  215. package/chunks/{runtime-FS5TL6P7.js → runtime-3WNOFLCR.js} +43 -40
  216. package/chunks/{scheduled-tasks-QXPV3Q35.js → scheduled-tasks-RNBH56DJ.js} +34 -33
  217. package/chunks/{scheduler-EXU5HMVK.js → scheduler-ERMW7Q7B.js} +31 -30
  218. package/chunks/{send-message-GQKXGMPI.js → send-message-V5T3NMFM.js} +4 -4
  219. package/chunks/{serve-ITJC7WNN.js → serve-7NV46RMP.js} +36 -35
  220. package/chunks/{server-6JQY3PTU.js → server-6RZJR5QF.js} +1358 -932
  221. package/chunks/{session-PJDEKXD4.js → session-Z4EV7NVV.js} +107 -78
  222. package/chunks/{session-attachments-root-L37ORSST.js → session-attachments-root-SG5FC52X.js} +29 -28
  223. package/chunks/{session-pr-refresh-WIFD52YL.js → session-pr-refresh-ILC4Z3ZM.js} +33 -32
  224. package/chunks/{settings-LO6J5SAZ.js → settings-Y47SPE3X.js} +35 -34
  225. package/chunks/{shell-ANAFVYGR.js → shell-YBVCOPVO.js} +20 -20
  226. package/chunks/{skill-SHJWKSPH.js → skill-AXC63EBA.js} +4 -4
  227. package/chunks/{skill-settings-GX3XHZ5Q.js → skill-settings-AFPAYGLO.js} +35 -34
  228. package/chunks/{spawnChannel-WE42VBKM.js → spawnChannel-ZFL4J2V3.js} +29 -28
  229. package/chunks/{standalone-update-CWDIKJRP.js → standalone-update-Y2OZPLNJ.js} +31 -30
  230. package/chunks/{start-opentui-ui-BBHGFOTF.js → start-opentui-ui-G6TKT4LI.js} +2270 -1026
  231. package/chunks/{startInteractiveUI-FQX7LUYP.js → startInteractiveUI-YTNDPW7J.js} +1789 -2211
  232. package/chunks/{task-create-PMAFST2T.js → task-create-MWXJFRRM.js} +3 -3
  233. package/chunks/{task-list-R2HSY2NC.js → task-list-EYO3FE57.js} +2 -2
  234. package/chunks/{task-update-JYC57USF.js → task-update-2JJJRHMT.js} +3 -3
  235. package/chunks/{team-create-WKTPCH6D.js → team-create-BUFLGGSH.js} +20 -20
  236. package/chunks/{team-delete-CBHVBTPB.js → team-delete-IQZ6XGFI.js} +2 -2
  237. package/chunks/{team-plan-approval-Y23DL7WR.js → team-plan-approval-OUWWM42U.js} +20 -20
  238. package/chunks/{terminal-image-renderer-B646HBDW.js → terminal-image-renderer-WH2WV5ES.js} +29 -28
  239. package/chunks/{theme-manager-BNWESY26.js → theme-manager-5UDRARM2.js} +29 -28
  240. package/chunks/{tool-search-PVQ5O5Y2.js → tool-search-MCDIRPHN.js} +4 -4
  241. package/chunks/{total-session-admission-P5Z43KNW.js → total-session-admission-VL27U74Z.js} +33 -32
  242. package/chunks/{trustedFolders-FH2LT2MZ.js → trustedFolders-MSXT4VDD.js} +30 -29
  243. package/chunks/{update-relaunch-WOWTKJSN.js → update-relaunch-JKLEWVCB.js} +5 -5
  244. package/chunks/{updateCheck-3MYFMM35.js → updateCheck-ARTHAJT2.js} +31 -30
  245. package/chunks/{useAutoAcceptIndicator-Q7ZRRRKO.js → useAutoAcceptIndicator-YEAAGYVU.js} +38 -37
  246. package/chunks/{validateNonInterActiveAuth-MYEWJX3G.js → validateNonInterActiveAuth-EMRQKH5S.js} +71 -69
  247. package/chunks/{version-RO2FPO76.js → version-HFQU35WD.js} +3 -1
  248. package/chunks/{web-fetch-QAKY2LUA.js → web-fetch-QBXAO6VF.js} +7 -7
  249. package/chunks/{web-search-XA5Z4ZCD.js → web-search-2URQXA3A.js} +201 -13
  250. package/chunks/{web-shell-static-POZHGGXE.js → web-shell-static-BFDESDD4.js} +5 -4
  251. package/chunks/{workflow-QFIOCMDM.js → workflow-JDD6WDAH.js} +211 -75
  252. package/chunks/{workspace-providers-status-B2UD7RAG.js → workspace-providers-status-B4IKR6YJ.js} +38 -37
  253. package/chunks/{workspace-registration-store-VZLRTI3Q.js → workspace-registration-store-PJ3YHR45.js} +1 -2
  254. package/chunks/{workspace-registry-GYOGG6TM.js → workspace-registry-WVYJ5UGB.js} +33 -32
  255. package/chunks/{workspace-runtime-coordinator-7KRXGQ4V.js → workspace-runtime-coordinator-DXL5YVAG.js} +33 -32
  256. package/chunks/{workspace-service-DJEYGJE4.js → workspace-service-QNGAMVH7.js} +40 -39
  257. package/chunks/{workspace-skills-status-MOKNESUC.js → workspace-skills-status-BEISJIII.js} +36 -35
  258. package/chunks/{workspace-trust-reconciler-AXOSUTQW.js → workspace-trust-reconciler-ORYJF5L4.js} +40 -39
  259. package/chunks/{write-file-QOYVHAKK.js → write-file-DWLKFBTJ.js} +21 -21
  260. package/chunks/{zoom-image-UCCLGFNC.js → zoom-image-BYVIXSNQ.js} +4 -4
  261. package/cli.js +13 -13
  262. package/export-transcript-document.js +123 -119
  263. package/package.json +4 -4
  264. package/web-shell/assets/{abnfDiagram-VCTEODGH-CTstZpXw.js → abnfDiagram-VCTEODGH-C_8kzsly.js} +1 -1
  265. package/web-shell/assets/{arc-DKW0mbPo.js → arc-CDg7Zfpm.js} +1 -1
  266. package/web-shell/assets/{architectureDiagram-5GKGNRK7-DkMpJ42t.js → architectureDiagram-5GKGNRK7-DZzdCWyF.js} +1 -1
  267. package/web-shell/assets/{blockDiagram-NRAW4CY4-7Cp1_4i3.js → blockDiagram-NRAW4CY4-DI3B4gyR.js} +1 -1
  268. package/web-shell/assets/{c4Diagram-UCG6FXSJ-BfaoSlBK.js → c4Diagram-UCG6FXSJ-CfOgwHZW.js} +1 -1
  269. package/web-shell/assets/channel-e4xwS72w.js +1 -0
  270. package/web-shell/assets/{chunk-2Q5K7J3B-_n1qzAio.js → chunk-2Q5K7J3B-B_PUth0g.js} +1 -1
  271. package/web-shell/assets/{chunk-5VM5RSS4-0cira5ZV.js → chunk-5VM5RSS4-CrKtvBIL.js} +1 -1
  272. package/web-shell/assets/{chunk-F27PBJKO-DseRXSHC.js → chunk-F27PBJKO-B4z2n8Py.js} +1 -1
  273. package/web-shell/assets/{chunk-G27WJ6UU-BehQWin0.js → chunk-G27WJ6UU-BUtrFEO8.js} +1 -1
  274. package/web-shell/assets/{chunk-JWPE2WC7-B5ftg1Bb.js → chunk-JWPE2WC7-Cqw3aXW0.js} +1 -1
  275. package/web-shell/assets/{chunk-LCL6LL3I-D7rnbVdk.js → chunk-LCL6LL3I-CZolnvls.js} +1 -1
  276. package/web-shell/assets/{chunk-POPQ4Y6H-2Bp-Orju.js → chunk-POPQ4Y6H-DivgasCa.js} +1 -1
  277. package/web-shell/assets/{chunk-SVP7TREG-CD2goGva.js → chunk-SVP7TREG--seyb1B6.js} +1 -1
  278. package/web-shell/assets/{chunk-XXDRQBXY-DzQt-Rji.js → chunk-XXDRQBXY-D7pHtuVM.js} +1 -1
  279. package/web-shell/assets/classDiagram-DTDB5LWJ-CzXfUUOt.js +1 -0
  280. package/web-shell/assets/classDiagram-v2-JRS7N3AN-CzXfUUOt.js +1 -0
  281. package/web-shell/assets/{cose-bilkent-JH36ORCC-C-BZXSUn.js → cose-bilkent-JH36ORCC-4MWaRF_3.js} +1 -1
  282. package/web-shell/assets/csv-CX7rUNeC.svg +1 -0
  283. package/web-shell/assets/{cynefin-OW5HDTMX-BTcvowe1.js → cynefin-OW5HDTMX-nhJhAjgD.js} +1 -1
  284. package/web-shell/assets/{cynefinDiagram-5FMLGOSQ-BoUE6K81.js → cynefinDiagram-5FMLGOSQ-NF-PwXlq.js} +1 -1
  285. package/web-shell/assets/{dagre-3AP2YEHR-BHxy9xeB.js → dagre-3AP2YEHR-Bu0ncdWP.js} +1 -1
  286. package/web-shell/assets/{diagram-S7CK7UJ4-DMiJIvDT.js → diagram-S7CK7UJ4-CsvhFHZC.js} +1 -1
  287. package/web-shell/assets/{diagram-UQ7AKVKN-DXV09Aes.js → diagram-UQ7AKVKN-Ck61sIB3.js} +1 -1
  288. package/web-shell/assets/{diagram-VSXAHHWV-CocpRomV.js → diagram-VSXAHHWV-D0171zrb.js} +1 -1
  289. package/web-shell/assets/{diagram-VX7I27RA-DL7nqtb4.js → diagram-VX7I27RA-DvdxY4UL.js} +1 -1
  290. package/web-shell/assets/{diagram-Z3DM3KII-CPZ2Jux_.js → diagram-Z3DM3KII-CGGpseiB.js} +1 -1
  291. package/web-shell/assets/{ebnfDiagram-PWID7BFC-BX-eVNsX.js → ebnfDiagram-PWID7BFC-K8-QMvY8.js} +1 -1
  292. package/web-shell/assets/{erDiagram-SSCWMZ5O-CPy_Ir6y.js → erDiagram-SSCWMZ5O-D316nAem.js} +1 -1
  293. package/web-shell/assets/{flowDiagram-A5DVABFB-eknAOte9.js → flowDiagram-A5DVABFB-B7siy_mn.js} +1 -1
  294. package/web-shell/assets/{ganttDiagram-EL5Y4UJY-crAxw_t7.js → ganttDiagram-EL5Y4UJY-BZQDxzTu.js} +1 -1
  295. package/web-shell/assets/{gitGraphDiagram-WWUBYQGX-M29pa3Tc.js → gitGraphDiagram-WWUBYQGX-DZynLCSV.js} +1 -1
  296. package/web-shell/assets/{index-C9R-iojE.js → index-9ie6xLTM.js} +1 -1
  297. package/web-shell/assets/index-DirkXQEg.js +2164 -0
  298. package/web-shell/assets/index-DzdST_7L.css +36 -0
  299. package/web-shell/assets/{infoDiagram-RXCK75RN-XqspXdOU.js → infoDiagram-RXCK75RN-B0gr769A.js} +1 -1
  300. package/web-shell/assets/{ishikawaDiagram-5VMMS53U-C5KFS-7j.js → ishikawaDiagram-5VMMS53U-0pQFfjvX.js} +1 -1
  301. package/web-shell/assets/{journeyDiagram-EYS64GPL-Cc57LVRo.js → journeyDiagram-EYS64GPL-DEGtClWb.js} +1 -1
  302. package/web-shell/assets/{kanban-definition-3QL26DDD-C81OG-AI.js → kanban-definition-3QL26DDD-CnN8gPzw.js} +1 -1
  303. package/web-shell/assets/{layout-CFVu37BB.js → layout-C_70RhaT.js} +1 -1
  304. package/web-shell/assets/{linear-ChBxdtWf.js → linear-BJ2ZLmcq.js} +1 -1
  305. package/web-shell/assets/{mermaid.core-CMLfue0w.js → mermaid.core-RlY0zPNC.js} +6 -6
  306. package/web-shell/assets/{mindmap-definition-FBJOCRG2-DFsvJThp.js → mindmap-definition-FBJOCRG2-CpVAxTNl.js} +1 -1
  307. package/web-shell/assets/{pegDiagram-XKGWAZYB-BzpRzM4F.js → pegDiagram-XKGWAZYB-DmrSv3hD.js} +1 -1
  308. package/web-shell/assets/{pieDiagram-E7YTZNPT-Cv0Kankl.js → pieDiagram-E7YTZNPT-CJmgp8KJ.js} +1 -1
  309. package/web-shell/assets/{quadrantDiagram-AXDQQJYC-Bh2BJ3Ay.js → quadrantDiagram-AXDQQJYC-UsgOyNco.js} +1 -1
  310. package/web-shell/assets/{railroadDiagram-O6MQD6OU-y8rNDdDS.js → railroadDiagram-O6MQD6OU-DQ6gMs_W.js} +1 -1
  311. package/web-shell/assets/{requirementDiagram-EFPCY7ZU-C0m2DKJ_.js → requirementDiagram-EFPCY7ZU-DhqadamF.js} +1 -1
  312. package/web-shell/assets/{sankeyDiagram-P5KCCOFB-BzdGnSF4.js → sankeyDiagram-P5KCCOFB-R4WnURaE.js} +1 -1
  313. package/web-shell/assets/{sequenceDiagram-WJ2MYXX4-DPzAVmzz.js → sequenceDiagram-WJ2MYXX4-D7BwMi_D.js} +1 -1
  314. package/web-shell/assets/{sizeCapture-X5ZJPWSS-LcHG28Zh.js → sizeCapture-X5ZJPWSS-Bqngz088.js} +1 -1
  315. package/web-shell/assets/{stateDiagram-HBIQ2CUA-C1Bzy3IT.js → stateDiagram-HBIQ2CUA-DwaXPGqn.js} +1 -1
  316. package/web-shell/assets/stateDiagram-v2-4QOOHH4V-8GCQZAvv.js +1 -0
  317. package/web-shell/assets/{swimlanes-XN3QIQJK-Bftk8V64.js → swimlanes-XN3QIQJK-BsaLeRDY.js} +1 -1
  318. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-BoRBF2Yw.js +8 -0
  319. package/web-shell/assets/{timeline-definition-24CTP7MA-BfXHcN1A.js → timeline-definition-24CTP7MA-NJ9G-NUU.js} +1 -1
  320. package/web-shell/assets/{vennDiagram-4TSXK5OY-DRSlI9-V.js → vennDiagram-4TSXK5OY-Ca3W4rSq.js} +1 -1
  321. package/web-shell/assets/{wardleyDiagram-VM6X3IG4-CaLmqGau.js → wardleyDiagram-VM6X3IG4-OabvjC-6.js} +1 -1
  322. package/web-shell/assets/{xychartDiagram-S5SC5T6Z-8lgUT6e8.js → xychartDiagram-S5SC5T6Z-C7rbjvpc.js} +1 -1
  323. package/web-shell/index.html +2 -2
  324. package/chunks/chunk-2LD5U7Q3.js +0 -114
  325. package/chunks/chunk-3UMWOKJC.js +0 -78
  326. package/chunks/chunk-IQAFKVXS.js +0 -22
  327. package/chunks/chunk-X35VIWWJ.js +0 -276
  328. package/chunks/chunk-ZJ2LM2SI.js +0 -198
  329. package/web-shell/assets/channel-CQx7VSAp.js +0 -1
  330. package/web-shell/assets/classDiagram-DTDB5LWJ-C-Uz8hHk.js +0 -1
  331. package/web-shell/assets/classDiagram-v2-JRS7N3AN-C-Uz8hHk.js +0 -1
  332. package/web-shell/assets/index-B4TLaxWs.js +0 -2142
  333. package/web-shell/assets/index-CCrkEbzz.css +0 -36
  334. package/web-shell/assets/stateDiagram-v2-4QOOHH4V-LuuL5byY.js +0 -1
  335. package/web-shell/assets/swimlanesDiagram-VK2B7HYN-COmnNq8s.js +0 -8
@@ -14,7 +14,7 @@ import {
14
14
  sanitizePromptText,
15
15
  sanitizeSenderName,
16
16
  truncateUtf16Units
17
- } from "./chunk-65GHQ4FX.js";
17
+ } from "./chunk-WDVV3LRM.js";
18
18
  import "./chunk-IW6RQPQB.js";
19
19
  import "./chunk-CQ35AJ4Z.js";
20
20
  import "./chunk-DMTGGOSA.js";
@@ -38,7 +38,7 @@ init_esbuild_shims();
38
38
  // packages/channels/dingtalk/dist/DingtalkAdapter.js
39
39
  init_esbuild_shims();
40
40
  import { mkdirSync, rmSync, writeFileSync } from "node:fs";
41
- import { randomUUID as randomUUID5 } from "node:crypto";
41
+ import { randomUUID as randomUUID6 } from "node:crypto";
42
42
  import { basename as basename3, join } from "node:path";
43
43
  import { tmpdir as tmpdir3 } from "node:os";
44
44
  import { Buffer as Buffer2 } from "node:buffer";
@@ -6279,11 +6279,6 @@ function projectFileText(text) {
6279
6279
  return projector.result(safe);
6280
6280
  }
6281
6281
  __name(projectFileText, "projectFileText");
6282
- function withFileUnavailableNotice(text) {
6283
- const safe = text.trimEnd();
6284
- return `${safe}${safe ? "\n" : ""}${FILE_UNAVAILABLE_NOTICE}`;
6285
- }
6286
- __name(withFileUnavailableNotice, "withFileUnavailableNotice");
6287
6282
  function safeFileName(filePath) {
6288
6283
  return basename2(filePath).replace(/[\p{Cc}\p{Cf}[\]]+/gu, "_").slice(0, 200) || "file";
6289
6284
  }
@@ -6853,16 +6848,24 @@ function parseDingtalkInteractiveCardConfig(value) {
6853
6848
  const root = asRecord(value) ?? {};
6854
6849
  const status = asRecord(root["statusCard"]);
6855
6850
  const question = asRecord(root["questionCard"]);
6851
+ const permission = asRecord(root["permissionCard"]);
6856
6852
  if (root["statusCard"] !== void 0 && !status) {
6857
6853
  throw new Error("DingTalk interactiveCards.statusCard must be an object.");
6858
6854
  }
6859
6855
  if (root["questionCard"] !== void 0 && !question) {
6860
6856
  throw new Error("DingTalk interactiveCards.questionCard must be an object.");
6861
6857
  }
6862
- const timeoutMs = question?.["timeoutMs"] === void 0 ? DEFAULT_QUESTION_TIMEOUT_MS : question["timeoutMs"];
6863
- if (typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= DINGTALK_INTERACTIVE_CARD_TIMEOUT_EXCLUSIVE_MINIMUM) {
6858
+ if (root["permissionCard"] !== void 0 && !permission) {
6859
+ throw new Error("DingTalk interactiveCards.permissionCard must be an object.");
6860
+ }
6861
+ const questionTimeoutMs = question?.["timeoutMs"] === void 0 ? DEFAULT_QUESTION_TIMEOUT_MS : question["timeoutMs"];
6862
+ if (typeof questionTimeoutMs !== "number" || !Number.isFinite(questionTimeoutMs) || questionTimeoutMs <= DINGTALK_INTERACTIVE_CARD_TIMEOUT_EXCLUSIVE_MINIMUM) {
6864
6863
  throw new Error("DingTalk interactiveCards.questionCard.timeoutMs must be a finite positive number.");
6865
6864
  }
6865
+ const permissionTimeoutMs = permission?.["timeoutMs"] === void 0 ? DEFAULT_QUESTION_TIMEOUT_MS : permission["timeoutMs"];
6866
+ if (typeof permissionTimeoutMs !== "number" || !Number.isFinite(permissionTimeoutMs) || permissionTimeoutMs <= DINGTALK_INTERACTIVE_CARD_TIMEOUT_EXCLUSIVE_MINIMUM) {
6867
+ throw new Error("DingTalk interactiveCards.permissionCard.timeoutMs must be a finite positive number.");
6868
+ }
6866
6869
  return {
6867
6870
  enabled: optionalBoolean(root["enabled"], "enabled", configured),
6868
6871
  statusCard: {
@@ -6870,7 +6873,11 @@ function parseDingtalkInteractiveCardConfig(value) {
6870
6873
  },
6871
6874
  questionCard: {
6872
6875
  enabled: optionalBoolean(question?.["enabled"], "questionCard.enabled", true),
6873
- timeoutMs: Math.min(timeoutMs, DINGTALK_INTERACTIVE_CARD_TIMEOUT_MAXIMUM_MS)
6876
+ timeoutMs: Math.min(questionTimeoutMs, DINGTALK_INTERACTIVE_CARD_TIMEOUT_MAXIMUM_MS)
6877
+ },
6878
+ permissionCard: {
6879
+ enabled: optionalBoolean(permission?.["enabled"], "permissionCard.enabled", true),
6880
+ timeoutMs: Math.min(permissionTimeoutMs, DINGTALK_INTERACTIVE_CARD_TIMEOUT_MAXIMUM_MS)
6874
6881
  }
6875
6882
  };
6876
6883
  }
@@ -6933,6 +6940,95 @@ __name(parseDingtalkCardActorId, "parseDingtalkCardActorId");
6933
6940
  // packages/channels/dingtalk/dist/status-card-controller.js
6934
6941
  init_esbuild_shims();
6935
6942
  import { randomUUID as randomUUID2 } from "node:crypto";
6943
+
6944
+ // packages/channels/dingtalk/dist/presentation-phase.js
6945
+ init_esbuild_shims();
6946
+ var DINGTALK_PRESENTATION_PHASE_LABELS = {
6947
+ thinking: "\u{1F914} Thinking",
6948
+ reading: "\u{1F4D6} Reading",
6949
+ searching: "\u{1F50E} Searching",
6950
+ running: "\u{1F5A5}\uFE0F Running",
6951
+ editing: "\u{1F6E0}\uFE0F Editing",
6952
+ deleting: "\u{1F5D1}\uFE0F Deleting",
6953
+ moving: "\u{1F4E6} Moving",
6954
+ fetching: "\u{1F310} Fetching",
6955
+ switching: "\u{1F504} Switching mode",
6956
+ working: "\u{1F6E0}\uFE0F Working",
6957
+ failed: "\u26A0\uFE0F Tool failed",
6958
+ replying: "\u270D\uFE0F Replying"
6959
+ };
6960
+ var DINGTALK_ZH_PRESENTATION_PHASE_LABELS = {
6961
+ thinking: "\u{1F914} \u601D\u8003\u4E2D",
6962
+ reading: "\u{1F4D6} \u8BFB\u53D6\u4E2D",
6963
+ searching: "\u{1F50E} \u641C\u7D22\u4E2D",
6964
+ running: "\u{1F5A5}\uFE0F \u6267\u884C\u4E2D",
6965
+ editing: "\u{1F6E0}\uFE0F \u7F16\u8F91\u4E2D",
6966
+ deleting: "\u{1F5D1}\uFE0F \u5220\u9664\u4E2D",
6967
+ moving: "\u{1F4E6} \u79FB\u52A8\u4E2D",
6968
+ fetching: "\u{1F310} \u83B7\u53D6\u4E2D",
6969
+ switching: "\u{1F504} \u5207\u6362\u6A21\u5F0F\u4E2D",
6970
+ working: "\u{1F6E0}\uFE0F \u5904\u7406\u4E2D",
6971
+ failed: "\u26A0\uFE0F \u5DE5\u5177\u5931\u8D25",
6972
+ replying: "\u270D\uFE0F \u56DE\u590D\u4E2D"
6973
+ };
6974
+ function isChinesePresentationLanguage(language) {
6975
+ const normalized = language?.trim().toLowerCase().replaceAll("_", "-");
6976
+ return normalized === "zh" || normalized === "zh-cn";
6977
+ }
6978
+ __name(isChinesePresentationLanguage, "isChinesePresentationLanguage");
6979
+ function presentationPhaseLabel(phase, language) {
6980
+ return (isChinesePresentationLanguage(language) ? DINGTALK_ZH_PRESENTATION_PHASE_LABELS : DINGTALK_PRESENTATION_PHASE_LABELS)[phase];
6981
+ }
6982
+ __name(presentationPhaseLabel, "presentationPhaseLabel");
6983
+ function toolPresentationPhase(kind) {
6984
+ switch (kind.trim().toLowerCase()) {
6985
+ case "read":
6986
+ return "reading";
6987
+ case "edit":
6988
+ return "editing";
6989
+ case "delete":
6990
+ return "deleting";
6991
+ case "move":
6992
+ return "moving";
6993
+ case "search":
6994
+ return "searching";
6995
+ case "execute":
6996
+ return "running";
6997
+ case "think":
6998
+ return "thinking";
6999
+ case "fetch":
7000
+ return "fetching";
7001
+ case "switch_mode":
7002
+ return "switching";
7003
+ case "other":
7004
+ return "working";
7005
+ default:
7006
+ if (/read/iu.test(kind))
7007
+ return "reading";
7008
+ if (/search|browser|web/iu.test(kind))
7009
+ return "searching";
7010
+ if (/shell|exec|command|run/iu.test(kind))
7011
+ return "running";
7012
+ if (/edit|write|patch/iu.test(kind))
7013
+ return "editing";
7014
+ return "working";
7015
+ }
7016
+ }
7017
+ __name(toolPresentationPhase, "toolPresentationPhase");
7018
+ function lifecyclePresentationPhase(event) {
7019
+ if (event.type === "text_chunk")
7020
+ return "replying";
7021
+ if (event.type !== "tool_call")
7022
+ return void 0;
7023
+ if (/fail|error/iu.test(event.toolCall.status))
7024
+ return "failed";
7025
+ if (/complete|success/iu.test(event.toolCall.status))
7026
+ return "thinking";
7027
+ return toolPresentationPhase(event.toolCall.kind);
7028
+ }
7029
+ __name(lifecyclePresentationPhase, "lifecyclePresentationPhase");
7030
+
7031
+ // packages/channels/dingtalk/dist/status-card-controller.js
6936
7032
  var FLUSH_INTERVAL_MS = 500;
6937
7033
  var STATUS_REFRESH_INTERVAL_MS = 1e3;
6938
7034
  var CONTENT_SYNC_INTERVAL_SECONDS = 5;
@@ -6948,6 +7044,23 @@ function boundContent(content) {
6948
7044
  return `${TRUNCATION_MARKER}${content.slice(content.length - (CONTENT_LIMIT - TRUNCATION_MARKER.length))}`;
6949
7045
  }
6950
7046
  __name(boundContent, "boundContent");
7047
+ function activeContent(phase, content, language, sourcePrefix) {
7048
+ const label = presentationPhaseLabel(phase, language);
7049
+ const sanitized = sanitizeStreamingImageMarkers(content);
7050
+ const renderedSourcePrefix = sourcePrefix && (sanitized === sourcePrefix || sanitized.startsWith(`${sourcePrefix}
7051
+
7052
+ `)) ? sourcePrefix : void 0;
7053
+ const body = renderedSourcePrefix ? sanitized.slice(renderedSourcePrefix.length + (sanitized.length === renderedSourcePrefix.length ? 0 : 2)) : sanitized;
7054
+ const prefix = [label, renderedSourcePrefix].filter(Boolean).join("\n\n");
7055
+ if (!body)
7056
+ return prefix;
7057
+ const separator = "\n\n";
7058
+ const available = CONTENT_LIMIT - prefix.length - separator.length;
7059
+ if (body.length <= available)
7060
+ return `${prefix}${separator}${body}`;
7061
+ return `${prefix}${separator}${TRUNCATION_MARKER}${body.slice(body.length - (available - TRUNCATION_MARKER.length))}`;
7062
+ }
7063
+ __name(activeContent, "activeContent");
6951
7064
  var StatusCardController = class {
6952
7065
  static {
6953
7066
  __name(this, "StatusCardController");
@@ -7080,6 +7193,8 @@ var StatusCardController = class {
7080
7193
  target,
7081
7194
  outTrackId,
7082
7195
  content: boundContent(initialContent),
7196
+ ...segment.sourceLabel ? { sourcePrefix: escapeDingTalkMarkdown(segment.sourceLabel) } : {},
7197
+ phase: "thinking",
7083
7198
  startedAt: Date.now(),
7084
7199
  lastStatusSecond: 0,
7085
7200
  lastContentSyncSecond: 0,
@@ -7114,6 +7229,20 @@ var StatusCardController = class {
7114
7229
  complete(segmentId, text, retainedContent) {
7115
7230
  return this.finalize(segmentId, boundContent(text), "Completed", false, retainedContent);
7116
7231
  }
7232
+ updateRunPhase(runId, phase) {
7233
+ if (this.disposed)
7234
+ return;
7235
+ for (const segmentId of this.segmentIdsByRun.get(runId) ?? []) {
7236
+ const record = this.recordsBySegment.get(segmentId);
7237
+ if (!record || record.terminal || record.streamFailed || record.phase === phase) {
7238
+ continue;
7239
+ }
7240
+ record.phase = phase;
7241
+ record.contentVersion++;
7242
+ record.hasPendingWrite = true;
7243
+ this.scheduleFlush(record);
7244
+ }
7245
+ }
7117
7246
  fail(segmentId, error) {
7118
7247
  void this.finalize(segmentId, boundContent(error), "Failed", true);
7119
7248
  }
@@ -7169,9 +7298,9 @@ var StatusCardController = class {
7169
7298
  outTrackId: record.outTrackId,
7170
7299
  target,
7171
7300
  cardParamMap: {
7172
- content: sanitizeStreamingImageMarkers(record.content),
7301
+ content: activeContent(record.phase, record.content, this.options.language, record.sourcePrefix),
7173
7302
  flowStatus: 2,
7174
- statusLine: this.statusLine(record, "Running").text,
7303
+ statusLine: this.statusLine(record).text,
7175
7304
  hasAction: "true",
7176
7305
  stop_action: "true"
7177
7306
  }
@@ -7196,7 +7325,7 @@ var StatusCardController = class {
7196
7325
  await this.options.client.openOrUpdateStream({
7197
7326
  outTrackId: record.outTrackId,
7198
7327
  key: "content",
7199
- content: sanitizeStreamingImageMarkers(record.content),
7328
+ content: activeContent(record.phase, record.content, this.options.language, record.sourcePrefix),
7200
7329
  finalize: false
7201
7330
  });
7202
7331
  } catch (error) {
@@ -7245,7 +7374,7 @@ var StatusCardController = class {
7245
7374
  await this.options.client.openOrUpdateStream({
7246
7375
  outTrackId: record.outTrackId,
7247
7376
  key: "content",
7248
- content: sanitizeStreamingImageMarkers(record.content),
7377
+ content: activeContent(record.phase, record.content, this.options.language, record.sourcePrefix),
7249
7378
  finalize: false
7250
7379
  });
7251
7380
  contentWritten = true;
@@ -7448,14 +7577,28 @@ var StatusCardController = class {
7448
7577
  const second = Math.max(0, Math.floor((Date.now() - record.startedAt) / 1e3));
7449
7578
  const model = this.options.model?.trim();
7450
7579
  return {
7451
- text: [state, model, `${second}s`].filter(Boolean).join(" \xB7 "),
7580
+ text: [
7581
+ state ? this.statusStateLabel(state) : void 0,
7582
+ model,
7583
+ `${second}s`
7584
+ ].filter(Boolean).join(" \xB7 "),
7452
7585
  second
7453
7586
  };
7454
7587
  }
7588
+ statusStateLabel(state) {
7589
+ if (!isChinesePresentationLanguage(this.options.language))
7590
+ return state;
7591
+ return {
7592
+ Completed: "\u5DF2\u5B8C\u6210",
7593
+ Failed: "\u5DF2\u5931\u8D25",
7594
+ Stopped: "\u5DF2\u7EC8\u6B62",
7595
+ Cancelled: "\u5DF2\u53D6\u6D88"
7596
+ }[state] ?? state;
7597
+ }
7455
7598
  async updateRunningStatus(record) {
7456
7599
  if (this.disposed || record.terminal || record.streamFailed)
7457
7600
  return;
7458
- const status = this.statusLine(record, "Running");
7601
+ const status = this.statusLine(record);
7459
7602
  if (status.second === record.lastStatusSecond)
7460
7603
  return;
7461
7604
  const syncContent = status.second - record.lastContentSyncSecond >= CONTENT_SYNC_INTERVAL_SECONDS;
@@ -7463,7 +7606,9 @@ var StatusCardController = class {
7463
7606
  await this.options.client.updateInstance({
7464
7607
  outTrackId: record.outTrackId,
7465
7608
  cardParamMap: {
7466
- ...syncContent ? { content: sanitizeStreamingImageMarkers(record.content) } : {},
7609
+ ...syncContent ? {
7610
+ content: activeContent(record.phase, record.content, this.options.language, record.sourcePrefix)
7611
+ } : {},
7467
7612
  statusLine: status.text
7468
7613
  }
7469
7614
  });
@@ -7843,9 +7988,294 @@ ${text}`;
7843
7988
  }
7844
7989
  };
7845
7990
 
7846
- // packages/channels/dingtalk/dist/interaction-presenter.js
7991
+ // packages/channels/dingtalk/dist/permission-card-controller.js
7847
7992
  init_esbuild_shims();
7848
7993
  import { randomUUID as randomUUID4 } from "node:crypto";
7994
+ var DECISION_FIELD = "permission_decision";
7995
+ var PERMISSION_CARD_COPY = {
7996
+ en: {
7997
+ title: "Permission required",
7998
+ submit: "Submit",
7999
+ choose: "Choose how to continue",
8000
+ approved: { description: "Permission approved.", button: "Approved" },
8001
+ denied: { description: "Permission denied.", button: "Denied" },
8002
+ expired: {
8003
+ description: "This permission request is no longer available.",
8004
+ button: "Expired"
8005
+ },
8006
+ cancelled: {
8007
+ description: "Permission request cancelled.",
8008
+ button: "Cancelled"
8009
+ }
8010
+ },
8011
+ zh: {
8012
+ title: "\u9700\u8981\u6388\u6743",
8013
+ submit: "\u63D0\u4EA4",
8014
+ choose: "\u8BF7\u9009\u62E9\u540E\u7EED\u64CD\u4F5C",
8015
+ approved: { description: "\u5DF2\u6388\u6743\u3002", button: "\u5DF2\u6388\u6743" },
8016
+ denied: { description: "\u5DF2\u62D2\u7EDD\u6388\u6743\u3002", button: "\u5DF2\u62D2\u7EDD" },
8017
+ expired: { description: "\u6B64\u6388\u6743\u8BF7\u6C42\u5DF2\u5931\u6548\u3002", button: "\u5DF2\u5931\u6548" },
8018
+ cancelled: { description: "\u6388\u6743\u8BF7\u6C42\u5DF2\u53D6\u6D88\u3002", button: "\u5DF2\u53D6\u6D88" }
8019
+ }
8020
+ };
8021
+ var PermissionCardController = class {
8022
+ static {
8023
+ __name(this, "PermissionCardController");
8024
+ }
8025
+ options;
8026
+ byRequest = /* @__PURE__ */ new Map();
8027
+ byOutTrack = /* @__PURE__ */ new Map();
8028
+ pendingByRun = /* @__PURE__ */ new Map();
8029
+ constructor(options) {
8030
+ this.options = options;
8031
+ }
8032
+ async present(context, target) {
8033
+ const previous = this.byRequest.get(context.requestId);
8034
+ if (previous) {
8035
+ this.reserveTerminalProjection(previous);
8036
+ await this.finalize(previous, "expired");
8037
+ }
8038
+ const record = {
8039
+ context,
8040
+ target,
8041
+ outTrackId: `qwen-permission-${randomUUID4()}`,
8042
+ state: "reserved",
8043
+ delivered: false,
8044
+ forbiddenActors: /* @__PURE__ */ new Set()
8045
+ };
8046
+ this.byRequest.set(context.requestId, record);
8047
+ this.byOutTrack.set(record.outTrackId, record);
8048
+ const unsubscribe = context.onSettled((reason) => {
8049
+ if (record.state === "claimed")
8050
+ return;
8051
+ if (record.state === "pending")
8052
+ this.reserveTerminalProjection(record);
8053
+ void this.finalize(record, reason === "resolved_outside_presenter" ? "expired" : "cancelled");
8054
+ });
8055
+ record.unsubscribe = unsubscribe;
8056
+ if (record.state === "terminal")
8057
+ unsubscribe();
8058
+ try {
8059
+ await this.options.client.createAndDeliver({
8060
+ templateId: QUESTION_CARD_TEMPLATE_ID,
8061
+ outTrackId: record.outTrackId,
8062
+ target,
8063
+ cardParamMap: this.cardData(context)
8064
+ });
8065
+ record.delivered = true;
8066
+ } catch (error) {
8067
+ this.options.onError?.("permission card creation", error);
8068
+ if (record.state === "terminal")
8069
+ return { kind: "presented" };
8070
+ this.discard(record);
8071
+ return { kind: "unsupported" };
8072
+ }
8073
+ if (record.state !== "reserved") {
8074
+ await this.projectTerminal(record);
8075
+ return { kind: "presented" };
8076
+ }
8077
+ record.state = "pending";
8078
+ const pending = this.pendingByRun.get(context.runId) ?? /* @__PURE__ */ new Set();
8079
+ pending.add(context.requestId);
8080
+ this.pendingByRun.set(context.runId, pending);
8081
+ record.timer = setTimeout(() => {
8082
+ void this.expire(record);
8083
+ }, this.options.timeoutMs);
8084
+ record.timer.unref?.();
8085
+ return { kind: "presented" };
8086
+ }
8087
+ claim(callback) {
8088
+ const record = this.byOutTrack.get(callback.outTrackId);
8089
+ if (!record || record.state !== "pending") {
8090
+ return { kind: "ignored", actorId: callback.actorId };
8091
+ }
8092
+ if (record.context.owner.id !== callback.actorId) {
8093
+ if (record.forbiddenActors.has(callback.actorId)) {
8094
+ return { kind: "ignored" };
8095
+ }
8096
+ record.forbiddenActors.add(callback.actorId);
8097
+ return {
8098
+ kind: "forbidden",
8099
+ actorId: callback.actorId,
8100
+ target: record.target
8101
+ };
8102
+ }
8103
+ if (callback.hasBusinessPayload === false || !callback.isCancel && callback.actionId !== "cancel" && callback.actionId !== "submit" && callback.actionId !== record.context.requestId) {
8104
+ return { kind: "ignored", actorId: callback.actorId };
8105
+ }
8106
+ if (callback.isCancel || callback.actionId === "cancel") {
8107
+ this.reserveTerminalProjection(record);
8108
+ record.state = "claimed";
8109
+ return {
8110
+ kind: "accepted",
8111
+ execute: /* @__PURE__ */ __name(() => this.respond(record, "deny", "cancelled"), "execute")
8112
+ };
8113
+ }
8114
+ const decision = this.parseDecision(record, callback.formData);
8115
+ if (!decision)
8116
+ return { kind: "ignored", actorId: callback.actorId };
8117
+ this.reserveTerminalProjection(record);
8118
+ record.state = "claimed";
8119
+ return {
8120
+ kind: "accepted",
8121
+ execute: /* @__PURE__ */ __name(() => this.respond(record, decision), "execute")
8122
+ };
8123
+ }
8124
+ cancelRun(runId) {
8125
+ const requestIds = [...this.pendingByRun.get(runId) ?? []];
8126
+ for (const requestId of requestIds) {
8127
+ const record = this.byRequest.get(requestId);
8128
+ if (record) {
8129
+ this.reserveTerminalProjection(record);
8130
+ void this.finalize(record, "cancelled");
8131
+ }
8132
+ }
8133
+ }
8134
+ async respond(record, decision, terminalState) {
8135
+ try {
8136
+ const accepted = await record.context.respond(decision);
8137
+ await this.finalize(record, accepted ? terminalState ?? (decision === "deny" ? "denied" : "approved") : "expired");
8138
+ } catch (error) {
8139
+ this.options.onError?.("permission response", error);
8140
+ await this.finalize(record, "expired");
8141
+ }
8142
+ }
8143
+ async expire(record) {
8144
+ if (record.state !== "pending")
8145
+ return;
8146
+ this.reserveTerminalProjection(record);
8147
+ record.state = "claimed";
8148
+ const response = record.context.respond("deny").catch((error) => {
8149
+ this.options.onError?.("expired permission cancellation", error);
8150
+ });
8151
+ await this.finalize(record, "expired");
8152
+ await response;
8153
+ }
8154
+ async finalize(record, terminalState) {
8155
+ if (record.state === "terminal")
8156
+ return;
8157
+ record.state = "terminal";
8158
+ record.terminalState = terminalState;
8159
+ this.removeRecord(record);
8160
+ if (!record.delivered)
8161
+ return;
8162
+ const finishTerminalProjection = record.finishTerminalProjection;
8163
+ record.finishTerminalProjection = void 0;
8164
+ if (finishTerminalProjection) {
8165
+ await finishTerminalProjection(() => this.projectTerminal(record));
8166
+ } else {
8167
+ await this.projectTerminal(record);
8168
+ }
8169
+ }
8170
+ discard(record) {
8171
+ if (record.state === "terminal")
8172
+ return;
8173
+ record.state = "terminal";
8174
+ this.removeRecord(record);
8175
+ }
8176
+ removeRecord(record) {
8177
+ if (record.timer)
8178
+ clearTimeout(record.timer);
8179
+ record.timer = void 0;
8180
+ record.unsubscribe?.();
8181
+ record.unsubscribe = void 0;
8182
+ this.byRequest.delete(record.context.requestId);
8183
+ this.byOutTrack.delete(record.outTrackId);
8184
+ const pending = this.pendingByRun.get(record.context.runId);
8185
+ pending?.delete(record.context.requestId);
8186
+ if (pending?.size === 0)
8187
+ this.pendingByRun.delete(record.context.runId);
8188
+ }
8189
+ reserveTerminalProjection(record) {
8190
+ record.finishTerminalProjection ??= this.options.reserveRunProjection?.(record.context.runId);
8191
+ }
8192
+ async projectTerminal(record) {
8193
+ if (!record.terminalState)
8194
+ return;
8195
+ const copy = PERMISSION_CARD_COPY[this.options.locale ?? "en"];
8196
+ const cardParamMap = {
8197
+ approved: {
8198
+ card_status: "approved",
8199
+ question_desc: copy.approved.description,
8200
+ form_btn_text: copy.approved.button
8201
+ },
8202
+ denied: {
8203
+ card_status: "denied",
8204
+ question_desc: copy.denied.description,
8205
+ form_btn_text: copy.denied.button
8206
+ },
8207
+ expired: {
8208
+ card_status: "expired",
8209
+ question_desc: copy.expired.description,
8210
+ form_btn_text: copy.expired.button
8211
+ },
8212
+ cancelled: {
8213
+ card_status: "cancelled",
8214
+ question_desc: copy.cancelled.description,
8215
+ form_btn_text: copy.cancelled.button
8216
+ }
8217
+ };
8218
+ try {
8219
+ await this.options.client.updateInstance({
8220
+ outTrackId: record.outTrackId,
8221
+ cardParamMap: cardParamMap[record.terminalState]
8222
+ });
8223
+ } catch (error) {
8224
+ this.options.onError?.("permission card finalization", error);
8225
+ }
8226
+ }
8227
+ parseDecision(record, formData) {
8228
+ if (Object.keys(formData).length !== 1 || !Object.prototype.hasOwnProperty.call(formData, DECISION_FIELD)) {
8229
+ return void 0;
8230
+ }
8231
+ const values = this.readValues(formData[DECISION_FIELD]);
8232
+ if (values.length !== 1)
8233
+ return void 0;
8234
+ const decision = values[0];
8235
+ return record.context.decisions.some((candidate) => candidate.kind === decision) ? decision : void 0;
8236
+ }
8237
+ readValues(value) {
8238
+ if (typeof value === "string")
8239
+ return value.trim() ? [value.trim()] : [];
8240
+ if (Array.isArray(value)) {
8241
+ return value.filter((item) => typeof item === "string").map((item) => item.trim()).filter(Boolean);
8242
+ }
8243
+ if (value !== null && typeof value === "object") {
8244
+ return this.readValues(value["value"]);
8245
+ }
8246
+ return [];
8247
+ }
8248
+ cardData(context) {
8249
+ const copy = PERMISSION_CARD_COPY[this.options.locale ?? "en"];
8250
+ return {
8251
+ question_id: context.requestId,
8252
+ question_title: copy.title,
8253
+ question_desc: context.title,
8254
+ card_status: "pending",
8255
+ form_btn_text: copy.submit,
8256
+ selected_text: "",
8257
+ selected_values: "[]",
8258
+ form: {
8259
+ fields: [
8260
+ {
8261
+ name: DECISION_FIELD,
8262
+ label: copy.choose,
8263
+ type: "CHECKBOX_GROUP",
8264
+ required: true,
8265
+ options: context.decisions.map((decision) => ({
8266
+ value: decision.kind,
8267
+ text: decision.label
8268
+ }))
8269
+ }
8270
+ ]
8271
+ }
8272
+ };
8273
+ }
8274
+ };
8275
+
8276
+ // packages/channels/dingtalk/dist/interaction-presenter.js
8277
+ init_esbuild_shims();
8278
+ import { randomUUID as randomUUID5 } from "node:crypto";
7849
8279
  function escapeSenderMarkdownText(text) {
7850
8280
  return text.replace(/([\\`*_[\]{}()#+.!|>~-])/gu, "\\$1");
7851
8281
  }
@@ -7905,6 +8335,12 @@ var DingtalkInteractionPresenter = class {
7905
8335
  statusCards?.replace(statusContext, target, this.withSourcePrefix(run, ""));
7906
8336
  });
7907
8337
  }
8338
+ updateStatusCardPhase(runId, phase) {
8339
+ const run = this.runs.get(runId);
8340
+ if (!run || run.terminal)
8341
+ return;
8342
+ void this.enqueue(run, () => this.options.statusCards?.updateRunPhase(runId, phase));
8343
+ }
7908
8344
  appendOutput(segment, chunk) {
7909
8345
  const run = this.runs.get(segment.runId);
7910
8346
  if (!run || run.terminal || run.ownerId !== segment.owner.id || run.target.chatId !== segment.target.chatId || run.target.isGroup !== segment.target.isGroup || !chunk || this.terminalSegmentIds.has(segment.segmentId)) {
@@ -8005,11 +8441,36 @@ var DingtalkInteractionPresenter = class {
8005
8441
  return Promise.resolve({ kind: "unsupported" });
8006
8442
  return questionCards.present(context, this.cardTarget(context.target));
8007
8443
  }
8444
+ presentPermission(context) {
8445
+ const run = this.runs.get(context.runId);
8446
+ if (!run || run.terminal || run.ownerId !== context.owner.id || run.target.chatId !== context.target.chatId || run.target.isGroup !== context.target.isGroup) {
8447
+ return Promise.resolve({ kind: "unsupported" });
8448
+ }
8449
+ const permissionCards = this.options.permissionCards;
8450
+ if (!permissionCards)
8451
+ return Promise.resolve({ kind: "unsupported" });
8452
+ return permissionCards.present(context, this.cardTarget(context.target));
8453
+ }
8454
+ terminalCopy() {
8455
+ if (this.options.language !== void 0 && !isChinesePresentationLanguage(this.options.language)) {
8456
+ return {
8457
+ failed: "Processing failed, please try again later.",
8458
+ stopped: "Task stopped",
8459
+ cancelled: "Task cancelled"
8460
+ };
8461
+ }
8462
+ return {
8463
+ failed: "\u672C\u6B21\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002",
8464
+ stopped: "\u4EFB\u52A1\u5DF2\u505C\u6B62",
8465
+ cancelled: "\u4EFB\u52A1\u5DF2\u53D6\u6D88"
8466
+ };
8467
+ }
8008
8468
  terminalizeRun(runId, terminal, detail = "") {
8009
8469
  const run = this.runs.get(runId);
8010
8470
  if (!run || run.terminal)
8011
8471
  return;
8012
8472
  this.options.questionCards?.cancelRun(runId, terminal === "cancelled" && (detail === "cancel_command" || detail === "clear") ? "cancelled" : "expired");
8473
+ this.options.permissionCards?.cancelRun(runId);
8013
8474
  run.terminal = true;
8014
8475
  const activeSegmentId = run.activeSegmentId;
8015
8476
  run.activeSegmentId = void 0;
@@ -8017,16 +8478,17 @@ var DingtalkInteractionPresenter = class {
8017
8478
  this.segments.delete(activeSegmentId);
8018
8479
  this.addTerminalSegment(activeSegmentId);
8019
8480
  }
8481
+ const copy = this.terminalCopy();
8020
8482
  const finalization = this.enqueue(run, async () => {
8021
8483
  if (terminal === "failed") {
8022
8484
  const statusContext = this.ensureStatusContext(run);
8023
8485
  this.options.statusCards?.ensure(statusContext, this.cardTarget(statusContext.target));
8024
- this.options.statusCards?.fail(statusContext.segmentId, this.withSenderPrefix(run, "\u672C\u6B21\u5904\u7406\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"));
8486
+ this.options.statusCards?.fail(statusContext.segmentId, this.withSenderPrefix(run, copy.failed));
8025
8487
  await this.redeliverCardDeliveredContent(run);
8026
8488
  } else if (terminal === "cancelled") {
8027
8489
  const statusContext = run.statusContext;
8028
8490
  if (statusContext) {
8029
- this.options.statusCards?.replace(statusContext, this.cardTarget(statusContext.target), this.withSenderPrefix(run, detail === "cancel_command" ? "\u4EFB\u52A1\u5DF2\u505C\u6B62" : "\u4EFB\u52A1\u5DF2\u53D6\u6D88"));
8491
+ this.options.statusCards?.replace(statusContext, this.cardTarget(statusContext.target), this.withSenderPrefix(run, detail === "cancel_command" ? copy.stopped : copy.cancelled));
8030
8492
  }
8031
8493
  this.options.statusCards?.cancelRun(runId, detail === "cancel_command" ? "cancel_command" : "dropped");
8032
8494
  await this.redeliverCardDeliveredContent(run);
@@ -8164,7 +8626,7 @@ ${this.boundContent(content, Math.max(0, CONTENT_LIMIT - sourceLabel.length - 2)
8164
8626
  ensureStatusContext(run, segment) {
8165
8627
  if (run.statusContext)
8166
8628
  return run.statusContext;
8167
- run.statusContext = segment ? { ...segment } : { ...run.baseContext, segmentId: `${run.runId}:${randomUUID4()}` };
8629
+ run.statusContext = segment ? { ...segment } : { ...run.baseContext, segmentId: `${run.runId}:${randomUUID5()}` };
8168
8630
  return run.statusContext;
8169
8631
  }
8170
8632
  cardTarget(target) {
@@ -8388,9 +8850,15 @@ var BACKGROUND_RESPONSE_AGGREGATION_MAX_RETRIES = 3;
8388
8850
  var ACK_REACTION_NAME = "\u{1F440}";
8389
8851
  var ACK_EMOTION_ID = "2659900";
8390
8852
  var ACK_EMOTION_BG_ID = "im_bg_1";
8853
+ var STATUS_EMOTION_ID = "34019";
8854
+ var STATUS_EMOTION_BG_ID = "im_bg_6";
8855
+ var DONE_EMOTION_ID = "54054";
8856
+ var DONE_EMOTION_BG_ID = "im_bg_5";
8391
8857
  var EMOTION_API = "https://api.dingtalk.com/v1.0/robot/emotion";
8392
8858
  var EMOTION_MAX_ATTEMPTS = 3;
8393
8859
  var EMOTION_RETRY_BASE_DELAY_MS = 250;
8860
+ var EMOTION_FETCH_TIMEOUT_MS = 15e3;
8861
+ var EMOTION_FINISH_MAX_ATTEMPTS = 3;
8394
8862
  var GROUP_MSG_API = "https://api.dingtalk.com/v1.0/robot/groupMessages/send";
8395
8863
  var DIRECT_MSG_API = "https://api.dingtalk.com/v1.0/robot/oToMessages/batchSend";
8396
8864
  var PROACTIVE_MSG_KEY = "sampleMarkdown";
@@ -8518,6 +8986,26 @@ var FILE_INSTRUCTIONS = [
8518
8986
  "File paths containing ] are not supported.",
8519
8987
  "Do not claim delivery succeeded; DingTalk shows successful files separately and reports failures in the final text."
8520
8988
  ].join("\n");
8989
+ function statusEmotionTag(name) {
8990
+ return {
8991
+ name,
8992
+ emotionId: STATUS_EMOTION_ID,
8993
+ backgroundId: STATUS_EMOTION_BG_ID
8994
+ };
8995
+ }
8996
+ __name(statusEmotionTag, "statusEmotionTag");
8997
+ var EYE_TAG = {
8998
+ name: ACK_REACTION_NAME,
8999
+ emotionId: ACK_EMOTION_ID,
9000
+ backgroundId: ACK_EMOTION_BG_ID
9001
+ };
9002
+ var DONE_TAG = {
9003
+ name: "\u2705 Done",
9004
+ emotionId: DONE_EMOTION_ID,
9005
+ backgroundId: DONE_EMOTION_BG_ID
9006
+ };
9007
+ var FAILED_TAG = statusEmotionTag("\u274C Failed");
9008
+ var STOPPED_TAG = statusEmotionTag("\u23F9\uFE0F Stopped");
8521
9009
  function collectNonBotMentionIds(data) {
8522
9010
  if (!Array.isArray(data.atUsers) || typeof data.chatbotUserId !== "string") {
8523
9011
  return [];
@@ -8585,6 +9073,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8585
9073
  }
8586
9074
  client;
8587
9075
  atSender;
9076
+ displayLanguage;
8588
9077
  connectionManager;
8589
9078
  seenMessages = /* @__PURE__ */ new Map();
8590
9079
  mentionTargets = /* @__PURE__ */ new Map();
@@ -8595,8 +9084,11 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8595
9084
  /** Map conversationId → latest sessionWebhook URL for sending replies. */
8596
9085
  webhooks = /* @__PURE__ */ new Map();
8597
9086
  activeReactionKeys = /* @__PURE__ */ new Set();
9087
+ reactionStates = /* @__PURE__ */ new Map();
8598
9088
  /** sessionId → reaction keys, so a dead session's reactions can be recalled. */
8599
9089
  sessionReactionKeys = /* @__PURE__ */ new Map();
9090
+ /** Settles when the reaction cleanup queued by disconnect() has run. */
9091
+ disconnectDrain;
8600
9092
  /**
8601
9093
  * Real inbound message ids (insertion-ordered, size-capped). Unlike the
8602
9094
  * TTL-swept seenMessages dedup map, entries survive long queue waits, so a
@@ -8613,6 +9105,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8613
9105
  interactiveCardClient;
8614
9106
  statusCardController;
8615
9107
  questionCardController;
9108
+ permissionCardController;
8616
9109
  interactionPresenter;
8617
9110
  inboundCardOwners = /* @__PURE__ */ new Map();
8618
9111
  cardRunBySession = /* @__PURE__ */ new Map();
@@ -8621,14 +9114,6 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8621
9114
  // boundary, input requested) mints a fresh segment UUID but the projection
8622
9115
  // state must survive it, or a marker split across the reset leaks.
8623
9116
  fileProjectors = /* @__PURE__ */ new Map();
8624
- blockFileProjectors = /* @__PURE__ */ new Map();
8625
- // Sessions armed for block projection by onPromptStart and disarmed when
8626
- // the turn settles (or the session dies). A block send that finds NO
8627
- // projector state is only legitimate as a turn's FIRST block, which always
8628
- // lands while armed: late sends from an evicted (/clear) or dead session
8629
- // must be dropped, because recreating state would post the tail of a
8630
- // force-split [FILE: ...] marker verbatim.
8631
- blockProjectionArmed = /* @__PURE__ */ new Set();
8632
9117
  backgroundResponseAggregations = /* @__PURE__ */ new Map();
8633
9118
  detachedBackgroundResponseAggregations = /* @__PURE__ */ new Set();
8634
9119
  pendingBackgroundResponseTerminals = /* @__PURE__ */ new Map();
@@ -8636,6 +9121,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8636
9121
  constructor(name, config, bridge, options) {
8637
9122
  super(name, config, bridge, options);
8638
9123
  this.atSender = config["atSender"] === true;
9124
+ this.displayLanguage = options?.displayLanguage;
8639
9125
  if (!this.config.instructions) {
8640
9126
  this.config.instructions = [
8641
9127
  "## DingTalk Channel",
@@ -8646,7 +9132,7 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8646
9132
  } else if (!this.config.instructions.includes("[IMAGE:")) {
8647
9133
  this.config.instructions += IMAGE_INSTRUCTIONS;
8648
9134
  }
8649
- if (config.blockStreaming !== "on" && !this.config.instructions.includes("[FILE:")) {
9135
+ if (!this.config.instructions.includes("[FILE:")) {
8650
9136
  this.config.instructions += FILE_INSTRUCTIONS;
8651
9137
  }
8652
9138
  this.interactiveCardConfig = parseDingtalkInteractiveCardConfig(config.interactiveCards);
@@ -8674,11 +9160,12 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8674
9160
  }
8675
9161
  }, "invalidateAccessToken")
8676
9162
  });
8677
- if (this.interactiveCardConfig.statusCard.enabled && config.blockStreaming !== "on") {
9163
+ if (this.interactiveCardConfig.statusCard.enabled) {
8678
9164
  this.statusCardController = new StatusCardController({
8679
9165
  client: this.interactiveCardClient,
8680
9166
  cancelRun: /* @__PURE__ */ __name((sessionId, runId) => this.requestPromptRunCancellation(sessionId, runId), "cancelRun"),
8681
9167
  ...config.model ? { model: config.model } : {},
9168
+ ...options?.displayLanguage ? { language: options.displayLanguage } : {},
8682
9169
  onError: /* @__PURE__ */ __name((operation, error) => {
8683
9170
  process.stderr.write(`[DingTalk:${this.name}] ${operation} failed: ${sanitizeLogText(String(error), 300)}
8684
9171
  `);
@@ -8697,13 +9184,25 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8697
9184
  }, "onError")
8698
9185
  });
8699
9186
  }
8700
- if (this.statusCardController || this.questionCardController) {
9187
+ if (this.interactiveCardConfig.permissionCard.enabled) {
9188
+ this.permissionCardController = new PermissionCardController({
9189
+ client: this.interactiveCardClient,
9190
+ timeoutMs: this.interactiveCardConfig.permissionCard.timeoutMs,
9191
+ locale: this.locale,
9192
+ reserveRunProjection: /* @__PURE__ */ __name((runId) => this.interactionPresenter?.reserveProjection(runId), "reserveRunProjection"),
9193
+ onError: /* @__PURE__ */ __name((operation, error) => {
9194
+ process.stderr.write(`[DingTalk:${this.name}] ${operation} failed: ${sanitizeLogText(String(error), 300)}
9195
+ `);
9196
+ }, "onError")
9197
+ });
9198
+ }
9199
+ if (this.statusCardController || this.questionCardController || this.permissionCardController) {
8701
9200
  this.interactionPresenter = new DingtalkInteractionPresenter({
8702
9201
  statusCards: this.statusCardController,
8703
9202
  questionCards: this.questionCardController,
8704
- ...config.blockStreaming !== "on" ? {
8705
- sendFallback: /* @__PURE__ */ __name((chatId, text, sessionId, sourceLabel) => this.sendFallbackReply(chatId, text, sessionId, sourceLabel), "sendFallback")
8706
- } : {}
9203
+ permissionCards: this.permissionCardController,
9204
+ ...options?.displayLanguage ? { language: options.displayLanguage } : {},
9205
+ sendFallback: /* @__PURE__ */ __name((chatId, text, sessionId, sourceLabel) => this.sendFallbackReply(chatId, text, sessionId, sourceLabel), "sendFallback")
8707
9206
  });
8708
9207
  }
8709
9208
  }
@@ -8787,7 +9286,11 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8787
9286
  if (callback.actionId === "btn_stop") {
8788
9287
  return this.statusCardController?.claimStop(callback.outTrackId, callback.actorId) ?? { kind: "ignored", actorId: callback.actorId };
8789
9288
  }
8790
- return this.questionCardController?.claim(callback) ?? {
9289
+ const permissionResult = this.permissionCardController?.claim(callback);
9290
+ if (permissionResult && permissionResult.kind !== "ignored") {
9291
+ return permissionResult;
9292
+ }
9293
+ return this.questionCardController?.claim(callback) ?? permissionResult ?? {
8791
9294
  kind: "ignored",
8792
9295
  actorId: callback.actorId
8793
9296
  };
@@ -8999,9 +9502,6 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
8999
9502
  process.stderr.write(`[DingTalk:${this.name}] file markers projected (final=${projection.markerCount}, streamed=${streamedMarkers})
9000
9503
  `);
9001
9504
  }
9002
- if (this.config.blockStreaming === "on" && (projection.markerCount > 0 || streamedMarkers > 0)) {
9003
- return this.prepareOutgoingText(withFileUnavailableNotice(projection.text));
9004
- }
9005
9505
  const notices = [];
9006
9506
  if (projection.invalidMarkers > 0) {
9007
9507
  notices.push("[File delivery failed: invalid marker]");
@@ -9240,20 +9740,29 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9240
9740
  return data.access_token;
9241
9741
  }
9242
9742
  sendCardInteractionFeedback(actorId, target) {
9743
+ const copy = this.locale === "zh" ? {
9744
+ title: "\u5361\u7247\u64CD\u4F5C",
9745
+ group: "\u4EC5\u4EFB\u52A1\u53D1\u8D77\u4EBA\u53EF\u4EE5\u64CD\u4F5C\u8FD9\u5F20\u5361\u7247\uFF0C\u672C\u6B21\u64CD\u4F5C\u672A\u751F\u6548\u3002",
9746
+ direct: "\u4F60\u65E0\u6743\u64CD\u4F5C\u8FD9\u5F20\u5361\u7247\uFF0C\u4EC5\u4EFB\u52A1\u53D1\u8D77\u4EBA\u53EF\u4EE5\u63D0\u4EA4\u6216\u505C\u6B62\u3002"
9747
+ } : {
9748
+ title: "Card interaction",
9749
+ group: "Only the task initiator can operate this card. This action had no effect.",
9750
+ direct: "You cannot operate this card. Only the task initiator can submit or stop it."
9751
+ };
9243
9752
  if (target?.isGroup) {
9244
9753
  return this.sendProactiveChunk({
9245
9754
  channelName: this.name,
9246
9755
  senderId: actorId,
9247
9756
  chatId: target.chatId,
9248
9757
  isGroup: true
9249
- }, "\u5361\u7247\u64CD\u4F5C", "\u4EC5\u4EFB\u52A1\u53D1\u8D77\u4EBA\u53EF\u4EE5\u64CD\u4F5C\u8FD9\u5F20\u5361\u7247\uFF0C\u672C\u6B21\u64CD\u4F5C\u672A\u751F\u6548\u3002", "card interaction feedback");
9758
+ }, copy.title, copy.group, "card interaction feedback");
9250
9759
  }
9251
9760
  return this.sendProactiveChunk({
9252
9761
  channelName: this.name,
9253
9762
  senderId: actorId,
9254
9763
  chatId: actorId,
9255
9764
  isGroup: false
9256
- }, "\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");
9765
+ }, copy.title, copy.direct, "card interaction feedback");
9257
9766
  }
9258
9767
  async sendProactiveChunk(target, title, text, chunkLabel) {
9259
9768
  return this.sendProactivePayload(target, PROACTIVE_MSG_KEY, { title, text }, chunkLabel);
@@ -9351,14 +9860,14 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9351
9860
  getAccessToken() {
9352
9861
  return this.client.getConfig().access_token;
9353
9862
  }
9354
- async emotionApi(endpoint, msgId, conversationId) {
9863
+ async emotionApi(endpoint, msgId, conversationId, tag) {
9355
9864
  const robotCode = this.config.clientId;
9356
9865
  if (!robotCode || !msgId || !conversationId)
9357
- return;
9866
+ return false;
9358
9867
  try {
9359
9868
  const token = this.config.clientSecret ? await this.getProactiveToken() : this.getAccessToken();
9360
9869
  if (!token)
9361
- return;
9870
+ return false;
9362
9871
  for (let attempt = 0; attempt < EMOTION_MAX_ATTEMPTS; attempt++) {
9363
9872
  const resp = await fetch(`${EMOTION_API}/${endpoint}`, {
9364
9873
  method: "POST",
@@ -9371,17 +9880,18 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9371
9880
  openMsgId: msgId,
9372
9881
  openConversationId: conversationId,
9373
9882
  emotionType: 2,
9374
- emotionName: ACK_REACTION_NAME,
9883
+ emotionName: tag.name,
9375
9884
  textEmotion: {
9376
- emotionId: ACK_EMOTION_ID,
9377
- emotionName: ACK_REACTION_NAME,
9378
- text: ACK_REACTION_NAME,
9379
- backgroundId: ACK_EMOTION_BG_ID
9885
+ emotionId: tag.emotionId,
9886
+ emotionName: tag.name,
9887
+ text: tag.name,
9888
+ backgroundId: tag.backgroundId
9380
9889
  }
9381
- })
9890
+ }),
9891
+ signal: AbortSignal.timeout(EMOTION_FETCH_TIMEOUT_MS)
9382
9892
  });
9383
9893
  if (resp.ok)
9384
- return;
9894
+ return true;
9385
9895
  const isTransient = resp.status === 429 || resp.status >= 500;
9386
9896
  if (isTransient && attempt < EMOTION_MAX_ATTEMPTS - 1) {
9387
9897
  await resp.body?.cancel();
@@ -9391,25 +9901,31 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9391
9901
  const detail = sanitizeLogText(await resp.text().catch(() => ""), 500);
9392
9902
  process.stderr.write(`[DingTalk:${this.name}] emotion/${endpoint} failed after ${attempt + 1}/${EMOTION_MAX_ATTEMPTS} attempts: ${resp.status} ${detail}
9393
9903
  `);
9394
- return;
9904
+ return false;
9395
9905
  }
9396
9906
  } catch {
9397
9907
  }
9908
+ return false;
9398
9909
  }
9399
- async attachReaction(msgId, conversationId) {
9400
- await this.emotionApi("reply", msgId, conversationId);
9910
+ async attachReaction(msgId, conversationId, tag = EYE_TAG) {
9911
+ return this.emotionApi("reply", msgId, conversationId, tag);
9401
9912
  }
9402
- async recallReaction(msgId, conversationId) {
9403
- await this.emotionApi("recall", msgId, conversationId);
9913
+ async recallReaction(msgId, conversationId, tag = EYE_TAG) {
9914
+ return this.emotionApi("recall", msgId, conversationId, tag);
9404
9915
  }
9405
9916
  disconnect() {
9406
9917
  if (this.dedupTimer) {
9407
9918
  clearInterval(this.dedupTimer);
9408
9919
  }
9920
+ const reactionStates = [...this.reactionStates.values()];
9921
+ for (const state of reactionStates) {
9922
+ this.finishReaction(state.chatId, state.messageId, state.sessionId);
9923
+ }
9409
9924
  this.statusCardController?.dispose();
9410
9925
  this.drainBackgroundResponseAggregations();
9411
9926
  this.activeReactionKeys.clear();
9412
9927
  this.sessionReactionKeys.clear();
9928
+ this.reactionStates.clear();
9413
9929
  if (this.connectionManager) {
9414
9930
  this.connectionManager.stop();
9415
9931
  } else {
@@ -9417,6 +9933,10 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9417
9933
  }
9418
9934
  process.stderr.write(`[DingTalk:${this.name}] Disconnected.
9419
9935
  `);
9936
+ this.disconnectDrain = Promise.allSettled(reactionStates.map((state) => state.tail)).then(() => void 0);
9937
+ }
9938
+ waitForDisconnect() {
9939
+ return this.disconnectDrain ?? Promise.resolve();
9420
9940
  }
9421
9941
  /** Stable API targets are conversation or user IDs, never webhook URLs. */
9422
9942
  isStableTargetId(chatId) {
@@ -9425,6 +9945,111 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9425
9945
  reactionKey(messageId, conversationId) {
9426
9946
  return `${conversationId}:${messageId}`;
9427
9947
  }
9948
+ forgetReactionState(state) {
9949
+ this.activeReactionKeys.delete(state.key);
9950
+ if (this.reactionStates.get(state.key) === state) {
9951
+ this.reactionStates.delete(state.key);
9952
+ }
9953
+ if (!state.sessionId)
9954
+ return;
9955
+ const keys = this.sessionReactionKeys.get(state.sessionId);
9956
+ keys?.delete(state.key);
9957
+ if (keys?.size === 0)
9958
+ this.sessionReactionKeys.delete(state.sessionId);
9959
+ }
9960
+ enqueueReaction(state, operation) {
9961
+ state.tail = state.tail.then(operation).catch((err) => {
9962
+ this.logReactionFailure("lifecycle tag update", err);
9963
+ });
9964
+ }
9965
+ scheduleReactionDrain(state) {
9966
+ if (state.drainScheduled)
9967
+ return;
9968
+ state.drainScheduled = true;
9969
+ this.enqueueReaction(state, async () => {
9970
+ try {
9971
+ await this.drainReactionState(state);
9972
+ } finally {
9973
+ state.drainScheduled = false;
9974
+ if (this.reactionStates.get(state.key) === state && (state.finishing ? !state.finishBlocked : this.activeReactionKeys.has(state.key) && state.desiredStatusTag && state.desiredStatusTag.name !== state.statusTag?.name)) {
9975
+ this.scheduleReactionDrain(state);
9976
+ }
9977
+ }
9978
+ });
9979
+ }
9980
+ async drainReactionState(state) {
9981
+ while (true) {
9982
+ if (state.finishing) {
9983
+ await this.finishReactionState(state);
9984
+ return;
9985
+ }
9986
+ if (this.reactionStates.get(state.key) !== state || !this.activeReactionKeys.has(state.key)) {
9987
+ return;
9988
+ }
9989
+ const desired = state.desiredStatusTag;
9990
+ if (!desired || desired.name === state.statusTag?.name)
9991
+ return;
9992
+ const latched = state.failedTransition;
9993
+ if (state.statusTag) {
9994
+ const from = state.statusTag.name;
9995
+ if (latched && latched.from === from && latched.to === desired.name) {
9996
+ state.desiredStatusTag = state.statusTag;
9997
+ return;
9998
+ }
9999
+ const revision2 = state.revision;
10000
+ if (await this.recallReaction(state.messageId, state.chatId, state.statusTag) === false) {
10001
+ state.failedTransition = { from, to: desired.name };
10002
+ if (state.revision !== revision2)
10003
+ continue;
10004
+ state.desiredStatusTag = state.statusTag;
10005
+ return;
10006
+ }
10007
+ state.failedTransition = void 0;
10008
+ state.statusTag = void 0;
10009
+ continue;
10010
+ }
10011
+ if (latched && latched.from === void 0 && latched.to === desired.name) {
10012
+ state.desiredStatusTag = void 0;
10013
+ return;
10014
+ }
10015
+ const revision = state.revision;
10016
+ if (await this.attachReaction(state.messageId, state.chatId, desired) === false) {
10017
+ state.failedTransition = { from: void 0, to: desired.name };
10018
+ if (state.revision !== revision)
10019
+ continue;
10020
+ state.desiredStatusTag = void 0;
10021
+ return;
10022
+ }
10023
+ state.failedTransition = void 0;
10024
+ state.statusTag = desired;
10025
+ }
10026
+ }
10027
+ async finishReactionState(state) {
10028
+ let statusCleared = true;
10029
+ if (state.statusTag) {
10030
+ statusCleared = await this.recallReaction(state.messageId, state.chatId, state.statusTag) !== false;
10031
+ if (statusCleared)
10032
+ state.statusTag = void 0;
10033
+ }
10034
+ const eyeCleared = !state.eyeAttached || await this.recallReaction(state.messageId, state.chatId, EYE_TAG) !== false;
10035
+ if (eyeCleared)
10036
+ state.eyeAttached = false;
10037
+ let terminalAttached = true;
10038
+ if (state.terminalTag && statusCleared && eyeCleared) {
10039
+ terminalAttached = await this.attachReaction(state.messageId, state.chatId, state.terminalTag) !== false;
10040
+ }
10041
+ if (!statusCleared || !eyeCleared || !terminalAttached) {
10042
+ state.finishAttempts = (state.finishAttempts ?? 0) + 1;
10043
+ if (state.finishAttempts >= EMOTION_FINISH_MAX_ATTEMPTS) {
10044
+ this.logReactionFailure("reaction cleanup", `abandoned after ${state.finishAttempts} attempts`);
10045
+ this.forgetReactionState(state);
10046
+ return;
10047
+ }
10048
+ state.finishBlocked = true;
10049
+ return;
10050
+ }
10051
+ this.forgetReactionState(state);
10052
+ }
9428
10053
  rememberInboundMessageId(msgId) {
9429
10054
  this.inboundMessageIds.delete(msgId);
9430
10055
  this.inboundMessageIds.add(msgId);
@@ -9447,6 +10072,19 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9447
10072
  if (this.activeReactionKeys.has(key))
9448
10073
  return;
9449
10074
  this.activeReactionKeys.add(key);
10075
+ const state = {
10076
+ key,
10077
+ messageId,
10078
+ chatId,
10079
+ ...sessionId ? { sessionId } : {},
10080
+ desiredStatusTag: this.phaseReactionTag("thinking"),
10081
+ finishing: false,
10082
+ drainScheduled: false,
10083
+ eyeAttached: false,
10084
+ revision: 0,
10085
+ tail: Promise.resolve()
10086
+ };
10087
+ this.reactionStates.set(key, state);
9450
10088
  if (sessionId) {
9451
10089
  let keys = this.sessionReactionKeys.get(sessionId);
9452
10090
  if (!keys) {
@@ -9455,39 +10093,71 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9455
10093
  }
9456
10094
  keys.set(key, { messageId, chatId });
9457
10095
  }
9458
- this.attachReaction(messageId, chatId).then(() => {
9459
- if (!this.activeReactionKeys.has(key)) {
9460
- void this.recallReaction(messageId, chatId).catch((err) => {
9461
- this.logReactionFailure("late reaction recall", err);
9462
- });
10096
+ this.enqueueReaction(state, async () => {
10097
+ try {
10098
+ if (await this.attachReaction(messageId, chatId, EYE_TAG) === false) {
10099
+ this.forgetReactionState(state);
10100
+ return;
10101
+ }
10102
+ state.eyeAttached = true;
10103
+ this.scheduleReactionDrain(state);
10104
+ } catch (err) {
10105
+ this.forgetReactionState(state);
10106
+ this.logReactionFailure("reaction attach", err);
9463
10107
  }
9464
- }).catch((err) => {
9465
- this.activeReactionKeys.delete(key);
9466
- this.logReactionFailure("reaction attach", err);
9467
10108
  });
9468
10109
  }
9469
- stopReaction(chatId, messageId, sessionId) {
10110
+ replaceStatusReaction(chatId, messageId, tag) {
10111
+ if (!messageId)
10112
+ return;
10113
+ const state = this.reactionStates.get(this.reactionKey(messageId, chatId));
10114
+ if (!state || !this.activeReactionKeys.has(state.key))
10115
+ return;
10116
+ state.desiredStatusTag = tag;
10117
+ state.revision++;
10118
+ this.scheduleReactionDrain(state);
10119
+ }
10120
+ phaseReactionTag(phase) {
10121
+ return statusEmotionTag(presentationPhaseLabel(phase, this.displayLanguage));
10122
+ }
10123
+ terminalReactionTag(type) {
10124
+ if (!isChinesePresentationLanguage(this.displayLanguage)) {
10125
+ return type === "completed" ? DONE_TAG : type === "failed" ? FAILED_TAG : STOPPED_TAG;
10126
+ }
10127
+ if (type === "completed") {
10128
+ return { ...DONE_TAG, name: "\u2705 \u5DF2\u5B8C\u6210" };
10129
+ }
10130
+ return statusEmotionTag(type === "failed" ? "\u274C \u5931\u8D25" : "\u23F9\uFE0F \u5DF2\u505C\u6B62");
10131
+ }
10132
+ finishReaction(chatId, messageId, sessionId, terminalTag) {
9470
10133
  if (!messageId || !this.isStableTargetId(chatId))
9471
10134
  return;
9472
10135
  const key = this.reactionKey(messageId, chatId);
9473
- if (sessionId) {
9474
- const keys = this.sessionReactionKeys.get(sessionId);
9475
- if (keys) {
9476
- keys.delete(key);
9477
- if (keys.size === 0)
9478
- this.sessionReactionKeys.delete(sessionId);
9479
- }
10136
+ const state = this.reactionStates.get(key);
10137
+ if (!state)
10138
+ return;
10139
+ if (state.finishing) {
10140
+ if (!state.finishBlocked)
10141
+ return;
10142
+ state.finishBlocked = false;
10143
+ if (terminalTag)
10144
+ state.terminalTag = terminalTag;
10145
+ this.scheduleReactionDrain(state);
10146
+ return;
9480
10147
  }
9481
10148
  if (!this.activeReactionKeys.delete(key))
9482
10149
  return;
9483
- this.recallReaction(messageId, chatId).catch((err) => {
9484
- this.logReactionFailure("reaction recall", err);
9485
- });
10150
+ state.finishing = true;
10151
+ state.desiredStatusTag = void 0;
10152
+ state.terminalTag = terminalTag;
10153
+ state.revision++;
10154
+ this.scheduleReactionDrain(state);
10155
+ }
10156
+ stopReaction(chatId, messageId, sessionId) {
10157
+ this.finishReaction(chatId, messageId, sessionId);
9486
10158
  }
9487
10159
  /** Recall reactions left behind when a session dies without terminal lifecycle events. */
9488
10160
  onSessionDied(sessionId) {
9489
- this.blockProjectionArmed.delete(sessionId);
9490
- this.blockFileProjectors.delete(sessionId);
9491
10161
  for (const [runId, state] of this.fileProjectors) {
9492
10162
  if (state.sessionId === sessionId)
9493
10163
  this.fileProjectors.delete(runId);
@@ -9511,16 +10181,32 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9511
10181
  const keys = this.sessionReactionKeys.get(sessionId);
9512
10182
  if (keys) {
9513
10183
  this.sessionReactionKeys.delete(sessionId);
9514
- for (const [key, { messageId, chatId }] of keys) {
9515
- if (this.activeReactionKeys.delete(key)) {
9516
- void this.recallReaction(messageId, chatId).catch((err) => {
9517
- this.logReactionFailure("session-death reaction recall", err);
9518
- });
9519
- }
10184
+ for (const { messageId, chatId } of keys.values()) {
10185
+ this.finishReaction(chatId, messageId, sessionId);
9520
10186
  }
9521
10187
  }
9522
10188
  super.onSessionDied(sessionId);
9523
10189
  }
10190
+ /**
10191
+ * A crashed standalone bridge never settles its in-flight turns, so their
10192
+ * transient tags and ticking status cards would otherwise assert a live
10193
+ * turn forever. Finish the tags without a terminal result and terminalize
10194
+ * the cards as interrupted. Session state stays: crash recovery restores
10195
+ * the sessions on a fresh bridge.
10196
+ */
10197
+ onBridgeDisconnected() {
10198
+ for (const [sessionId, keys] of this.sessionReactionKeys) {
10199
+ this.sessionReactionKeys.delete(sessionId);
10200
+ for (const { messageId, chatId } of keys.values()) {
10201
+ this.finishReaction(chatId, messageId, sessionId);
10202
+ }
10203
+ }
10204
+ for (const [sessionId, runId] of this.cardRunBySession) {
10205
+ this.cardRunBySession.delete(sessionId);
10206
+ this.interactionPresenter?.terminalizeRun(runId, "cancelled");
10207
+ this.cardRuns.delete(runId);
10208
+ }
10209
+ }
9524
10210
  onSessionRetiring(sessionId) {
9525
10211
  this.drainBackgroundResponseAggregations(sessionId);
9526
10212
  }
@@ -9539,10 +10225,18 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9539
10225
  }
9540
10226
  return;
9541
10227
  }
10228
+ const presentationPhase = lifecyclePresentationPhase(event);
10229
+ if (event.runId && presentationPhase) {
10230
+ this.interactionPresenter?.updateStatusCardPhase(event.runId, presentationPhase);
10231
+ }
10232
+ if (presentationPhase) {
10233
+ this.replaceStatusReaction(event.chatId, event.messageId, this.phaseReactionTag(presentationPhase));
10234
+ return;
10235
+ }
9542
10236
  if (isTerminalTaskLifecycleType(event.type)) {
9543
10237
  if (event.messageId)
9544
10238
  this.mentionTargets.delete(event.messageId);
9545
- this.stopReaction(event.chatId, event.messageId, event.sessionId);
10239
+ this.finishReaction(event.chatId, event.messageId, event.sessionId, this.terminalReactionTag(event.type));
9546
10240
  if (event.runId) {
9547
10241
  this.deleteFileProjectorsForRun(event.runId);
9548
10242
  if (event.type === "failed") {
@@ -9587,7 +10281,6 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9587
10281
  }
9588
10282
  }
9589
10283
  onPromptStart(chatId, sessionId, messageId) {
9590
- this.blockProjectionArmed.add(sessionId);
9591
10284
  if (messageId) {
9592
10285
  this.bufferedMentionTargets.delete(messageId);
9593
10286
  this.untrackBufferedMentionTarget(sessionId, messageId);
@@ -9650,35 +10343,9 @@ var DingtalkChannel = class _DingtalkChannel extends ChannelBase {
9650
10343
  this.bufferedMentionTargetsBySession.delete(sessionId);
9651
10344
  }
9652
10345
  onPromptEnd(chatId, sessionId, messageId) {
9653
- this.settleBlockFileProjector(chatId, sessionId);
9654
10346
  this.sessionMentionTargets.delete(sessionId);
9655
10347
  this.stopReaction(chatId, messageId, sessionId);
9656
10348
  }
9657
- /**
9658
- * Turn end is the only point where the block projector's held state can be
9659
- * settled: ChannelBase drains the turn's queued block sends before calling
9660
- * onPromptEnd, so everything already appended belongs to this turn. Flush
9661
- * the held candidate bytes (a trailing `[FILE:` prefix the stream never
9662
- * completed) before deleting the entry — a later delete-without-settle
9663
- * would silently drop them from the delivered answer. Also disarm the
9664
- * session: /clear eviction and session death settle WITHOUT draining the
9665
- * turn's send chain, and any block that lands afterwards must be dropped
9666
- * rather than recreating projector state.
9667
- */
9668
- settleBlockFileProjector(chatId, sessionId) {
9669
- this.blockProjectionArmed.delete(sessionId);
9670
- const state = this.blockFileProjectors.get(sessionId);
9671
- if (!state)
9672
- return;
9673
- this.blockFileProjectors.delete(sessionId);
9674
- const tail = state.projector.complete();
9675
- if (!tail.trim())
9676
- return;
9677
- void this.sendReply(chatId, tail, void 0, this.getResponseSourceLabel(sessionId)).catch((err) => {
9678
- process.stderr.write(`[DingTalk:${this.name}] projector tail delivery failed for session ${sessionId}: ${err instanceof Error ? err.message : String(err)}
9679
- `);
9680
- });
9681
- }
9682
10349
  /** Deliver every Agent segment immediately unless aggregation is enabled. */
9683
10350
  async dispatchBackgroundResponse(sessionId, text, context) {
9684
10351
  const target = this.router.getTarget(sessionId);
@@ -10231,51 +10898,21 @@ ${text}`;
10231
10898
  return escapeDingTalkMarkdown(normalized || "\u540E\u53F0\u4EFB\u52A1");
10232
10899
  }
10233
10900
  /**
10234
- * Out-of-turn one-shot sends (background responses) must not flow through
10235
- * the session's block-streaming projector: a second sender interleaving with
10236
- * mid-projection state can swallow the send or split a held marker.
10901
+ * Body-identical to the base implementation — this override exists only to
10902
+ * widen the signature, which the base seam does not declare. The background
10903
+ * aggregation flush passes `prepared` so the body it already projected isn't
10904
+ * projected a second time (that would re-upload its files), and
10905
+ * `failOnHttpError` so a failed send throws instead of being swallowed,
10906
+ * letting the flush capture the delivery plan for the next retry.
10237
10907
  */
10238
10908
  async deliverBackgroundReply(chatId, text, sessionId, sourceLabel, prepared = false, failOnHttpError = false) {
10239
- if (this.config.blockStreaming !== "on") {
10240
- return this.sendResponseMessage(chatId, text, sessionId, sourceLabel, prepared, failOnHttpError);
10241
- }
10242
- await this.sendReply(chatId, text, void 0, sourceLabel, prepared, failOnHttpError);
10909
+ await this.sendResponseMessage(chatId, text, sessionId, sourceLabel, prepared, failOnHttpError);
10243
10910
  }
10244
10911
  async sendResponseMessage(chatId, text, sessionId, sourceLabel, prepared = false, failOnHttpError = false) {
10245
- let outgoingText = text;
10246
- let consumesMention = true;
10247
- if (this.config.blockStreaming === "on") {
10248
- const projected = this.projectBlockStreamChunk(text, sessionId);
10249
- if (!projected.text.trim())
10250
- return;
10251
- outgoingText = projected.text;
10252
- consumesMention = projected.hasContent;
10253
- }
10254
- const atUserId = consumesMention && this.atSender ? this.sessionMentionTargets.get(sessionId) : void 0;
10912
+ const atUserId = this.atSender ? this.sessionMentionTargets.get(sessionId) : void 0;
10255
10913
  if (atUserId)
10256
10914
  this.sessionMentionTargets.delete(sessionId);
10257
- await this.sendReply(chatId, outgoingText, atUserId, sourceLabel ?? this.getResponseSourceLabel(sessionId), prepared, failOnHttpError);
10258
- }
10259
- projectBlockStreamChunk(text, sessionId) {
10260
- let state = this.blockFileProjectors.get(sessionId);
10261
- if (!state) {
10262
- if (!this.blockProjectionArmed.has(sessionId)) {
10263
- return { text: "", hasContent: false };
10264
- }
10265
- state = { projector: new OutboundFileProjector(), reportedMarkers: 0 };
10266
- this.blockFileProjectors.set(sessionId, state);
10267
- }
10268
- const safe = state.projector.append(text);
10269
- const hasContent = safe.trim().length > 0;
10270
- const result = state.projector.result(safe);
10271
- let outgoingText = safe;
10272
- if (result.markerCount > state.reportedMarkers) {
10273
- outgoingText = withFileUnavailableNotice(safe);
10274
- state.reportedMarkers = result.markerCount;
10275
- process.stderr.write(`[DingTalk:${this.name}] file markers redacted in block stream (session ${sessionId}, markers=${result.markerCount})
10276
- `);
10277
- }
10278
- return { text: outgoingText, hasContent };
10915
+ await this.sendReply(chatId, text, atUserId, sourceLabel ?? this.getResponseSourceLabel(sessionId), prepared, failOnHttpError);
10279
10916
  }
10280
10917
  async sendFallbackReply(chatId, text, sessionId, sourceLabel) {
10281
10918
  const atUserId = this.atSender ? this.sessionMentionTargets.get(sessionId) : void 0;
@@ -10329,6 +10966,16 @@ ${text}`;
10329
10966
  }
10330
10967
  return this.interactionPresenter.presentInput(context);
10331
10968
  }
10969
+ async presentPermissionRequest(context) {
10970
+ const run = this.cardRuns.get(context.runId);
10971
+ if (!run || run.ownerId !== context.owner.id) {
10972
+ return { kind: "unsupported" };
10973
+ }
10974
+ if (!this.permissionCardController || !this.interactionPresenter) {
10975
+ return { kind: "unsupported" };
10976
+ }
10977
+ return this.interactionPresenter.presentPermission(context);
10978
+ }
10332
10979
  /**
10333
10980
  * Extract quoted/referenced message context from a reply.
10334
10981
  * DingTalk provides this via text.repliedMsg (newer) or quoteMessage (legacy).
@@ -10567,7 +11214,7 @@ ${text}`;
10567
11214
  let filePath;
10568
11215
  let safeName;
10569
11216
  try {
10570
- dir = join(tmpdir3(), "channel-files", randomUUID5());
11217
+ dir = join(tmpdir3(), "channel-files", randomUUID6());
10571
11218
  mkdirSync(dir, { recursive: true });
10572
11219
  safeName = basename3(typeof fileName === "string" ? fileName : "") || `dingtalk_${mediaType}_${Date.now()}.${GENERATED_MEDIA_EXT[media.mimeType] ?? "bin"}`;
10573
11220
  filePath = join(dir, safeName);
@@ -10674,7 +11321,7 @@ ${text}`;
10674
11321
  }
10675
11322
  }) : this.handleInbound(envelope);
10676
11323
  processMessage.catch((err) => {
10677
- const reference = randomUUID5().slice(0, 8);
11324
+ const reference = randomUUID6().slice(0, 8);
10678
11325
  let errorSummary = "Unknown error";
10679
11326
  try {
10680
11327
  errorSummary = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
@@ -10761,6 +11408,24 @@ var plugin = {
10761
11408
  exclusiveMinimum: DINGTALK_INTERACTIVE_CARD_TIMEOUT_EXCLUSIVE_MINIMUM
10762
11409
  }
10763
11410
  ]
11411
+ },
11412
+ {
11413
+ key: "permissionCard",
11414
+ label: "Permission Card",
11415
+ kind: "object",
11416
+ properties: [
11417
+ {
11418
+ key: "enabled",
11419
+ label: "Enabled",
11420
+ kind: "boolean"
11421
+ },
11422
+ {
11423
+ key: "timeoutMs",
11424
+ label: "Timeout (ms)",
11425
+ kind: "number",
11426
+ exclusiveMinimum: DINGTALK_INTERACTIVE_CARD_TIMEOUT_EXCLUSIVE_MINIMUM
11427
+ }
11428
+ ]
10764
11429
  }
10765
11430
  ]
10766
11431
  }