@qwen-code/qwen-code 0.21.7-nightly.20260808.4ec0371e6 → 0.21.8

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 (254) hide show
  1. package/README.md +2 -0
  2. package/bundled/qc-helper/docs/configuration/settings.md +12 -8
  3. package/bundled/qc-helper/docs/features/commands.md +1 -1
  4. package/bundled/qc-helper/docs/features/hooks.md +50 -0
  5. package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
  6. package/bundled/qc-helper/docs/qwen-serve.md +1 -1
  7. package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
  8. package/bundled/review/SKILL.md +24 -5
  9. package/chunks/{MaxSizedBox-COZBVNCI.js → MaxSizedBox-7PM6BGJ5.js} +13 -10
  10. package/chunks/{StandaloneSessionPicker-3OF2FS6S.js → StandaloneSessionPicker-3UQHM7GV.js} +29 -26
  11. package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
  12. package/chunks/{acpAgent-3JCJ6KWG.js → acpAgent-5UWLFV6V.js} +369 -148
  13. package/chunks/{agent-DBSC47CD.js → agent-624T2BLO.js} +13 -10
  14. package/chunks/{agent-headless-ZJHZ7I3S.js → agent-headless-2EE5J2KX.js} +13 -10
  15. package/chunks/{bridge-NFBYT4ZI.js → bridge-JENKGFFP.js} +15 -12
  16. package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
  17. package/chunks/{channel-management-service-LXSJXQGM.js → channel-management-service-DDWUPHMU.js} +1 -1
  18. package/chunks/{channel-settings-store-LABKDKSI.js → channel-settings-store-SA6JZSPH.js} +21 -18
  19. package/chunks/{channel-worker-group-MTW2AGT3.js → channel-worker-group-E67EN3RV.js} +2 -2
  20. package/chunks/{channel-worker-manager-UU6PTQSI.js → channel-worker-manager-SW4C45CF.js} +2 -2
  21. package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
  22. package/chunks/{chunk-HKCYGZZ4.js → chunk-2ILAOM2I.js} +30 -13
  23. package/chunks/{chunk-LDY4J4G6.js → chunk-2M4K4KYS.js} +176 -119
  24. package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
  25. package/chunks/{chunk-XCG76UE6.js → chunk-3PY4LPJF.js} +17 -129
  26. package/chunks/{chunk-26ISE5EG.js → chunk-3SE7J4DR.js} +3 -3
  27. package/chunks/{chunk-APMRLB2H.js → chunk-3WNQOYHQ.js} +12 -12
  28. package/chunks/{chunk-O7VQ3F22.js → chunk-4ALIARFY.js} +1 -1
  29. package/chunks/{chunk-FJ6YHWHZ.js → chunk-4DU3NCHG.js} +47 -54
  30. package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
  31. package/chunks/{chunk-3HS6Y4UA.js → chunk-4WU6NY7F.js} +2 -2
  32. package/chunks/{chunk-JRIJOZXO.js → chunk-5ZGR6RKJ.js} +3 -3
  33. package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
  34. package/chunks/{chunk-ZQGHESAS.js → chunk-6TR7CFXH.js} +1 -1
  35. package/chunks/{chunk-EZ53KMUN.js → chunk-757GB46F.js} +1 -1
  36. package/chunks/{chunk-5YT3Y33M.js → chunk-77QVBFCU.js} +3 -3
  37. package/chunks/{chunk-5PGKKSO6.js → chunk-7DVT4LVV.js} +35 -28
  38. package/chunks/{chunk-IMK3SJ43.js → chunk-7VUERJHS.js} +1066 -597
  39. package/chunks/{chunk-KPMB4JEZ.js → chunk-B52AWKBB.js} +64 -20
  40. package/chunks/{chunk-R2KZWK5Z.js → chunk-BF224XHL.js} +2 -2
  41. package/chunks/{chunk-TSYIQDG7.js → chunk-BF52U4XJ.js} +1 -1
  42. package/chunks/{chunk-LDUGDB5H.js → chunk-C5VWPTGT.js} +1 -1
  43. package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
  44. package/chunks/chunk-COBO5EBO.js +135 -0
  45. package/chunks/{chunk-ACHMWGC5.js → chunk-DQSDACD2.js} +1 -1
  46. package/chunks/{chunk-VT3VNFVW.js → chunk-DX5W5AON.js} +2 -2
  47. package/chunks/{chunk-JACAHYEN.js → chunk-E4ZBKMSF.js} +4 -4
  48. package/chunks/{chunk-MV7VUCIG.js → chunk-EIVICVHM.js} +4 -4
  49. package/chunks/{chunk-YHEEE624.js → chunk-EN2TKTFH.js} +1 -1
  50. package/chunks/chunk-F6WFNA7U.js +22 -0
  51. package/chunks/{chunk-Z6W3XDLN.js → chunk-FN6YXJOP.js} +1 -1
  52. package/chunks/{chunk-BJKFFPX2.js → chunk-FWBXMANW.js} +3 -3
  53. package/chunks/{chunk-764F335K.js → chunk-FYAXKJK7.js} +314 -63
  54. package/chunks/{chunk-XIDHBXUI.js → chunk-GBDINRIL.js} +3 -3
  55. package/chunks/{chunk-Z5ZAWED3.js → chunk-GOEVOFQI.js} +3 -3
  56. package/chunks/{chunk-ZKUJ4AO7.js → chunk-GQCEQPYQ.js} +3 -3
  57. package/chunks/{chunk-BFSQBXHV.js → chunk-GXSNGY5M.js} +399 -534
  58. package/chunks/{chunk-3ARO4N5G.js → chunk-HA3SAB64.js} +22 -69
  59. package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
  60. package/chunks/{chunk-LMEIS6WW.js → chunk-HWX5HPUG.js} +3 -3
  61. package/chunks/{chunk-VLFX3L3X.js → chunk-IBYULW65.js} +6 -6
  62. package/chunks/{chunk-SDUDZNF4.js → chunk-IUQ52YJK.js} +1 -1
  63. package/chunks/{chunk-H2352CX2.js → chunk-IYES5WOT.js} +2 -2
  64. package/chunks/{chunk-CE5UCTKO.js → chunk-KAQCJO6Y.js} +1 -1
  65. package/chunks/{chunk-DPH3MUAP.js → chunk-KKDVZLGL.js} +1 -1
  66. package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
  67. package/chunks/{chunk-P7HUJDBZ.js → chunk-M3STHEMM.js} +11 -16
  68. package/chunks/{chunk-VDS2WYM5.js → chunk-NGYI5EF5.js} +2 -2
  69. package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
  70. package/chunks/{chunk-GUFY6D3E.js → chunk-NPUXXRJI.js} +1 -1
  71. package/chunks/{chunk-4Q6N3SNL.js → chunk-NVRDQFCX.js} +1 -1
  72. package/chunks/{chunk-77WOUGCA.js → chunk-OHKJVAKG.js} +7 -7
  73. package/chunks/{chunk-TAOSTUHI.js → chunk-PG62DFWD.js} +10 -10
  74. package/chunks/{chunk-REHWPCG2.js → chunk-PLFATELK.js} +1 -1
  75. package/chunks/{chunk-APNNM3JC.js → chunk-QGHSP65Z.js} +2 -2
  76. package/chunks/{chunk-HY2INPTA.js → chunk-QQWD7LZV.js} +4 -4
  77. package/chunks/{chunk-P74TZRXD.js → chunk-QXVSWG66.js} +1 -1
  78. package/chunks/{chunk-TX3KSSDN.js → chunk-S3Y3GBFD.js} +1 -1
  79. package/chunks/{chunk-B23P3YWE.js → chunk-SNRT2TJJ.js} +6 -23
  80. package/chunks/chunk-SR7RZ4MS.js +202 -0
  81. package/chunks/{chunk-F3LPXDJP.js → chunk-TE3ZAJE7.js} +13 -3
  82. package/chunks/{chunk-AB4A73VL.js → chunk-TKSZJ5BV.js} +1 -1
  83. package/chunks/{chunk-RZMGG3HP.js → chunk-U5SLIG7E.js} +1 -1
  84. package/chunks/chunk-UA5H3DS2.js +203 -0
  85. package/chunks/{chunk-JSJTZ6GO.js → chunk-VWMUDKLC.js} +3 -3
  86. package/chunks/{chunk-RGTB44BO.js → chunk-VXZ5HAOV.js} +1 -1
  87. package/chunks/{chunk-BCMJPTXV.js → chunk-WG6542MA.js} +1 -1
  88. package/chunks/{chunk-AG3P2RES.js → chunk-WV5J6Q6N.js} +1 -1
  89. package/chunks/{chunk-MIA37QO3.js → chunk-XHD7CRP2.js} +2 -2
  90. package/chunks/{chunk-KKRGVSHC.js → chunk-XZKQT2B2.js} +4 -4
  91. package/chunks/{chunk-4QJJHIZ5.js → chunk-Y4TETC74.js} +5 -5
  92. package/chunks/{chunk-QKJT5K4Q.js → chunk-YEF7XEO2.js} +3 -3
  93. package/chunks/{chunk-UKAYEQDU.js → chunk-YHJFF7KH.js} +131 -38
  94. package/chunks/{chunk-64YLXLMY.js → chunk-YOM7DEGB.js} +2 -2
  95. package/chunks/{chunk-BN3OROB3.js → chunk-ZCLLJARV.js} +9 -9
  96. package/chunks/{chunk-RFA6VDCR.js → chunk-ZHA242R4.js} +2 -2
  97. package/chunks/{chunk-L4OW63GW.js → chunk-ZPLALRXZ.js} +17 -9
  98. package/chunks/{computer-use-QLJ27OCZ.js → computer-use-ESQYJ3JY.js} +13 -10
  99. package/chunks/{config-utils-KIEXWA4F.js → config-utils-XQHBJP7G.js} +2 -2
  100. package/chunks/{contextCommand-JDTOJRBO.js → contextCommand-CX3YF4ZE.js} +15 -12
  101. package/chunks/{core-runtime-MZIAVYQC.js → core-runtime-DIAU7JMG.js} +13 -10
  102. package/chunks/{create-sub-session-YBBCNSHE.js → create-sub-session-HDPD6HOA.js} +13 -10
  103. package/chunks/{daemon-SCTQMM7Z.js → daemon-VZBGJUNL.js} +30 -0
  104. package/chunks/{daemon-status-provider-BZ7RD4ZJ.js → daemon-status-provider-H6O4UQ4F.js} +19 -16
  105. package/chunks/{daemon-trust-policy-2E4C3M7S.js → daemon-trust-policy-BNUXG6MT.js} +20 -17
  106. package/chunks/{daemon-trust-policy-monitor-UYLFH6RW.js → daemon-trust-policy-monitor-E4EQ7GF4.js} +20 -17
  107. package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
  108. package/chunks/{deferred-core-runtime-6XZYMJZB.js → deferred-core-runtime-CBMSHPAU.js} +13 -10
  109. package/chunks/{dist-BATY7GI4.js → dist-EEEQGCZA.js} +731 -136
  110. package/chunks/{dist-26RK5XZO.js → dist-MKX5OSFF.js} +4 -3
  111. package/chunks/{earlyInputCapture-LATQCGDC.js → earlyInputCapture-UIOP7OIN.js} +13 -10
  112. package/chunks/{edit-72DP57CD.js → edit-ITMZYFKA.js} +13 -10
  113. package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
  114. package/chunks/{enter-worktree-B4FY2ZPP.js → enter-worktree-S4PL5UV6.js} +13 -10
  115. package/chunks/{enterPlanMode-TQBWGCPL.js → enterPlanMode-YV52NNJT.js} +13 -10
  116. package/chunks/{environment-MOGZGZDS.js → environment-NGOWPRZV.js} +17 -14
  117. package/chunks/{errors-PGON5GH7.js → errors-BU26DTDX.js} +15 -12
  118. package/chunks/{exit-worktree-EYUD4YP2.js → exit-worktree-XRM6LH5F.js} +13 -10
  119. package/chunks/{exitPlanMode-4Q7BSQXR.js → exitPlanMode-ZLI5F7KR.js} +13 -10
  120. package/chunks/{fast-path-WI7D5MER.js → fast-path-UJWORIED.js} +3 -3
  121. package/chunks/{fast-path-settings-YBRL24DB.js → fast-path-settings-37WQD5B2.js} +6 -3
  122. package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
  123. package/chunks/{gemini-ZXURGM6Y.js → gemini-ZSKNDUMU.js} +55 -48
  124. package/chunks/{geminiContentGenerator-EOODO75Y.js → geminiContentGenerator-YGEXOEKD.js} +1 -1
  125. package/chunks/{glob-QNRIUOS6.js → glob-7KZG44BR.js} +13 -10
  126. package/chunks/{goal-tools-QSYW65HV.js → goal-tools-PXWN5VK3.js} +3 -1
  127. package/chunks/{grep-56MTW67B.js → grep-6ZFC7RJ5.js} +13 -10
  128. package/chunks/{handleAutoUpdate-XGFIPVT4.js → handleAutoUpdate-KSEL3TQS.js} +17 -14
  129. package/chunks/{i18n-RZB35L4B.js → i18n-ZIUXBW5V.js} +14 -11
  130. package/chunks/{image-gen-OE2EEKN3.js → image-gen-AUIZJJNK.js} +6 -4
  131. package/chunks/{initializer-YPVMTMKD.js → initializer-7AHY3N6Q.js} +20 -17
  132. package/chunks/{installationInfo-ZTMTMYNW.js → installationInfo-VGBXMYLY.js} +14 -11
  133. package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
  134. package/chunks/{list-NIW3WID5.js → list-PSFKQHLB.js} +23 -20
  135. package/chunks/{loadedSettingsAdapter-VSLILTOZ.js → loadedSettingsAdapter-FTMRCTOF.js} +20 -17
  136. package/chunks/{loggingContentGenerator-KFZYVAGV.js → loggingContentGenerator-MZAN52UV.js} +5 -3
  137. package/chunks/{managed-npm-update-WHTA2K5V.js → managed-npm-update-O4NHK45X.js} +14 -11
  138. package/chunks/{mcp-7KGK3CS3.js → mcp-6CFP2AYQ.js} +20 -17
  139. package/chunks/{monitor-FDWEJQWP.js → monitor-DAKD6OU4.js} +13 -10
  140. package/chunks/{nonInteractiveCli-2MVJ6TCS.js → nonInteractiveCli-RC7VIUZL.js} +49 -44
  141. package/chunks/{notebook-edit-ZUVK2XWE.js → notebook-edit-474DPMRL.js} +13 -10
  142. package/chunks/{openaiContentGenerator-TNLWOPH5.js → openaiContentGenerator-2NFY2MWO.js} +6 -3
  143. package/chunks/{pidfile-BB6SKPH2.js → pidfile-KBFVDNQP.js} +13 -10
  144. package/chunks/{processUtils-WKHJOPDH.js → processUtils-6GRYH4Y3.js} +2 -2
  145. package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
  146. package/chunks/{qwenContentGenerator-FZS2DYF7.js → qwenContentGenerator-KAHU6IZY.js} +14 -11
  147. package/chunks/{qwenOAuth2-UYMYRXBB.js → qwenOAuth2-RRQTCP4W.js} +6 -4
  148. package/chunks/{read-file-FMTE6LPA.js → read-file-3M6WXDXP.js} +4 -2
  149. package/chunks/{resumeHistoryUtils-Z34RCZFF.js → resumeHistoryUtils-D6TAY3HX.js} +16 -13
  150. package/chunks/{ripGrep-DUIYUZGM.js → ripGrep-PLPENT3E.js} +13 -10
  151. package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
  152. package/chunks/{run-qwen-serve-KOHHR3F4.js → run-qwen-serve-ZAFIJKJC.js} +93 -40
  153. package/chunks/{runtime-K4NTZSAU.js → runtime-ZED7CYOZ.js} +23 -20
  154. package/chunks/{scheduler-6G6AMURS.js → scheduler-MD3AL2W5.js} +13 -10
  155. package/chunks/{serve-NMG2TM5K.js → serve-E3VUDRZN.js} +20 -17
  156. package/chunks/{server-FS7KDELS.js → server-OWMEMAKR.js} +381 -192
  157. package/chunks/{session-XZADUVKJ.js → session-HZ57QK7K.js} +141 -81
  158. package/chunks/{settings-G75R6FOA.js → settings-V7BR3RKP.js} +19 -16
  159. package/chunks/{shell-3D3PMQHE.js → shell-23OMNMW6.js} +13 -10
  160. package/chunks/{skill-TSEYMVQ2.js → skill-6HBDYZRS.js} +4 -2
  161. package/chunks/{skill-settings-HJC2CPBJ.js → skill-settings-HWJLTU7M.js} +19 -16
  162. package/chunks/{spawnChannel-YWCN74G5.js → spawnChannel-N6KKUW5B.js} +13 -10
  163. package/chunks/{standalone-update-HLYOLX6V.js → standalone-update-QGIKHATD.js} +15 -12
  164. package/chunks/{startInteractiveUI-ROUIQ5KU.js → startInteractiveUI-GX2CRL42.js} +269 -118
  165. package/chunks/{team-create-OTP5SSB2.js → team-create-CFFKU7KL.js} +13 -10
  166. package/chunks/{team-plan-approval-TQX5TMXU.js → team-plan-approval-6EFOKR6A.js} +13 -10
  167. package/chunks/{terminal-image-renderer-KF3GKNWW.js → terminal-image-renderer-TLDNACQY.js} +13 -10
  168. package/chunks/{theme-manager-XVWAAGAM.js → theme-manager-5LJ3H7VO.js} +13 -10
  169. package/chunks/{tool-search-7N4D4O56.js → tool-search-UJV3A24H.js} +4 -2
  170. package/chunks/{total-session-admission-ZQ4VKIRW.js → total-session-admission-D63QYXGO.js} +15 -12
  171. package/chunks/{trustedFolders-4XYFPWVV.js → trustedFolders-KZCOB53W.js} +17 -12
  172. package/chunks/{update-relaunch-L4GSBLUU.js → update-relaunch-IFILM3SA.js} +5 -5
  173. package/chunks/{updateCheck-PCUTVRFE.js → updateCheck-YZ2CRCFC.js} +16 -13
  174. package/chunks/{useAutoAcceptIndicator-WMXY7MND.js → useAutoAcceptIndicator-AXEVNA3Q.js} +22 -19
  175. package/chunks/{validateNonInterActiveAuth-5S3U2D56.js → validateNonInterActiveAuth-3WTOJFWA.js} +44 -41
  176. package/chunks/{version-P57IQU2T.js → version-GXK7OHZY.js} +1 -1
  177. package/chunks/{web-fetch-5ZLLLCDD.js → web-fetch-ILB4GAVR.js} +10 -6
  178. package/chunks/{web-search-NELKANTW.js → web-search-HKRPGPZZ.js} +5 -3
  179. package/chunks/{workflow-RXKBF3LO.js → workflow-FXIPRQQA.js} +735 -134
  180. package/chunks/{workspace-providers-status-HAEMNAWC.js → workspace-providers-status-NYHC7HSR.js} +22 -19
  181. package/chunks/{workspace-registration-store-U3U3YM6V.js → workspace-registration-store-AKEB7OMW.js} +1 -1
  182. package/chunks/{workspace-registry-ZFP33GVB.js → workspace-registry-CDAS5TVZ.js} +15 -12
  183. package/chunks/{workspace-service-QMISJBMA.js → workspace-service-PAMUKMAV.js} +23 -20
  184. package/chunks/{workspace-skills-status-K7EOUGXL.js → workspace-skills-status-YQSHCCMS.js} +20 -17
  185. package/chunks/{workspace-trust-reconciler-BFPKULDZ.js → workspace-trust-reconciler-RPTXOIY2.js} +22 -19
  186. package/chunks/{write-file-2F76RRFE.js → write-file-CGS57TS4.js} +13 -10
  187. package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
  188. package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
  189. package/chunks/{zoom-image-DPR22XWY.js → zoom-image-E7D72GYV.js} +4 -2
  190. package/cli.js +13 -13
  191. package/locales/ca.js +10 -0
  192. package/locales/de.js +9 -0
  193. package/locales/en.js +10 -0
  194. package/locales/fr.js +9 -0
  195. package/locales/ja.js +9 -0
  196. package/locales/pt.js +9 -0
  197. package/locales/ru.js +9 -0
  198. package/locales/zh-TW.js +10 -0
  199. package/locales/zh.js +10 -0
  200. package/package.json +3 -3
  201. package/web-shell/assets/{arc-CunFPPcQ.js → arc-DybZaz32.js} +1 -1
  202. package/web-shell/assets/{architectureDiagram-3BPJPVTR-D3SqCgeM.js → architectureDiagram-3BPJPVTR-jN3qBd19.js} +1 -1
  203. package/web-shell/assets/{blockDiagram-GPEHLZMM-CPRx90S_.js → blockDiagram-GPEHLZMM-Ct5DZPrj.js} +1 -1
  204. package/web-shell/assets/{c4Diagram-AAUBKEIU-CahP9Ue4.js → c4Diagram-AAUBKEIU-CUAFMlUG.js} +1 -1
  205. package/web-shell/assets/channel-BMwLrwLW.js +1 -0
  206. package/web-shell/assets/{chunk-2J33WTMH-DckIWZ12.js → chunk-2J33WTMH-CuV8n90B.js} +1 -1
  207. package/web-shell/assets/{chunk-4BX2VUAB-D2Kfctyn.js → chunk-4BX2VUAB-BUzl_kls.js} +1 -1
  208. package/web-shell/assets/{chunk-55IACEB6-DkI11FTX.js → chunk-55IACEB6-BnDBLX6A.js} +1 -1
  209. package/web-shell/assets/{chunk-727SXJPM-rR-TSCIi.js → chunk-727SXJPM-B83uTOjm.js} +1 -1
  210. package/web-shell/assets/{chunk-AQP2D5EJ-DFGKcGRO.js → chunk-AQP2D5EJ-DM3HLgpT.js} +1 -1
  211. package/web-shell/assets/{chunk-FMBD7UC4-CjWqcTPE.js → chunk-FMBD7UC4-CSQ5hgyb.js} +1 -1
  212. package/web-shell/assets/{chunk-ND2GUHAM-RXe-87UV.js → chunk-ND2GUHAM-BWOF4SxX.js} +1 -1
  213. package/web-shell/assets/{chunk-QZHKN3VN-Dz0c_Yrn.js → chunk-QZHKN3VN-BsOH9LMi.js} +1 -1
  214. package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +1 -0
  215. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +1 -0
  216. package/web-shell/assets/{cose-bilkent-S5V4N54A-ZHF0-jvV.js → cose-bilkent-S5V4N54A-IENqH2iJ.js} +1 -1
  217. package/web-shell/assets/{dagre-BM42HDAG-7Umz_ygJ.js → dagre-BM42HDAG--dyzDTGo.js} +1 -1
  218. package/web-shell/assets/{diagram-2AECGRRQ-DomN8nxq.js → diagram-2AECGRRQ-BE7Dcqof.js} +1 -1
  219. package/web-shell/assets/{diagram-5GNKFQAL-eebvj2OL.js → diagram-5GNKFQAL-Cr8-5OTj.js} +1 -1
  220. package/web-shell/assets/{diagram-KO2AKTUF-IR1mmn9d.js → diagram-KO2AKTUF-Bzey3uAY.js} +1 -1
  221. package/web-shell/assets/{diagram-LMA3HP47-CKysx5KF.js → diagram-LMA3HP47-sErl28Xb.js} +1 -1
  222. package/web-shell/assets/{diagram-OG6HWLK6-cBy5puHn.js → diagram-OG6HWLK6-Dq30ATIo.js} +1 -1
  223. package/web-shell/assets/{erDiagram-TEJ5UH35-B5RJagPG.js → erDiagram-TEJ5UH35-BkCoEfVW.js} +1 -1
  224. package/web-shell/assets/{flowDiagram-I6XJVG4X-CfHgDmPg.js → flowDiagram-I6XJVG4X-DHwO0rrI.js} +1 -1
  225. package/web-shell/assets/{ganttDiagram-6RSMTGT7-DUfFF5nb.js → ganttDiagram-6RSMTGT7-s7vAPxWq.js} +1 -1
  226. package/web-shell/assets/{gitGraphDiagram-PVQCEYII-M9dt57k5.js → gitGraphDiagram-PVQCEYII-CQxhwPOU.js} +1 -1
  227. package/web-shell/assets/{index-B8e-CkuC.css → index-Bckpjr-I.css} +1 -1
  228. package/web-shell/assets/{index-CKjO4myk.js → index-CF4wApWp.js} +1 -1
  229. package/web-shell/assets/{index-Dc-fTO0V.js → index-DwEr9HEW.js} +316 -316
  230. package/web-shell/assets/{infoDiagram-5YYISTIA-CTKMmIro.js → infoDiagram-5YYISTIA-BnFrD0bq.js} +1 -1
  231. package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-DJIJDP4s.js → ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js} +1 -1
  232. package/web-shell/assets/{journeyDiagram-JHISSGLW-DgRnvn6S.js → journeyDiagram-JHISSGLW-CyGAhsxi.js} +1 -1
  233. package/web-shell/assets/{kanban-definition-UN3LZRKU-VUwO8yrg.js → kanban-definition-UN3LZRKU-CbsK5akB.js} +1 -1
  234. package/web-shell/assets/{linear-BCvgV5I_.js → linear-cQsF4P8D.js} +1 -1
  235. package/web-shell/assets/{mermaid.core-mv_kVV6q.js → mermaid.core-Z4HVqrKY.js} +5 -5
  236. package/web-shell/assets/{mindmap-definition-RKZ34NQL-sfnjMlOd.js → mindmap-definition-RKZ34NQL-CYnrBo_f.js} +1 -1
  237. package/web-shell/assets/{pieDiagram-4H26LBE5-BlhICse4.js → pieDiagram-4H26LBE5-CBzOfhrs.js} +1 -1
  238. package/web-shell/assets/{quadrantDiagram-W4KKPZXB-BgTQzwen.js → quadrantDiagram-W4KKPZXB-D4LK1Ebn.js} +1 -1
  239. package/web-shell/assets/{requirementDiagram-4Y6WPE33-CZ-FTrrN.js → requirementDiagram-4Y6WPE33-Bzti2Lcj.js} +1 -1
  240. package/web-shell/assets/{sankeyDiagram-5OEKKPKP-G5Wp_jn3.js → sankeyDiagram-5OEKKPKP-yTBw5Z2s.js} +1 -1
  241. package/web-shell/assets/{sequenceDiagram-3UESZ5HK-C8MKZ3i1.js → sequenceDiagram-3UESZ5HK-D07UVRiZ.js} +1 -1
  242. package/web-shell/assets/{stateDiagram-AJRCARHV-Bo0ZDm7y.js → stateDiagram-AJRCARHV-UE_lHsTn.js} +1 -1
  243. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +1 -0
  244. package/web-shell/assets/{timeline-definition-PNZ67QCA-M3L9E01f.js → timeline-definition-PNZ67QCA-DRvYdiTs.js} +1 -1
  245. package/web-shell/assets/{vennDiagram-CIIHVFJN-DD4eHCrm.js → vennDiagram-CIIHVFJN-CQLIXs0u.js} +1 -1
  246. package/web-shell/assets/{wardley-L42UT6IY-DNEL_3g4.js → wardley-L42UT6IY-JZz_Xqse.js} +1 -1
  247. package/web-shell/assets/{wardleyDiagram-YWT4CUSO-q484OoqI.js → wardleyDiagram-YWT4CUSO--i7BiJwB.js} +1 -1
  248. package/web-shell/assets/{xychartDiagram-2RQKCTM6-4mcNt1Yg.js → xychartDiagram-2RQKCTM6-Bkc-bW0S.js} +1 -1
  249. package/web-shell/index.html +2 -2
  250. package/chunks/chunk-ALFTV7GA.js +0 -92
  251. package/web-shell/assets/channel-zbv7GWAw.js +0 -1
  252. package/web-shell/assets/classDiagram-4FO5ZUOK-DSjLkJJZ.js +0 -1
  253. package/web-shell/assets/classDiagram-v2-Q7XG4LA2-DSjLkJJZ.js +0 -1
  254. package/web-shell/assets/stateDiagram-v2-BHNVJYJU-31TSCPcH.js +0 -1
@@ -88997,6 +88997,440 @@ async function downloadMedia(messageId, fileKey, resourceType, accessToken) {
88997
88997
  }
88998
88998
  __name(downloadMedia, "downloadMedia");
88999
88999
 
89000
+ // packages/channels/feishu/dist/question-card-controller.js
89001
+ init_esbuild_shims();
89002
+
89003
+ // packages/channels/feishu/dist/question-card.js
89004
+ init_esbuild_shims();
89005
+ var terminalLabels = {
89006
+ processing: "\u6B63\u5728\u5904\u7406...",
89007
+ submitted: "\u5DF2\u63D0\u4EA4",
89008
+ cancelled: "\u5DF2\u53D6\u6D88",
89009
+ expired: "\u5DF2\u8FC7\u671F"
89010
+ };
89011
+ function buildQuestionCard(context) {
89012
+ const elements = [];
89013
+ for (const question of context.questions) {
89014
+ const descriptions = question.options.map((option) => `> **${option.label}**: ${option.description}`).join("\n");
89015
+ elements.push({
89016
+ tag: "markdown",
89017
+ text_size: "notation",
89018
+ content: `**${question.header}**
89019
+ > ${question.question}
89020
+
89021
+ ${descriptions}`
89022
+ });
89023
+ elements.push({
89024
+ tag: question.multiSelect ? "multi_select_static" : "select_static",
89025
+ name: question.answerKey,
89026
+ options: question.options.map((option) => ({
89027
+ text: { tag: "plain_text", content: option.label },
89028
+ value: option.label
89029
+ }))
89030
+ });
89031
+ }
89032
+ elements.push({
89033
+ tag: "button",
89034
+ text: { tag: "plain_text", content: "\u63D0\u4EA4" },
89035
+ type: "primary",
89036
+ name: `qwen_ask_submit_${context.requestId}`,
89037
+ form_action_type: "submit",
89038
+ value: {
89039
+ action: "qwen_ask_submit",
89040
+ operation_id: context.requestId
89041
+ }
89042
+ }, {
89043
+ tag: "button",
89044
+ text: { tag: "plain_text", content: "\u53D6\u6D88" },
89045
+ name: `qwen_ask_cancel_${context.requestId}`,
89046
+ value: {
89047
+ action: "qwen_ask_cancel",
89048
+ operation_id: context.requestId
89049
+ }
89050
+ });
89051
+ return {
89052
+ schema: "2.0",
89053
+ body: { elements: [{ tag: "form", name: "qwen_ask_form", elements }] }
89054
+ };
89055
+ }
89056
+ __name(buildQuestionCard, "buildQuestionCard");
89057
+ function buildQuestionTerminalCard(questions, state, answers) {
89058
+ const details = questions.map((question) => {
89059
+ const answer = answers?.[question.answerKey];
89060
+ return answer ? `**${question.header}**
89061
+ ${answer}` : `**${question.header}**
89062
+ ${question.question}`;
89063
+ }).join("\n\n");
89064
+ return {
89065
+ schema: "2.0",
89066
+ body: {
89067
+ elements: [
89068
+ {
89069
+ tag: "markdown",
89070
+ content: `**${terminalLabels[state]}**
89071
+
89072
+ ${details}`
89073
+ }
89074
+ ]
89075
+ }
89076
+ };
89077
+ }
89078
+ __name(buildQuestionTerminalCard, "buildQuestionTerminalCard");
89079
+ function record(value) {
89080
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
89081
+ return void 0;
89082
+ }
89083
+ return value;
89084
+ }
89085
+ __name(record, "record");
89086
+ function nonEmptyString(value) {
89087
+ return typeof value === "string" && value ? value : void 0;
89088
+ }
89089
+ __name(nonEmptyString, "nonEmptyString");
89090
+ function parseQuestionAction(data) {
89091
+ const payload = record(data);
89092
+ const action = record(payload?.["action"]);
89093
+ const rawValue = action?.["value"];
89094
+ const value = record(rawValue);
89095
+ let requestId = nonEmptyString(value?.["operation_id"]);
89096
+ let actionId = nonEmptyString(value?.["action"]);
89097
+ const name = action?.["name"];
89098
+ if (rawValue === void 0 && typeof name === "string" && name.startsWith("qwen_ask_submit_")) {
89099
+ requestId = nonEmptyString(name.slice("qwen_ask_submit_".length));
89100
+ actionId = requestId ? "qwen_ask_submit" : void 0;
89101
+ }
89102
+ if (rawValue === void 0 && typeof name === "string" && name.startsWith("qwen_ask_cancel_")) {
89103
+ requestId = nonEmptyString(name.slice("qwen_ask_cancel_".length));
89104
+ actionId = requestId ? "qwen_ask_cancel" : void 0;
89105
+ }
89106
+ if (!requestId || !actionId || typeof name !== "string") {
89107
+ return { kind: "unhandled" };
89108
+ }
89109
+ const operator = record(payload?.["operator"]);
89110
+ const operatorId = nonEmptyString(operator?.["open_id"]);
89111
+ const operatorResult = operatorId ? { operatorId } : void 0;
89112
+ const context = record(payload?.["context"]);
89113
+ const chatId = nonEmptyString(context?.["open_chat_id"]) ?? nonEmptyString(payload?.["open_chat_id"]);
89114
+ const messageId = nonEmptyString(context?.["open_message_id"]) ?? nonEmptyString(payload?.["open_message_id"]);
89115
+ const correlation = {
89116
+ ...chatId ? { chatId } : {},
89117
+ ...messageId ? { messageId } : {}
89118
+ };
89119
+ if (actionId === "qwen_ask_submit" && name === `qwen_ask_submit_${requestId}`) {
89120
+ const formValue = record(action?.["form_value"]);
89121
+ return {
89122
+ kind: "submit",
89123
+ requestId,
89124
+ ...operatorResult,
89125
+ ...correlation,
89126
+ ...formValue ? { formValue } : {}
89127
+ };
89128
+ }
89129
+ if (actionId === "qwen_ask_cancel" && name === `qwen_ask_cancel_${requestId}`) {
89130
+ return { kind: "cancel", requestId, ...operatorResult, ...correlation };
89131
+ }
89132
+ return { kind: "unhandled" };
89133
+ }
89134
+ __name(parseQuestionAction, "parseQuestionAction");
89135
+ function parseQuestionAnswers(questions, formValue) {
89136
+ if (!formValue)
89137
+ return void 0;
89138
+ const answerKeys = new Set(questions.map((question) => question.answerKey));
89139
+ const submittedKeys = Object.keys(formValue);
89140
+ if (submittedKeys.length !== questions.length || submittedKeys.some((key) => !answerKeys.has(key))) {
89141
+ return void 0;
89142
+ }
89143
+ const answers = {};
89144
+ for (const question of questions) {
89145
+ const rawAnswer = formValue[question.answerKey];
89146
+ let values;
89147
+ if (question.multiSelect) {
89148
+ if (Array.isArray(rawAnswer)) {
89149
+ values = rawAnswer;
89150
+ } else if (typeof rawAnswer === "string") {
89151
+ try {
89152
+ const parsed = JSON.parse(rawAnswer);
89153
+ if (!Array.isArray(parsed))
89154
+ return void 0;
89155
+ values = parsed;
89156
+ } catch {
89157
+ return void 0;
89158
+ }
89159
+ } else {
89160
+ return void 0;
89161
+ }
89162
+ } else if (typeof rawAnswer === "string" && rawAnswer) {
89163
+ values = [rawAnswer];
89164
+ } else {
89165
+ return void 0;
89166
+ }
89167
+ if (values.length === 0 || !question.multiSelect && values.length !== 1 || question.multiSelect && new Set(values).size !== values.length || values.some((value) => typeof value !== "string" || !question.options.some((option) => option.label === value))) {
89168
+ return void 0;
89169
+ }
89170
+ answers[question.answerKey] = values.join(", ");
89171
+ }
89172
+ return answers;
89173
+ }
89174
+ __name(parseQuestionAnswers, "parseQuestionAnswers");
89175
+
89176
+ // packages/channels/feishu/dist/question-card-controller.js
89177
+ var FeishuQuestionCardController = class {
89178
+ static {
89179
+ __name(this, "FeishuQuestionCardController");
89180
+ }
89181
+ options;
89182
+ byRequest = /* @__PURE__ */ new Map();
89183
+ activeByScope = /* @__PURE__ */ new Map();
89184
+ disposed = false;
89185
+ constructor(options) {
89186
+ this.options = options;
89187
+ }
89188
+ async present(context) {
89189
+ if (this.disposed)
89190
+ return { kind: "unsupported" };
89191
+ const scopeKey = this.scopeKey(context);
89192
+ const active = this.activeByScope.get(scopeKey);
89193
+ if (active && active.state !== "terminal")
89194
+ return { kind: "unsupported" };
89195
+ const record2 = {
89196
+ context,
89197
+ requestId: context.requestId,
89198
+ runId: context.runId,
89199
+ ownerId: context.owner.id,
89200
+ chatId: context.target.chatId,
89201
+ scopeKey,
89202
+ state: "reserved"
89203
+ };
89204
+ this.byRequest.set(context.requestId, record2);
89205
+ this.activeByScope.set(scopeKey, record2);
89206
+ const unsubscribe = context.onSettled((reason) => {
89207
+ if (record2.state !== "claimed" || !record2.responding) {
89208
+ void this.finalize(record2, reason === "resolved_outside_presenter" ? "expired" : "cancelled");
89209
+ }
89210
+ });
89211
+ record2.unsubscribe = unsubscribe;
89212
+ if (record2.state === "terminal") {
89213
+ unsubscribe();
89214
+ record2.unsubscribe = void 0;
89215
+ return { kind: "presented" };
89216
+ }
89217
+ try {
89218
+ const messageId = await this.options.sendCard(record2.chatId, buildQuestionCard(context));
89219
+ if (!messageId)
89220
+ throw new Error("Feishu card delivery returned no message id");
89221
+ if (record2.state !== "reserved" || this.byRequest.get(record2.requestId) !== record2 || this.activeByScope.get(record2.scopeKey) !== record2) {
89222
+ await this.projectTerminal(record2, messageId);
89223
+ return { kind: "presented" };
89224
+ }
89225
+ record2.messageId = messageId;
89226
+ } catch (error) {
89227
+ if (this.isTerminated(record2))
89228
+ return { kind: "presented" };
89229
+ this.options.onError?.("question card delivery", error);
89230
+ await this.finalize(record2, "cancelled");
89231
+ try {
89232
+ await this.options.sendFallback(record2.chatId, this.fallbackText(record2.context));
89233
+ } catch (fallbackError) {
89234
+ this.options.onError?.("question fallback delivery", fallbackError);
89235
+ }
89236
+ try {
89237
+ await context.respond({ outcome: { outcome: "cancelled" } });
89238
+ } catch (respondError) {
89239
+ this.options.onError?.("question delivery cancellation", respondError);
89240
+ }
89241
+ return { kind: "handled" };
89242
+ }
89243
+ record2.state = "pending";
89244
+ record2.timer = setTimeout(() => {
89245
+ void this.expire(record2);
89246
+ }, this.options.timeoutMs);
89247
+ record2.timer.unref?.();
89248
+ return { kind: "presented" };
89249
+ }
89250
+ claim(data) {
89251
+ const action = parseQuestionAction(data);
89252
+ if (action.kind === "unhandled")
89253
+ return { kind: "unhandled" };
89254
+ const record2 = this.byRequest.get(action.requestId);
89255
+ if (!record2 || record2.state !== "pending")
89256
+ return this.expiredResponse();
89257
+ if (!action.operatorId || !action.chatId || !action.messageId || action.operatorId !== record2.ownerId || action.chatId !== record2.chatId || action.messageId !== record2.messageId) {
89258
+ return this.expiredResponse();
89259
+ }
89260
+ if (action.kind === "submit") {
89261
+ const answers = parseQuestionAnswers(record2.context.questions, action.formValue);
89262
+ if (!answers) {
89263
+ return {
89264
+ kind: "handled",
89265
+ response: {
89266
+ toast: { type: "warning", content: "\u8BF7\u5B8C\u6574\u9009\u62E9\u6709\u6548\u7B54\u6848\u3002" }
89267
+ }
89268
+ };
89269
+ }
89270
+ this.markClaimed(record2);
89271
+ return {
89272
+ kind: "handled",
89273
+ response: {
89274
+ toast: { type: "success", content: "\u7B54\u6848\u5DF2\u63D0\u4EA4\uFF0C\u6B63\u5728\u5904\u7406\u3002" },
89275
+ card: {
89276
+ type: "raw",
89277
+ data: buildQuestionTerminalCard(record2.context.questions, "processing", answers)
89278
+ }
89279
+ },
89280
+ execute: /* @__PURE__ */ __name(() => this.respond(record2, "submitted", answers), "execute")
89281
+ };
89282
+ }
89283
+ this.markClaimed(record2);
89284
+ record2.terminalDeliveredByClaim = true;
89285
+ return {
89286
+ kind: "handled",
89287
+ response: {
89288
+ toast: { type: "info", content: "\u5DF2\u53D6\u6D88\u3002" },
89289
+ card: {
89290
+ type: "raw",
89291
+ data: buildQuestionTerminalCard(record2.context.questions, "cancelled")
89292
+ }
89293
+ },
89294
+ execute: /* @__PURE__ */ __name(() => this.respond(record2, "cancelled"), "execute")
89295
+ };
89296
+ }
89297
+ cancelRun(runId, terminalState = "cancelled") {
89298
+ for (const record2 of [...this.byRequest.values()]) {
89299
+ if (record2.runId === runId)
89300
+ void this.finalize(record2, terminalState);
89301
+ }
89302
+ }
89303
+ dispose() {
89304
+ this.disposed = true;
89305
+ for (const record2 of [...this.byRequest.values()]) {
89306
+ record2.ignoreResponseProjection = true;
89307
+ void this.finalize(record2, "expired");
89308
+ }
89309
+ }
89310
+ async expire(record2) {
89311
+ if (record2.state !== "pending")
89312
+ return;
89313
+ await this.finalize(record2, "expired");
89314
+ try {
89315
+ await record2.context.respond({ outcome: { outcome: "cancelled" } });
89316
+ } catch (error) {
89317
+ this.options.onError?.("expired question cancellation", error);
89318
+ }
89319
+ }
89320
+ async respond(record2, terminalState, answers) {
89321
+ if (record2.state !== "claimed")
89322
+ return;
89323
+ record2.responding = true;
89324
+ try {
89325
+ const accepted = await record2.context.respond(terminalState === "submitted" ? {
89326
+ outcome: {
89327
+ outcome: "selected",
89328
+ optionId: record2.context.submitOptionId
89329
+ },
89330
+ answers
89331
+ } : { outcome: { outcome: "cancelled" } });
89332
+ record2.responding = false;
89333
+ if (!accepted) {
89334
+ this.options.onError?.("question response", new Error("Question response was no longer accepted"));
89335
+ } else if (terminalState === "submitted") {
89336
+ record2.terminalAnswers = answers;
89337
+ }
89338
+ await this.completeResponse(record2, accepted ? terminalState : "expired");
89339
+ } catch (error) {
89340
+ record2.responding = false;
89341
+ this.options.onError?.("question response", error);
89342
+ await this.completeResponse(record2, "expired");
89343
+ }
89344
+ }
89345
+ isTerminated(record2) {
89346
+ return record2.state === "terminal";
89347
+ }
89348
+ async finalize(record2, terminalState) {
89349
+ if (record2.state === "terminal")
89350
+ return;
89351
+ record2.state = "terminal";
89352
+ record2.terminalState = terminalState;
89353
+ if (record2.timer)
89354
+ clearTimeout(record2.timer);
89355
+ record2.timer = void 0;
89356
+ record2.unsubscribe?.();
89357
+ record2.unsubscribe = void 0;
89358
+ this.byRequest.delete(record2.requestId);
89359
+ if (this.activeByScope.get(record2.scopeKey) === record2) {
89360
+ this.activeByScope.delete(record2.scopeKey);
89361
+ }
89362
+ await this.projectTerminal(record2);
89363
+ }
89364
+ async completeResponse(record2, terminalState) {
89365
+ if (record2.state !== "terminal") {
89366
+ await this.finalize(record2, terminalState);
89367
+ return;
89368
+ }
89369
+ if (record2.ignoreResponseProjection)
89370
+ return;
89371
+ if (terminalState === "expired" && record2.terminalState)
89372
+ return;
89373
+ record2.terminalState = terminalState;
89374
+ await this.projectTerminal(record2);
89375
+ }
89376
+ projectTerminal(record2, messageId = record2.messageId) {
89377
+ if (!messageId || !record2.terminalState)
89378
+ return Promise.resolve();
89379
+ if (record2.terminalDeliveredByClaim)
89380
+ return Promise.resolve();
89381
+ const terminalState = record2.terminalState;
89382
+ const answers = record2.terminalAnswers;
89383
+ const card = buildQuestionTerminalCard(record2.context.questions, terminalState, answers);
89384
+ const projection = (record2.projection ?? Promise.resolve()).then(async () => {
89385
+ let patched = false;
89386
+ try {
89387
+ patched = await this.options.patchCard(messageId, card);
89388
+ if (!patched) {
89389
+ this.options.onError?.("question card finalization", new Error("Feishu card patch was not accepted"));
89390
+ }
89391
+ } catch (error) {
89392
+ this.options.onError?.("question card finalization", error);
89393
+ }
89394
+ if (!patched) {
89395
+ const details = record2.context.questions.map((question) => {
89396
+ const answer = answers?.[question.answerKey];
89397
+ return `${question.header}: ${answer ?? question.question}`;
89398
+ }).join("\n");
89399
+ try {
89400
+ await this.options.sendFallback(record2.chatId, `${terminalLabels[terminalState]}
89401
+ ${details}`);
89402
+ } catch (fallbackError) {
89403
+ this.options.onError?.("question terminal fallback delivery", fallbackError);
89404
+ }
89405
+ }
89406
+ });
89407
+ record2.projection = projection;
89408
+ return projection;
89409
+ }
89410
+ expiredResponse() {
89411
+ return {
89412
+ kind: "handled",
89413
+ response: {
89414
+ toast: { type: "warning", content: "\u8BE5\u95EE\u9898\u5DF2\u8FC7\u671F\u6216\u5DF2\u5904\u7406\u3002" }
89415
+ }
89416
+ };
89417
+ }
89418
+ markClaimed(record2) {
89419
+ record2.state = "claimed";
89420
+ if (record2.timer)
89421
+ clearTimeout(record2.timer);
89422
+ record2.timer = void 0;
89423
+ }
89424
+ scopeKey(context) {
89425
+ return `${context.sessionId}\0${context.owner.id}`;
89426
+ }
89427
+ fallbackText(context) {
89428
+ const questions = context.questions.map((question) => `- ${question.question}: ${question.options.map((option) => option.label).join(", ")}`).join("\n");
89429
+ return `\u4E92\u52A8\u95EE\u9898\u5361\u7247\u6295\u9012\u5931\u8D25\uFF0C\u8BE5\u8BF7\u6C42\u5DF2\u53D6\u6D88\uFF0C\u8BF7\u91CD\u8BD5\u3002
89430
+ ${questions}`;
89431
+ }
89432
+ };
89433
+
89000
89434
  // packages/channels/feishu/dist/FeishuAdapter.js
89001
89435
  var DEDUP_TTL_MS = 5 * 60 * 1e3;
89002
89436
  var OBSERVED_LABEL_CACHE_LIMIT = 500;
@@ -89025,6 +89459,17 @@ var FEISHU_STATUS_LABELS = `(?:${FEISHU_STATUS_STRINGS.map(escapeRegExp).join("|
89025
89459
  var FEISHU_STATUS_BLOCK_RE = new RegExp(`(?:^|\\n)---\\n\\*${FEISHU_STATUS_LABELS}\\*(?=\\n|$)`, "g");
89026
89460
  var BASE_URL2 = "https://open.feishu.cn/open-apis";
89027
89461
  var FEISHU_ID_RE2 = /^[a-zA-Z0-9_.:-]+$/;
89462
+ var FeishuCardDeliveryError = class extends Error {
89463
+ static {
89464
+ __name(this, "FeishuCardDeliveryError");
89465
+ }
89466
+ detail;
89467
+ constructor(message, detail) {
89468
+ super(message);
89469
+ this.detail = detail;
89470
+ this.name = "FeishuCardDeliveryError";
89471
+ }
89472
+ };
89028
89473
  var FeishuChannel = class extends ChannelBase {
89029
89474
  static {
89030
89475
  __name(this, "FeishuChannel");
@@ -89049,6 +89494,7 @@ var FeishuChannel = class extends ChannelBase {
89049
89494
  botOpenId;
89050
89495
  tokenCache;
89051
89496
  tokenRefreshPromise;
89497
+ questionCardController;
89052
89498
  // Core (non-silent) callers waiting on the shared token refresh, so a
89053
89499
  // silent-initiated refresh still logs token errors for them.
89054
89500
  tokenRefreshHasCoreWaiters = false;
@@ -89068,6 +89514,16 @@ var FeishuChannel = class extends ChannelBase {
89068
89514
  const feishuCfg = config;
89069
89515
  this.collapsible = feishuCfg["collapsible"] || false;
89070
89516
  this.collapsibleThreshold = feishuCfg["collapsibleThreshold"] || 500;
89517
+ this.questionCardController = new FeishuQuestionCardController({
89518
+ timeoutMs: 27e4,
89519
+ sendCard: /* @__PURE__ */ __name((chatId, card) => this.sendInteractiveCard(chatId, card), "sendCard"),
89520
+ patchCard: /* @__PURE__ */ __name((messageId, card) => this.patchInteractiveCard(messageId, card), "patchCard"),
89521
+ sendFallback: /* @__PURE__ */ __name((chatId, text) => this.sendMessageInternal(chatId, text, true), "sendFallback"),
89522
+ onError: /* @__PURE__ */ __name((operation, error) => {
89523
+ process.stderr.write(`[Feishu:${this.name}] ${operation} error: ${error instanceof Error ? error.message : error}
89524
+ `);
89525
+ }, "onError")
89526
+ });
89071
89527
  }
89072
89528
  supportsProactiveSend() {
89073
89529
  return true;
@@ -89083,6 +89539,19 @@ var FeishuChannel = class extends ChannelBase {
89083
89539
  "card.action.trigger": /* @__PURE__ */ __name((data) => {
89084
89540
  const payload = data;
89085
89541
  this.logDebugPayload("Feishu", payload);
89542
+ const question = this.questionCardController.claim(payload);
89543
+ if (question.kind === "handled") {
89544
+ const execute = question.execute;
89545
+ if (execute) {
89546
+ setImmediate(() => {
89547
+ execute().catch((error) => {
89548
+ process.stderr.write(`[Feishu:${this.name}] question action execution error: ${error instanceof Error ? error.message : error}
89549
+ `);
89550
+ });
89551
+ });
89552
+ }
89553
+ return question.response;
89554
+ }
89086
89555
  const stopped = this.onCardAction(payload);
89087
89556
  if (stopped) {
89088
89557
  return { toast: { type: "info", content: "\u5DF2\u505C\u6B62" } };
@@ -89679,65 +90148,40 @@ var FeishuChannel = class extends ChannelBase {
89679
90148
  }
89680
90149
  }
89681
90150
  // ----- Interactive Card Streaming -----
89682
- async createStreamingCard(chatId, text, title, inboundMsgId) {
90151
+ async sendInteractiveCard(chatId, card) {
89683
90152
  const token = await this.getTenantAccessToken();
89684
90153
  if (!token)
89685
- return { messageId: "", success: false };
89686
- const cardTitle = title || inboundMsgId && this.msgToQuestion.get(inboundMsgId) || "Qwen";
89687
- const card = buildCardContent(text, {
89688
- title: cardTitle,
89689
- showStopButton: true,
89690
- isStreaming: true,
89691
- statusLabel: this.statusLabelFor(),
89692
- collapsible: this.collapsible,
89693
- collapsibleThreshold: this.collapsibleThreshold
90154
+ throw new FeishuCardDeliveryError("Feishu card delivery failed: no access token");
90155
+ const resp = await fetch(`${BASE_URL2}/im/v1/messages?receive_id_type=chat_id`, {
90156
+ method: "POST",
90157
+ headers: {
90158
+ Authorization: `Bearer ${token}`,
90159
+ "Content-Type": "application/json"
90160
+ },
90161
+ body: JSON.stringify({
90162
+ receive_id: chatId,
90163
+ msg_type: "interactive",
90164
+ content: JSON.stringify(card)
90165
+ }),
90166
+ signal: AbortSignal.timeout(15e3)
89694
90167
  });
89695
- const body = {
89696
- receive_id: chatId,
89697
- msg_type: "interactive",
89698
- content: JSON.stringify(card)
89699
- };
89700
- try {
89701
- const resp = await fetch(`${BASE_URL2}/im/v1/messages?receive_id_type=chat_id`, {
89702
- method: "POST",
89703
- headers: {
89704
- Authorization: `Bearer ${token}`,
89705
- "Content-Type": "application/json"
89706
- },
89707
- body: JSON.stringify(body),
89708
- signal: AbortSignal.timeout(15e3)
89709
- });
89710
- if (!resp.ok) {
89711
- if (resp.status === 401)
89712
- this.tokenCache = void 0;
89713
- const detail = await resp.text().catch(() => "");
89714
- process.stderr.write(`[Feishu:${this.name}] createStreamingCard failed: HTTP ${resp.status} ${detail}
89715
- `);
89716
- return { messageId: "", success: false };
89717
- }
89718
- const data = await resp.json();
89719
- const messageId = data.data?.message_id || "";
89720
- return { messageId, success: !!messageId };
89721
- } catch (err) {
89722
- process.stderr.write(`[Feishu:${this.name}] createStreamingCard error: ${err}
89723
- `);
89724
- return { messageId: "", success: false };
90168
+ if (!resp.ok) {
90169
+ if (resp.status === 401)
90170
+ this.tokenCache = void 0;
90171
+ const detail = await resp.text().catch(() => "");
90172
+ const errorDetail = `HTTP ${resp.status} ${detail}`;
90173
+ throw new FeishuCardDeliveryError(`Feishu card delivery failed: ${errorDetail}`, errorDetail);
90174
+ }
90175
+ const data = await resp.json();
90176
+ const messageId = data.data?.message_id;
90177
+ if (!messageId) {
90178
+ throw new FeishuCardDeliveryError("Feishu card delivery returned no message id");
89725
90179
  }
90180
+ return messageId;
89726
90181
  }
89727
- async updateCard(messageId, text, finished = false, inboundMsgId, statusLabel) {
90182
+ async patchInteractiveCard(messageId, card) {
89728
90183
  const token = await this.getTenantAccessToken();
89729
- if (!token)
89730
- return false;
89731
- const cardTitle = inboundMsgId ? this.msgToQuestion.get(inboundMsgId) || "Qwen" : "Qwen";
89732
- const card = buildCardContent(text, {
89733
- title: cardTitle,
89734
- showStopButton: !finished,
89735
- isStreaming: !finished,
89736
- statusLabel: statusLabel ?? (!finished ? this.statusLabelFor() : void 0),
89737
- collapsible: this.collapsible,
89738
- collapsibleThreshold: this.collapsibleThreshold
89739
- });
89740
- if (!FEISHU_ID_RE2.test(messageId))
90184
+ if (!token || !FEISHU_ID_RE2.test(messageId))
89741
90185
  return false;
89742
90186
  try {
89743
90187
  const resp = await fetch(`${BASE_URL2}/im/v1/messages/${messageId}`, {
@@ -89767,6 +90211,52 @@ var FeishuChannel = class extends ChannelBase {
89767
90211
  return false;
89768
90212
  }
89769
90213
  }
90214
+ async createStreamingCard(chatId, text, title, inboundMsgId) {
90215
+ const cardTitle = title || inboundMsgId && this.msgToQuestion.get(inboundMsgId) || "Qwen";
90216
+ const card = buildCardContent(text, {
90217
+ title: cardTitle,
90218
+ showStopButton: true,
90219
+ isStreaming: true,
90220
+ statusLabel: this.statusLabelFor(),
90221
+ collapsible: this.collapsible,
90222
+ collapsibleThreshold: this.collapsibleThreshold
90223
+ });
90224
+ try {
90225
+ const messageId = await this.sendInteractiveCard(chatId, card);
90226
+ return { messageId, success: true };
90227
+ } catch (err) {
90228
+ if (err instanceof FeishuCardDeliveryError) {
90229
+ process.stderr.write(`[Feishu:${this.name}] createStreamingCard failed: ${err.detail ?? err.message}
90230
+ `);
90231
+ return { messageId: "", success: false };
90232
+ }
90233
+ process.stderr.write(`[Feishu:${this.name}] createStreamingCard error: ${err}
90234
+ `);
90235
+ return { messageId: "", success: false };
90236
+ }
90237
+ }
90238
+ async updateCard(messageId, text, finished = false, inboundMsgId, statusLabel) {
90239
+ const cardTitle = inboundMsgId ? this.msgToQuestion.get(inboundMsgId) || "Qwen" : "Qwen";
90240
+ const card = buildCardContent(text, {
90241
+ title: cardTitle,
90242
+ showStopButton: !finished,
90243
+ isStreaming: !finished,
90244
+ statusLabel: statusLabel ?? (!finished ? this.statusLabelFor() : void 0),
90245
+ collapsible: this.collapsible,
90246
+ collapsibleThreshold: this.collapsibleThreshold
90247
+ });
90248
+ return this.patchInteractiveCard(messageId, card);
90249
+ }
90250
+ async presentUserInputRequest(context) {
90251
+ if (!context.precedingSegmentId) {
90252
+ const inboundMsgId = this.sessionToInboundMsg.get(context.sessionId);
90253
+ const cardState = inboundMsgId ? this.cardSessions.get(inboundMsgId) : void 0;
90254
+ if (inboundMsgId && cardState) {
90255
+ await this.endOutputCardBeforeInputRequest(context.target.chatId, inboundMsgId, cardState);
90256
+ }
90257
+ }
90258
+ return this.questionCardController.present(context);
90259
+ }
89770
90260
  /** Delete a card message from Feishu to prevent orphaned "思考中..." cards. */
89771
90261
  async deleteCard(messageId) {
89772
90262
  const token = await this.getTenantAccessToken();
@@ -89818,6 +90308,7 @@ var FeishuChannel = class extends ChannelBase {
89818
90308
  }
89819
90309
  if (cardState.stopped)
89820
90310
  return;
90311
+ cardState.boundaryText = void 0;
89821
90312
  const MAX_ACCUMULATE = 25e3;
89822
90313
  cardState.accumulatedText += chunk;
89823
90314
  if (cardState.accumulatedText.length > MAX_ACCUMULATE) {
@@ -89827,12 +90318,14 @@ var FeishuChannel = class extends ChannelBase {
89827
90318
  return;
89828
90319
  if (!cardState.created && !cardState.cardCreationFailed) {
89829
90320
  cardState.creating = true;
90321
+ cardState.lastUpdateAt = Date.now();
89830
90322
  const cs = cardState;
89831
90323
  cardState.creationTimer = setTimeout(async () => {
89832
90324
  try {
89833
90325
  if (cs.stopped || this.stoppedMessages.has(inboundMsgId)) {
89834
90326
  cs.creating = false;
89835
- this.cleanupCard(inboundMsgId);
90327
+ if (!cs.abandoned)
90328
+ this.cleanupCard(inboundMsgId);
89836
90329
  return;
89837
90330
  }
89838
90331
  const atPrefix = this.msgToSenderName.get(inboundMsgId);
@@ -89879,36 +90372,50 @@ ${cs.accumulatedText}` : cs.accumulatedText;
89879
90372
  const cs = cardState;
89880
90373
  const elapsed = Date.now() - cardState.lastUpdateAt;
89881
90374
  const delay = Math.max(0, CARD_UPDATE_INTERVAL_MS - elapsed);
89882
- cardState.pendingUpdateTimer = setTimeout(async () => {
90375
+ cardState.pendingUpdateTimer = setTimeout(() => {
89883
90376
  cs.pendingUpdateTimer = void 0;
89884
90377
  if (cs.stopped || cs.finalizing)
89885
90378
  return;
89886
90379
  cs.lastUpdateAt = Date.now();
89887
- try {
89888
- const MAX_CARD_CHARS = 2e4;
89889
- const atPrefix = this.msgToSenderName.get(inboundMsgId);
89890
- let displayContent = atPrefix ? `${atPrefix}
89891
-
89892
- ${cs.accumulatedText}` : cs.accumulatedText;
89893
- if (displayContent.length > MAX_CARD_CHARS) {
89894
- const marker = "\n\n_(\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\u65E9\u671F\u5185\u5BB9)_";
89895
- displayContent = displayContent.slice(-(MAX_CARD_CHARS - marker.length)) + marker;
89896
- if (this.countFences(displayContent) % 2 === 1) {
89897
- displayContent = "```\n" + displayContent;
89898
- }
89899
- }
89900
- const ok = await this.updateCard(cs.messageId, displayContent, false, inboundMsgId);
89901
- if (!ok) {
89902
- const stripped = this.stripTables(displayContent, "(\u8868\u683C)");
89903
- await this.updateCard(cs.messageId, stripped, false, inboundMsgId);
89904
- }
89905
- } catch (err) {
90380
+ if (cs.pendingUpdatePromise) {
90381
+ cs.updateQueued = true;
90382
+ return;
90383
+ }
90384
+ cs.pendingUpdatePromise = this.runThrottledCardUpdate(inboundMsgId, cs).catch((err) => {
89906
90385
  process.stderr.write(`[Feishu:${this.name}] card update error: ${err}
89907
90386
  `);
89908
- }
90387
+ }).then(() => {
90388
+ cs.pendingUpdatePromise = void 0;
90389
+ });
89909
90390
  }, delay);
89910
90391
  }
89911
90392
  }
90393
+ /** Runs one throttled streaming PATCH, then re-runs once when timer fires
90394
+ * coalesced behind it (`updateQueued`) so the latest buffer still goes out.
90395
+ * `pendingUpdatePromise` covers the whole chain so finalization can drain
90396
+ * every in-flight update before sending the final patch. */
90397
+ async runThrottledCardUpdate(inboundMsgId, cs) {
90398
+ if (cs.stopped || cs.finalizing)
90399
+ return;
90400
+ try {
90401
+ const atPrefix = this.msgToSenderName.get(inboundMsgId);
90402
+ const displayContent = this.truncateCardText(atPrefix ? `${atPrefix}
90403
+
90404
+ ${cs.accumulatedText}` : cs.accumulatedText);
90405
+ const ok = await this.updateCard(cs.messageId, displayContent, false, inboundMsgId);
90406
+ if (!ok && !cs.stopped && !cs.finalizing) {
90407
+ const stripped = this.stripTables(displayContent, "(\u8868\u683C)");
90408
+ await this.updateCard(cs.messageId, stripped, false, inboundMsgId);
90409
+ }
90410
+ } catch (err) {
90411
+ process.stderr.write(`[Feishu:${this.name}] card update error: ${err}
90412
+ `);
90413
+ }
90414
+ if (cs.updateQueued) {
90415
+ cs.updateQueued = false;
90416
+ await this.runThrottledCardUpdate(inboundMsgId, cs);
90417
+ }
90418
+ }
89912
90419
  onResponseBoundary(_chatId, sessionId) {
89913
90420
  if (this.config.blockStreaming === "on")
89914
90421
  return;
@@ -89922,8 +90429,90 @@ ${cs.accumulatedText}` : cs.accumulatedText;
89922
90429
  clearTimeout(cardState.pendingUpdateTimer);
89923
90430
  cardState.pendingUpdateTimer = void 0;
89924
90431
  }
90432
+ cardState.updateQueued = false;
90433
+ if (cardState.accumulatedText) {
90434
+ cardState.boundaryText = cardState.accumulatedText;
90435
+ }
89925
90436
  cardState.accumulatedText = "";
89926
90437
  }
90438
+ async onOutputSegmentEnd(chatId, sessionId, _segment, reason) {
90439
+ if (reason === "response_boundary") {
90440
+ this.onResponseBoundary(chatId, sessionId);
90441
+ return;
90442
+ }
90443
+ if (reason !== "input_requested" || this.config.blockStreaming === "on") {
90444
+ return;
90445
+ }
90446
+ const inboundMsgId = this.sessionToInboundMsg.get(sessionId);
90447
+ if (!inboundMsgId)
90448
+ return;
90449
+ const cardState = this.cardSessions.get(inboundMsgId);
90450
+ if (!cardState)
90451
+ return;
90452
+ await this.endOutputCardBeforeInputRequest(chatId, inboundMsgId, cardState);
90453
+ }
90454
+ async endOutputCardBeforeInputRequest(chatId, inboundMsgId, cardState) {
90455
+ if (cardState.cancelling || cardState.stopped || cardState.finalizing || this.stoppedMessages.has(inboundMsgId)) {
90456
+ return;
90457
+ }
90458
+ const atPrefix = this.msgToSenderName.get(inboundMsgId);
90459
+ const text = cardState.accumulatedText || cardState.boundaryText || "";
90460
+ const displayText = atPrefix ? text ? `${atPrefix}
90461
+
90462
+ ${text}` : atPrefix : text;
90463
+ const completedSuffix = `
90464
+
90465
+ ---
90466
+ *${this.statusLabelFor("completed")}*`;
90467
+ const prefixPart = atPrefix && text ? `${atPrefix}
90468
+
90469
+ ` : "";
90470
+ const finalText = text ? prefixPart + this.truncateCardText(text, prefixPart.length + completedSuffix.length) : displayText;
90471
+ try {
90472
+ if (cardState.created && cardState.messageId && !cardState.stopped) {
90473
+ cardState.finalizing = true;
90474
+ if (cardState.pendingUpdateTimer) {
90475
+ clearTimeout(cardState.pendingUpdateTimer);
90476
+ cardState.pendingUpdateTimer = void 0;
90477
+ }
90478
+ if (cardState.pendingUpdatePromise) {
90479
+ await cardState.pendingUpdatePromise;
90480
+ }
90481
+ let updated = false;
90482
+ try {
90483
+ if (await this.finalizeStoppedCardUpdate(inboundMsgId, cardState, chatId)) {
90484
+ return;
90485
+ }
90486
+ updated = await this.updateCard(cardState.messageId, finalText, true, inboundMsgId, this.statusLabelFor("completed"));
90487
+ if (!updated) {
90488
+ const noTableText = this.stripTables(finalText, "(\u8868\u683C\u5185\u5BB9\u8BF7\u67E5\u770B\u539F\u6587)");
90489
+ updated = await this.updateCard(cardState.messageId, noTableText, true, inboundMsgId, this.statusLabelFor("completed"));
90490
+ }
90491
+ if (await this.finalizeStoppedCardUpdate(inboundMsgId, cardState, chatId)) {
90492
+ return;
90493
+ }
90494
+ } catch (error) {
90495
+ process.stderr.write(`[Feishu:${this.name}] input-request card finalization error: ${error instanceof Error ? error.message : error}
90496
+ `);
90497
+ }
90498
+ if (!updated) {
90499
+ await this.deleteCard(cardState.messageId);
90500
+ if (displayText)
90501
+ await this.sendMessage(chatId, displayText);
90502
+ }
90503
+ } else {
90504
+ if (cardState.creating) {
90505
+ cardState.stopped = true;
90506
+ cardState.abandoned = true;
90507
+ }
90508
+ if (text) {
90509
+ await this.sendMessage(chatId, displayText);
90510
+ }
90511
+ }
90512
+ } finally {
90513
+ this.releaseOutputCard(inboundMsgId);
90514
+ }
90515
+ }
89927
90516
  isKnownInboundMessageId(messageId) {
89928
90517
  return this.msgToQuestion.has(messageId) || this.msgToSenderName.has(messageId) || this.msgToSenderId.has(messageId) || this.cardSessions.has(messageId) || this.stoppedMessages.has(messageId);
89929
90518
  }
@@ -89968,6 +90557,9 @@ ${contentPart}` : contentPart;
89968
90557
  if (!isTerminalTaskLifecycleType(event.type)) {
89969
90558
  return;
89970
90559
  }
90560
+ if (event.runId) {
90561
+ this.questionCardController.cancelRun(event.runId, event.type === "cancelled" && (event.reason === "cancel_command" || event.reason === "clear") ? "cancelled" : "expired");
90562
+ }
89971
90563
  const inboundMsgId = this.knownInboundMessageId(event.sessionId, event.messageId);
89972
90564
  if (!inboundMsgId)
89973
90565
  return;
@@ -89997,34 +90589,22 @@ ${contentPart}` : contentPart;
89997
90589
  return;
89998
90590
  }
89999
90591
  const atSender = this.msgToSenderName.get(inboundMsgId);
90000
- let displayText = atSender ? `${atSender}
90001
-
90002
- ${fullText}` : fullText;
90003
90592
  const completedLabel = this.statusLabelFor("completed");
90004
90593
  const completedSuffix = `
90005
90594
 
90006
90595
  ---
90007
90596
  *${completedLabel}*`;
90008
- const MAX_FINAL_CARD_CHARS = 2e4;
90009
- if (displayText.length + completedSuffix.length > MAX_FINAL_CARD_CHARS) {
90010
- const prefix = atSender ? `${atSender}
90597
+ const atPrefix = atSender ? `${atSender}
90011
90598
 
90012
90599
  ` : "";
90013
- const suffix = "\n\n_(\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\u65E9\u671F\u5185\u5BB9)_";
90014
- const fenceReserve = 4;
90015
- const maxBody = MAX_FINAL_CARD_CHARS - prefix.length - suffix.length - completedSuffix.length - fenceReserve;
90016
- displayText = prefix + fullText.slice(-maxBody) + suffix;
90017
- if (this.countFences(displayText) % 2 === 1) {
90018
- displayText = "```\n" + displayText;
90019
- }
90020
- }
90600
+ const displayText = atPrefix + this.truncateCardText(fullText, atPrefix.length + completedSuffix.length);
90021
90601
  if (cardState)
90022
90602
  cardState.finalizing = true;
90023
90603
  if (cardState?.pendingUpdateTimer) {
90024
90604
  clearTimeout(cardState.pendingUpdateTimer);
90025
90605
  }
90026
- if (cardState?.creationTimer) {
90027
- clearTimeout(cardState.creationTimer);
90606
+ if (cardState?.pendingUpdatePromise) {
90607
+ await cardState.pendingUpdatePromise;
90028
90608
  }
90029
90609
  if (cardState?.creating) {
90030
90610
  await new Promise((resolve) => {
@@ -90099,60 +90679,20 @@ ${fullText}` : fullText);
90099
90679
 
90100
90680
  ${fullText}` : fullText);
90101
90681
  }
90102
- onPromptStart(chatId, sessionId, messageId) {
90682
+ onPromptStart(_chatId, sessionId, messageId) {
90103
90683
  const inboundMsgId = messageId && this.isKnownInboundMessageId(messageId) ? messageId : void 0;
90104
90684
  if (inboundMsgId) {
90105
90685
  this.sessionToInboundMsg.set(sessionId, inboundMsgId);
90106
90686
  this.addReaction(inboundMsgId, "OnIt").catch(() => {
90107
90687
  });
90108
- if (this.config.blockStreaming === "on")
90109
- return;
90110
- if (!this.cardSessions.has(inboundMsgId)) {
90111
- const atSender = this.msgToSenderName.get(inboundMsgId) || "";
90112
- const placeholderText = atSender ? `${atSender}\uFF0C\u601D\u8003\u4E2D...` : "\u601D\u8003\u4E2D...";
90113
- const cardState = {
90688
+ if (this.config.blockStreaming !== "on" && !this.cardSessions.has(inboundMsgId)) {
90689
+ this.cardSessions.set(inboundMsgId, {
90114
90690
  messageId: "",
90115
90691
  created: false,
90116
- creating: true,
90692
+ creating: false,
90117
90693
  stopped: false,
90118
90694
  accumulatedText: "",
90119
90695
  lastUpdateAt: Date.now()
90120
- };
90121
- this.cardSessions.set(inboundMsgId, cardState);
90122
- this.createStreamingCard(chatId, placeholderText, void 0, inboundMsgId).then((result) => {
90123
- if (cardState.stopped || this.stoppedMessages.has(inboundMsgId)) {
90124
- if (cardState.abandoned) {
90125
- if (result.success) {
90126
- this.deleteCard(result.messageId).catch((err) => {
90127
- process.stderr.write(`[Feishu:${this.name}] ORPHANED CARD: failed to delete abandoned card msg=${result.messageId}: ${err instanceof Error ? err.message : err}
90128
- `);
90129
- });
90130
- }
90131
- cardState.creating = false;
90132
- return;
90133
- }
90134
- if (result.success) {
90135
- const prefix = cardState.atPrefix || this.msgToSenderName.get(inboundMsgId) || "";
90136
- this.updateCard(result.messageId, prefix, true, inboundMsgId, this.stopLabelFor(cardState.terminalStatus, cardState.userStopped ?? false)).catch(() => {
90137
- });
90138
- }
90139
- cardState.creating = false;
90140
- this.cleanupCard(inboundMsgId);
90141
- return;
90142
- }
90143
- if (result.success) {
90144
- cardState.messageId = result.messageId;
90145
- cardState.created = true;
90146
- cardState.lastUpdateAt = Date.now();
90147
- } else {
90148
- cardState.cardCreationFailed = true;
90149
- }
90150
- cardState.creating = false;
90151
- }).catch((err) => {
90152
- process.stderr.write(`[Feishu:${this.name}] Processing card error: ${err}
90153
- `);
90154
- cardState.creating = false;
90155
- this.cleanupCard(inboundMsgId);
90156
90696
  });
90157
90697
  }
90158
90698
  }
@@ -90168,6 +90708,14 @@ ${fullText}` : fullText);
90168
90708
  cs.stopped = true;
90169
90709
  } else if (cs.created) {
90170
90710
  cs.stopped = true;
90711
+ cs.finalizing = true;
90712
+ if (cs.pendingUpdateTimer) {
90713
+ clearTimeout(cs.pendingUpdateTimer);
90714
+ cs.pendingUpdateTimer = void 0;
90715
+ }
90716
+ if (cs.pendingUpdatePromise) {
90717
+ await cs.pendingUpdatePromise;
90718
+ }
90171
90719
  const atPrefix = this.msgToSenderName.get(inboundMsgId) || "";
90172
90720
  const terminalStatus = cs.terminalStatus ?? (cs.cancelling ? "cancelled" : "failed");
90173
90721
  const terminalLabel = this.stopLabelFor(terminalStatus, cs.userStopped ?? false);
@@ -90185,7 +90733,7 @@ ${cs.accumulatedText}` : cs.accumulatedText : atPrefix || "";
90185
90733
  ${cs.accumulatedText}` : cs.accumulatedText;
90186
90734
  this.sendMessage(_chatId, fallbackText).catch(() => {
90187
90735
  });
90188
- } else {
90736
+ } else if (cs.terminalStatus !== "completed") {
90189
90737
  const atPrefix = this.msgToSenderName.get(inboundMsgId) || "";
90190
90738
  const fallbackLabel = cs.terminalStatus ? this.statusLabelFor(cs.terminalStatus) : "\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
90191
90739
  const errorText = atPrefix ? `${atPrefix}
@@ -90325,6 +90873,13 @@ ${cs.accumulatedText}` : cs.accumulatedText;
90325
90873
  }
90326
90874
  if (cardState.finalizing)
90327
90875
  return;
90876
+ if (cardState.pendingUpdateTimer) {
90877
+ clearTimeout(cardState.pendingUpdateTimer);
90878
+ cardState.pendingUpdateTimer = void 0;
90879
+ }
90880
+ if (cardState.pendingUpdatePromise) {
90881
+ await cardState.pendingUpdatePromise;
90882
+ }
90328
90883
  if (cardState.created && cardState.messageId) {
90329
90884
  const prefix = cardState.atPrefix || this.msgToSenderName.get(inboundId) || "";
90330
90885
  const stopLabel = cancelSucceeded ? this.stopLabelFor(cardState.terminalStatus, wasUserStop) : FEISHU_STOP_FAILED_STATUS_LABEL;
@@ -90355,6 +90910,7 @@ ${contentPart}` : prefix : contentPart;
90355
90910
  }
90356
90911
  }
90357
90912
  disconnect() {
90913
+ this.questionCardController.dispose();
90358
90914
  if (this.dedupTimer) {
90359
90915
  clearInterval(this.dedupTimer);
90360
90916
  this.dedupTimer = void 0;
@@ -90429,6 +90985,21 @@ ${contentPart}` : prefix : contentPart;
90429
90985
  }
90430
90986
  return result.join("\n");
90431
90987
  }
90988
+ /** Truncate card content to the Feishu card size limit, keeping the tail.
90989
+ * `reservedChars` covers content rendered alongside the text (greeting
90990
+ * prefix, status block) that must fit the same limit. */
90991
+ truncateCardText(text, reservedChars = 0) {
90992
+ const MAX_CARD_CHARS = 2e4;
90993
+ if (text.length + reservedChars <= MAX_CARD_CHARS)
90994
+ return text;
90995
+ const marker = "\n\n_(\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\u65E9\u671F\u5185\u5BB9)_";
90996
+ const fenceReserve = 4;
90997
+ let truncated = text.slice(-(MAX_CARD_CHARS - marker.length - fenceReserve - reservedChars)) + marker;
90998
+ if (this.countFences(truncated) % 2 === 1) {
90999
+ truncated = "```\n" + truncated;
91000
+ }
91001
+ return truncated;
91002
+ }
90432
91003
  cleanupCard(inboundMsgId) {
90433
91004
  const cardState = this.cardSessions.get(inboundMsgId);
90434
91005
  if (cardState?.pendingUpdateTimer) {
@@ -90449,6 +91020,30 @@ ${contentPart}` : prefix : contentPart;
90449
91020
  }
90450
91021
  }
90451
91022
  }
91023
+ releaseOutputCard(inboundMsgId) {
91024
+ const cardState = this.cardSessions.get(inboundMsgId);
91025
+ if (!cardState)
91026
+ return;
91027
+ if (cardState.pendingUpdateTimer) {
91028
+ clearTimeout(cardState.pendingUpdateTimer);
91029
+ }
91030
+ if (cardState.creationTimer) {
91031
+ clearTimeout(cardState.creationTimer);
91032
+ }
91033
+ this.cardSessions.set(inboundMsgId, {
91034
+ messageId: "",
91035
+ created: false,
91036
+ creating: false,
91037
+ // Carry a settled user stop (not the abandoned-creation marker) so a
91038
+ // late-settled stop cannot flip onPromptEnd into a contradictory
91039
+ // terminal message.
91040
+ stopped: cardState.stopped && !cardState.abandoned,
91041
+ accumulatedText: "",
91042
+ lastUpdateAt: Date.now(),
91043
+ userStopped: cardState.userStopped,
91044
+ terminalStatus: cardState.terminalStatus
91045
+ });
91046
+ }
90452
91047
  // ----- Message handling -----
90453
91048
  onMessage(data) {
90454
91049
  try {