@qwen-code/qwen-code 0.21.7 → 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.
- package/README.md +2 -0
- package/bundled/qc-helper/docs/configuration/settings.md +43 -30
- package/bundled/qc-helper/docs/features/channels/dingtalk.md +40 -2
- package/bundled/qc-helper/docs/features/channels/feishu.md +13 -2
- package/bundled/qc-helper/docs/features/channels/github.md +13 -11
- package/bundled/qc-helper/docs/features/channels/gitlab.md +13 -11
- package/bundled/qc-helper/docs/features/channels/overview.md +49 -31
- package/bundled/qc-helper/docs/features/channels/plugins.md +2 -2
- package/bundled/qc-helper/docs/features/channels/qqbot.md +4 -2
- package/bundled/qc-helper/docs/features/channels/telegram.md +4 -2
- package/bundled/qc-helper/docs/features/channels/wecom.md +1 -1
- package/bundled/qc-helper/docs/features/code-review.md +4 -0
- package/bundled/qc-helper/docs/features/commands.md +1 -1
- package/bundled/qc-helper/docs/features/hooks.md +52 -0
- package/bundled/qc-helper/docs/integration-jetbrains.md +1 -0
- package/bundled/qc-helper/docs/qwen-serve.md +4 -1
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +50 -36
- package/bundled/review/SKILL.md +28 -5
- package/chunks/{MaxSizedBox-ANWZBPTS.js → MaxSizedBox-7PM6BGJ5.js} +26 -22
- package/chunks/{StandaloneSessionPicker-XKS3VU3A.js → StandaloneSessionPicker-3UQHM7GV.js} +44 -40
- package/chunks/{acp-startup-profiler-ORIQ2CCQ.js → acp-startup-profiler-B5BYAMYQ.js} +2 -2
- package/chunks/{acpAgent-KUAZ3GCZ.js → acpAgent-5UWLFV6V.js} +534 -262
- package/chunks/{agent-T6PTGX5R.js → agent-624T2BLO.js} +26 -22
- package/chunks/{agent-headless-PR7YCB7S.js → agent-headless-2EE5J2KX.js} +26 -22
- package/chunks/{artifact-tool-U4VOZIK5.js → artifact-tool-N652YE4L.js} +1 -1
- package/chunks/{askUserQuestion-XOBQLPFA.js → askUserQuestion-ONW74PKJ.js} +1 -1
- package/chunks/{bridge-NU6YEEHK.js → bridge-JENKGFFP.js} +29 -25
- package/chunks/{ca-NYKNH222.js → ca-ZLKAB4K3.js} +6 -0
- package/chunks/{channel-management-service-FSQ7SHYI.js → channel-management-service-DDWUPHMU.js} +19 -10
- package/chunks/{channel-settings-store-35VQVUVV.js → channel-settings-store-SA6JZSPH.js} +34 -30
- package/chunks/{channel-worker-group-JWQK224X.js → channel-worker-group-E67EN3RV.js} +5 -5
- package/chunks/{channel-worker-manager-77E3OXRQ.js → channel-worker-manager-SW4C45CF.js} +5 -5
- package/chunks/{channel-worker-supervisor-62YWUGP2.js → channel-worker-supervisor-5SRD24FG.js} +3 -3
- package/chunks/{chunk-CJXIIILK.js → chunk-2FRY5CRX.js} +1 -1
- package/chunks/{chunk-ZJ3VGYHK.js → chunk-2ILAOM2I.js} +34 -17
- package/chunks/{chunk-6XJMFJ4D.js → chunk-2M4K4KYS.js} +177 -120
- package/chunks/{chunk-CNIID3TV.js → chunk-2UUMVNYT.js} +1 -1
- package/chunks/{chunk-22NBYCPD.js → chunk-3P2LV43B.js} +1 -1
- package/chunks/{chunk-2U3WZGZG.js → chunk-3PY4LPJF.js} +19 -131
- package/chunks/{chunk-SPMY6CX6.js → chunk-3SE7J4DR.js} +3 -3
- package/chunks/{chunk-6UWFTUQL.js → chunk-3WNQOYHQ.js} +66 -22
- package/chunks/{chunk-KXSDEOFU.js → chunk-4ALIARFY.js} +1 -1
- package/chunks/{chunk-D3UEZIQH.js → chunk-4DU3NCHG.js} +48 -55
- package/chunks/{chunk-BGG4MBYD.js → chunk-4PYCZH2V.js} +4 -187
- package/chunks/{chunk-H2UQ2M5Z.js → chunk-4WU6NY7F.js} +96 -22
- package/chunks/{chunk-TLV2IMHR.js → chunk-5ZGR6RKJ.js} +3 -3
- package/chunks/{chunk-3K7FH2KQ.js → chunk-67N6HB5H.js} +1310 -171
- package/chunks/{chunk-EORNAQDT.js → chunk-6TR7CFXH.js} +1 -1
- package/chunks/{chunk-NG2R4N5O.js → chunk-6ZRFAKXK.js} +1 -1
- package/chunks/{chunk-P2AJ7FTI.js → chunk-757GB46F.js} +1 -1
- package/chunks/{chunk-72LNFGUY.js → chunk-77QVBFCU.js} +3 -3
- package/chunks/{chunk-OH2VKQXH.js → chunk-7DVT4LVV.js} +37 -30
- package/chunks/{chunk-KKJJB5X6.js → chunk-7VUERJHS.js} +1503 -815
- package/chunks/{chunk-VOARQPTA.js → chunk-B52AWKBB.js} +65 -21
- package/chunks/{chunk-Y4EWSQF7.js → chunk-BF224XHL.js} +2 -2
- package/chunks/{chunk-PJOBIWUG.js → chunk-BF52U4XJ.js} +1 -1
- package/chunks/{chunk-55LYDVPU.js → chunk-C5VWPTGT.js} +1 -1
- package/chunks/{chunk-W7U4ESW2.js → chunk-CG3WBKJK.js} +1 -1
- package/chunks/chunk-COBO5EBO.js +135 -0
- package/chunks/chunk-CPG6P4GG.js +82 -0
- package/chunks/{chunk-DIEFUBV6.js → chunk-DIWZNWZT.js} +205 -35
- package/chunks/{chunk-AE77C5ZU.js → chunk-DQSDACD2.js} +1 -1
- package/chunks/{chunk-P3LEG54R.js → chunk-DX5W5AON.js} +2 -2
- package/chunks/{chunk-EUQTXRKZ.js → chunk-E4ZBKMSF.js} +5 -5
- package/chunks/{chunk-FPM27XN4.js → chunk-EIVICVHM.js} +4 -4
- package/chunks/{chunk-YHEEE624.js → chunk-EN2TKTFH.js} +1 -1
- package/chunks/chunk-F6WFNA7U.js +22 -0
- package/chunks/{chunk-FZBZSYKU.js → chunk-FN6YXJOP.js} +1 -1
- package/chunks/{chunk-KR4ZSC7K.js → chunk-FWBXMANW.js} +3 -3
- package/chunks/{chunk-LA7YLSR6.js → chunk-FYAXKJK7.js} +327 -67
- package/chunks/{chunk-CSZEXZBE.js → chunk-GBDINRIL.js} +3 -3
- package/chunks/{chunk-SCI7K3GM.js → chunk-GOEVOFQI.js} +19 -10
- package/chunks/{chunk-LEMXGVEP.js → chunk-GQCEQPYQ.js} +3 -3
- package/chunks/{chunk-Y7E5LNLO.js → chunk-GXSNGY5M.js} +1027 -876
- package/chunks/{chunk-6XU3PH66.js → chunk-HA3SAB64.js} +22 -69
- package/chunks/{chunk-Y4NGLFGJ.js → chunk-HUWENAHO.js} +1 -1
- package/chunks/{chunk-3ULCB3NE.js → chunk-HV76SFIA.js} +1 -1
- package/chunks/{chunk-CB2464BK.js → chunk-HWX5HPUG.js} +14 -4
- package/chunks/{chunk-LZC3B5N2.js → chunk-IA7TGCN2.js} +2 -2
- package/chunks/{chunk-RERATVSK.js → chunk-IBYULW65.js} +6 -6
- package/chunks/{chunk-HYRDKNUY.js → chunk-IUQ52YJK.js} +1 -1
- package/chunks/{chunk-TDXGKHDN.js → chunk-IYES5WOT.js} +2 -2
- package/chunks/{chunk-RGSBTHSU.js → chunk-KAQCJO6Y.js} +131 -4
- package/chunks/{chunk-VWOVHOTT.js → chunk-KJZ26VBX.js} +1 -1
- package/chunks/{chunk-6GONZVLS.js → chunk-KKDVZLGL.js} +1 -1
- package/chunks/{chunk-MKVZE4ZJ.js → chunk-KTJFU7RT.js} +3 -2
- package/chunks/{chunk-R574ATRM.js → chunk-M2PNLYGY.js} +41 -0
- package/chunks/{chunk-6EOI4HOK.js → chunk-M3STHEMM.js} +12 -17
- package/chunks/chunk-NGYI5EF5.js +244 -0
- package/chunks/{chunk-ALGGS7UH.js → chunk-NPQ5ZKRP.js} +82 -1
- package/chunks/{chunk-HQB2KUAN.js → chunk-NPUXXRJI.js} +1 -1
- package/chunks/{chunk-QETYKPMG.js → chunk-NVRDQFCX.js} +1 -1
- package/chunks/{chunk-PQBHU2IA.js → chunk-OHKJVAKG.js} +10 -10
- package/chunks/{chunk-CYR3HI5X.js → chunk-OQTXYMKW.js} +2 -2
- package/chunks/{chunk-DBOFL3LQ.js → chunk-PG62DFWD.js} +10 -10
- package/chunks/{chunk-2VSTGY6M.js → chunk-PJRW65JO.js} +1 -1
- package/chunks/{chunk-33ACCIIY.js → chunk-PLFATELK.js} +1 -1
- package/chunks/{chunk-IC4Z6LX6.js → chunk-PYQADEFD.js} +5 -0
- package/chunks/{chunk-MAJS7AT4.js → chunk-QGHSP65Z.js} +2 -2
- package/chunks/{chunk-OHJLEW5J.js → chunk-QQWD7LZV.js} +4 -4
- package/chunks/{chunk-ZXU5UHMI.js → chunk-QXVSWG66.js} +2 -2
- package/chunks/{chunk-E33LOKRA.js → chunk-RPWVIXDB.js} +18 -1
- package/chunks/{chunk-TYKC75AX.js → chunk-S3Y3GBFD.js} +1 -1
- package/chunks/{chunk-7UFKAV7Y.js → chunk-S6HYI3MF.js} +2 -2
- package/chunks/chunk-SAH4BD2J.js +92 -0
- package/chunks/{chunk-OMKQH5C5.js → chunk-SNRT2TJJ.js} +6 -23
- package/chunks/chunk-SR7RZ4MS.js +202 -0
- package/chunks/{chunk-CXE7E23H.js → chunk-TE3ZAJE7.js} +45 -17
- package/chunks/{chunk-S7CV4KO6.js → chunk-TKSZJ5BV.js} +3 -3
- package/chunks/{chunk-3NB7TSE2.js → chunk-U5SLIG7E.js} +1 -1
- package/chunks/chunk-UA5H3DS2.js +203 -0
- package/chunks/{chunk-24ER7UV4.js → chunk-UFALT4LK.js} +1 -1
- package/chunks/{chunk-YJQCUTT2.js → chunk-VWMUDKLC.js} +3 -3
- package/chunks/{chunk-RMH5OWLD.js → chunk-VXZ5HAOV.js} +1 -1
- package/chunks/{chunk-BVWVWGLE.js → chunk-WAUGQKUU.js} +4 -64
- package/chunks/{chunk-SHZYHGQH.js → chunk-WG6542MA.js} +1 -1
- package/chunks/{chunk-5KH532V7.js → chunk-WV5J6Q6N.js} +1 -1
- package/chunks/{chunk-RNVQB725.js → chunk-XHD7CRP2.js} +2 -2
- package/chunks/{chunk-W4B7UBUS.js → chunk-XZKQT2B2.js} +5 -5
- package/chunks/{chunk-6HVUFDS2.js → chunk-Y4TETC74.js} +22 -13
- package/chunks/{chunk-RZHU3ILK.js → chunk-YEF7XEO2.js} +4 -4
- package/chunks/{chunk-RUL4S3K3.js → chunk-YHJFF7KH.js} +146 -45
- package/chunks/{chunk-23RZCH76.js → chunk-YOM7DEGB.js} +3 -3
- package/chunks/{chunk-OFI7IGST.js → chunk-ZCLLJARV.js} +9 -9
- package/chunks/{chunk-GSS34377.js → chunk-ZHA242R4.js} +2 -2
- package/chunks/{chunk-TRLYP7OF.js → chunk-ZPLALRXZ.js} +17 -9
- package/chunks/{chunk-WUC6ZFXO.js → chunk-ZWBUH5UP.js} +1 -1
- package/chunks/{computer-use-KEAPATUY.js → computer-use-ESQYJ3JY.js} +26 -22
- package/chunks/{config-utils-K7SCOWHD.js → config-utils-XQHBJP7G.js} +4 -4
- package/chunks/{contextCommand-ZJA6A5K5.js → contextCommand-CX3YF4ZE.js} +28 -24
- package/chunks/{core-runtime-QMJPWHCI.js → core-runtime-DIAU7JMG.js} +30 -26
- package/chunks/{create-sub-session-DJE6XICH.js → create-sub-session-HDPD6HOA.js} +26 -22
- package/chunks/{create-sub-session-E4PBYXV5.js → create-sub-session-QIDZUOPU.js} +1 -1
- package/chunks/{cron-create-GRBWYMIJ.js → cron-create-VONA5JYY.js} +1 -1
- package/chunks/{cron-delete-4CMKBR2M.js → cron-delete-5JXSP2MI.js} +1 -1
- package/chunks/{cron-list-W7K4ASOA.js → cron-list-KE4F2CIR.js} +1 -1
- package/chunks/{daemon-SCTQMM7Z.js → daemon-VZBGJUNL.js} +30 -0
- package/chunks/{daemon-status-provider-FSWDPE2G.js → daemon-status-provider-H6O4UQ4F.js} +33 -29
- package/chunks/{daemon-trust-policy-P5L5VFAY.js → daemon-trust-policy-BNUXG6MT.js} +33 -29
- package/chunks/{daemon-trust-policy-monitor-73JYN6ET.js → daemon-trust-policy-monitor-E4EQ7GF4.js} +33 -29
- package/chunks/{de-VL76CPLV.js → de-LIW4XVLN.js} +5 -0
- package/chunks/{deferred-core-runtime-BWRCCFTE.js → deferred-core-runtime-CBMSHPAU.js} +26 -22
- package/chunks/{display-image-O2XFPQTC.js → display-image-NQRSIBXM.js} +2 -2
- package/chunks/{dist-DPPHJAVL.js → dist-EEEQGCZA.js} +918 -142
- package/chunks/{dist-K4WWQBHS.js → dist-HIACTZEK.js} +55 -15
- package/chunks/{dist-3BMEUGTG.js → dist-IRL7WA5Z.js} +1 -1
- package/chunks/{dist-HVBMEYWK.js → dist-KVISB2O2.js} +1 -1
- package/chunks/{dist-KS4O2NKE.js → dist-MBF3I5MX.js} +14 -8
- package/chunks/{dist-SFQ34F4M.js → dist-MKX5OSFF.js} +5 -4
- package/chunks/{dist-7JGAAQSC.js → dist-RCH3I7SS.js} +2 -2
- package/chunks/{dist-C5U4LJKW.js → dist-TUSWNE2I.js} +5 -4
- package/chunks/{earlyInputCapture-L5ST23A6.js → earlyInputCapture-UIOP7OIN.js} +26 -22
- package/chunks/{edit-LHHRFNFK.js → edit-ITMZYFKA.js} +26 -22
- package/chunks/{en-IRJ2WN5T.js → en-SY5GTIGX.js} +6 -0
- package/chunks/{enter-worktree-6NXCRZPF.js → enter-worktree-S4PL5UV6.js} +26 -22
- package/chunks/{enterPlanMode-ZVQT4U7D.js → enterPlanMode-YV52NNJT.js} +26 -22
- package/chunks/{environment-GJ2HWJOS.js → environment-NGOWPRZV.js} +30 -26
- package/chunks/{errors-6RLH3XXC.js → errors-BU26DTDX.js} +28 -24
- package/chunks/{exit-worktree-I2YLUHHY.js → exit-worktree-XRM6LH5F.js} +26 -22
- package/chunks/{exitPlanMode-7CCWKO7I.js → exitPlanMode-ZLI5F7KR.js} +26 -22
- package/chunks/{fast-path-DVFD4HQD.js → fast-path-UJWORIED.js} +23 -3
- package/chunks/{fast-path-settings-WQJU2LAT.js → fast-path-settings-37WQD5B2.js} +6 -3
- package/chunks/{fr-GK3HQYVB.js → fr-RQFO7U4P.js} +5 -0
- package/chunks/{gemini-7FWGOYD4.js → gemini-ZSKNDUMU.js} +77 -65
- package/chunks/{geminiContentGenerator-V2WVLIXU.js → geminiContentGenerator-YGEXOEKD.js} +1 -1
- package/chunks/{glob-3N6GGI75.js → glob-7KZG44BR.js} +26 -22
- package/chunks/{goal-tools-APOW6UXL.js → goal-tools-PXWN5VK3.js} +4 -2
- package/chunks/{grep-V43ILZVX.js → grep-6ZFC7RJ5.js} +26 -22
- package/chunks/{handleAutoUpdate-A5WFVWIA.js → handleAutoUpdate-KSEL3TQS.js} +30 -26
- package/chunks/{i18n-PLVQ4FBZ.js → i18n-ZIUXBW5V.js} +27 -23
- package/chunks/{image-gen-7C6IK6DC.js → image-gen-AUIZJJNK.js} +7 -5
- package/chunks/{initializer-CVAIKZYL.js → initializer-7AHY3N6Q.js} +33 -29
- package/chunks/{installationInfo-J6QDHNTK.js → installationInfo-VGBXMYLY.js} +27 -23
- package/chunks/{ja-3FA46IKD.js → ja-KOZKHJHZ.js} +5 -0
- package/chunks/{list-ZZ4OUUWV.js → list-PSFKQHLB.js} +36 -32
- package/chunks/{list-agents-KFFIIS2G.js → list-agents-Z4WABFDZ.js} +1 -1
- package/chunks/{loadedSettingsAdapter-QRYRJSWL.js → loadedSettingsAdapter-FTMRCTOF.js} +33 -29
- package/chunks/{loggingContentGenerator-OJCO75HM.js → loggingContentGenerator-MZAN52UV.js} +7 -5
- package/chunks/{loop-wakeup-TLMJPMMP.js → loop-wakeup-UZ5RL5Y2.js} +2 -2
- package/chunks/{ls-UVVE2XGE.js → ls-TVHDGIES.js} +1 -1
- package/chunks/{lsp-QMEA2VLB.js → lsp-CVN6OQPI.js} +1 -1
- package/chunks/{managed-npm-update-PCOSCP2N.js → managed-npm-update-O4NHK45X.js} +27 -23
- package/chunks/{mcp-M3WKKWKY.js → mcp-6CFP2AYQ.js} +33 -29
- package/chunks/{monitor-GN24FH6C.js → monitor-DAKD6OU4.js} +26 -22
- package/chunks/{nonInteractiveCli-KPTU3VSQ.js → nonInteractiveCli-RC7VIUZL.js} +66 -60
- package/chunks/{notebook-edit-4YM65BBO.js → notebook-edit-474DPMRL.js} +34 -22
- package/chunks/{openaiContentGenerator-EDQT6GTV.js → openaiContentGenerator-2NFY2MWO.js} +19 -9
- package/chunks/{pidfile-JOIIRN2C.js → pidfile-KBFVDNQP.js} +26 -22
- package/chunks/{process-registry-2CHQBXH5.js → process-registry-PMJOA5CO.js} +15 -0
- package/chunks/{processUtils-5SV4MX3Q.js → processUtils-6GRYH4Y3.js} +2 -2
- package/chunks/{pt-3AOBKPIJ.js → pt-U6AOCTMF.js} +5 -0
- package/chunks/{qwenContentGenerator-ODRJSUGR.js → qwenContentGenerator-KAHU6IZY.js} +33 -28
- package/chunks/{qwenOAuth2-NESCMZ47.js → qwenOAuth2-RRQTCP4W.js} +7 -5
- package/chunks/{read-file-HPSODLPK.js → read-file-3M6WXDXP.js} +6 -4
- package/chunks/{read-mcp-resource-2TNSJTC3.js → read-mcp-resource-PZ4ZF6YL.js} +1 -1
- package/chunks/{record-artifact-RAON52FC.js → record-artifact-P4HFMS7X.js} +2 -2
- package/chunks/{resumeHistoryUtils-TXCOFFMQ.js → resumeHistoryUtils-D6TAY3HX.js} +30 -26
- package/chunks/{ripGrep-ZKQGTQAO.js → ripGrep-PLPENT3E.js} +26 -22
- package/chunks/{ru-VJRAMC4W.js → ru-CMX4UMYP.js} +5 -0
- package/chunks/{run-qwen-serve-ZPKPKECF.js → run-qwen-serve-ZAFIJKJC.js} +168 -54
- package/chunks/{runtime-2FLNNM36.js → runtime-ZED7CYOZ.js} +38 -34
- package/chunks/{scheduler-365PJHNR.js → scheduler-MD3AL2W5.js} +26 -22
- package/chunks/{send-message-ZM7MRUGP.js → send-message-CAMSLG2L.js} +4 -3
- package/chunks/{serve-QD2RNLKJ.js → serve-E3VUDRZN.js} +33 -29
- package/chunks/{server-XLJVLTYM.js → server-OWMEMAKR.js} +450 -231
- package/chunks/{session-3VTUHH4Q.js → session-HZ57QK7K.js} +158 -97
- package/chunks/{settings-KULVPCQC.js → settings-V7BR3RKP.js} +32 -28
- package/chunks/{shell-3SWW22MH.js → shell-23OMNMW6.js} +26 -22
- package/chunks/{skill-KDHWYS7W.js → skill-6HBDYZRS.js} +7 -5
- package/chunks/{skill-settings-NMY4JEJC.js → skill-settings-HWJLTU7M.js} +32 -28
- package/chunks/{spawnChannel-ZKS4Q5OU.js → spawnChannel-N6KKUW5B.js} +27 -23
- package/chunks/{standalone-update-7CXPGAQ4.js → standalone-update-QGIKHATD.js} +28 -24
- package/chunks/{startInteractiveUI-2QQLEKM6.js → startInteractiveUI-GX2CRL42.js} +365 -155
- package/chunks/{syntheticOutput-ZLCUTKO2.js → syntheticOutput-PEBJQYJV.js} +2 -2
- package/chunks/{task-create-CQP5UEA3.js → task-create-5NWCQSJF.js} +5 -4
- package/chunks/{task-list-XLEZOJXP.js → task-list-53265TRZ.js} +1 -1
- package/chunks/{task-stop-7ZQM5CFF.js → task-stop-FPCOIRYX.js} +1 -1
- package/chunks/{task-update-JA75U2SN.js → task-update-5HN577LS.js} +5 -4
- package/chunks/{team-create-2WTNGAOX.js → team-create-CFFKU7KL.js} +26 -22
- package/chunks/{team-delete-MHY3UZGY.js → team-delete-MMQB4OSC.js} +1 -1
- package/chunks/{team-plan-approval-LZTYLEG4.js → team-plan-approval-6EFOKR6A.js} +26 -22
- package/chunks/{terminal-image-renderer-R5HHAFJN.js → terminal-image-renderer-TLDNACQY.js} +28 -24
- package/chunks/{theme-manager-PAUCSJFF.js → theme-manager-5LJ3H7VO.js} +26 -22
- package/chunks/{todoWrite-UPVOHYGD.js → todoWrite-JGV6VLOX.js} +1 -1
- package/chunks/{tool-search-2BFCGLI6.js → tool-search-UJV3A24H.js} +9 -6
- package/chunks/{total-session-admission-MK4SINFK.js → total-session-admission-D63QYXGO.js} +29 -25
- package/chunks/{trustedFolders-TJ5S26N7.js → trustedFolders-KZCOB53W.js} +30 -24
- package/chunks/{update-relaunch-N7AYLARF.js → update-relaunch-IFILM3SA.js} +5 -5
- package/chunks/{updateCheck-QRZ3DVT5.js → updateCheck-YZ2CRCFC.js} +29 -25
- package/chunks/{useAutoAcceptIndicator-DBJ7Y5AF.js → useAutoAcceptIndicator-AXEVNA3Q.js} +35 -31
- package/chunks/{validateNonInterActiveAuth-6ZQWUDS3.js → validateNonInterActiveAuth-3WTOJFWA.js} +61 -57
- package/chunks/{version-AJQGQWXC.js → version-GXK7OHZY.js} +1 -1
- package/chunks/{web-fetch-QWJYRXFL.js → web-fetch-ILB4GAVR.js} +12 -8
- package/chunks/{web-search-2AOXJGHU.js → web-search-HKRPGPZZ.js} +8 -6
- package/chunks/{workflow-ERH3SJG2.js → workflow-FXIPRQQA.js} +750 -147
- package/chunks/{workspace-providers-status-HZ474RA4.js → workspace-providers-status-NYHC7HSR.js} +35 -31
- package/chunks/{workspace-registration-store-6EUP4JXG.js → workspace-registration-store-AKEB7OMW.js} +1 -1
- package/chunks/{workspace-registry-R4APRRNC.js → workspace-registry-CDAS5TVZ.js} +29 -25
- package/chunks/{workspace-service-HFIFDMU7.js → workspace-service-PAMUKMAV.js} +36 -32
- package/chunks/{workspace-skills-status-HAHEIHGK.js → workspace-skills-status-YQSHCCMS.js} +33 -29
- package/chunks/{workspace-trust-reconciler-65GTAGDK.js → workspace-trust-reconciler-RPTXOIY2.js} +36 -32
- package/chunks/{write-file-B34CDELV.js → write-file-CGS57TS4.js} +26 -22
- package/chunks/{zh-ARWDLDLR.js → zh-AGL2FVBI.js} +6 -0
- package/chunks/{zh-TW-Y4RGI3P7.js → zh-TW-KI66MHQY.js} +6 -0
- package/chunks/{zoom-image-HPRBZHSS.js → zoom-image-E7D72GYV.js} +6 -4
- package/cli.js +13 -13
- package/locales/ca.js +10 -0
- package/locales/de.js +9 -0
- package/locales/en.js +10 -0
- package/locales/fr.js +9 -0
- package/locales/ja.js +9 -0
- package/locales/pt.js +9 -0
- package/locales/ru.js +9 -0
- package/locales/zh-TW.js +10 -0
- package/locales/zh.js +10 -0
- package/package.json +3 -3
- package/web-shell/assets/{arc-Ip-FFDJ0.js → arc-DybZaz32.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-CChqgwIb.js → architectureDiagram-3BPJPVTR-jN3qBd19.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-BHN-Tfss.js → blockDiagram-GPEHLZMM-Ct5DZPrj.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BhyjzDjN.js → c4Diagram-AAUBKEIU-CUAFMlUG.js} +1 -1
- package/web-shell/assets/channel-BMwLrwLW.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-BB9eyHrx.js → chunk-2J33WTMH-CuV8n90B.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-BeV7ce_J.js → chunk-4BX2VUAB-BUzl_kls.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-DO7kXDiV.js → chunk-55IACEB6-BnDBLX6A.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-B27MPznD.js → chunk-727SXJPM-B83uTOjm.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-DHIjqjD_.js → chunk-AQP2D5EJ-DM3HLgpT.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-DabMqyN2.js → chunk-FMBD7UC4-CSQ5hgyb.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-Dw7Nnnxc.js → chunk-ND2GUHAM-BWOF4SxX.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-DdaZew1Q.js → chunk-QZHKN3VN-BsOH9LMi.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BGDv98jY.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BGDv98jY.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-CgBpCYH5.js → cose-bilkent-S5V4N54A-IENqH2iJ.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-BB4IU8G0.js → dagre-BM42HDAG--dyzDTGo.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-BcUTHU37.js → diagram-2AECGRRQ-BE7Dcqof.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-B6Lyihyv.js → diagram-5GNKFQAL-Cr8-5OTj.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CRIJOjpG.js → diagram-KO2AKTUF-Bzey3uAY.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-DdNiwWWT.js → diagram-LMA3HP47-sErl28Xb.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-Dz4b32Do.js → diagram-OG6HWLK6-Dq30ATIo.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-D-8NGw77.js → erDiagram-TEJ5UH35-BkCoEfVW.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-Dun26LyM.js → flowDiagram-I6XJVG4X-DHwO0rrI.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-F10Hu1Gc.js → ganttDiagram-6RSMTGT7-s7vAPxWq.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Bf8Ez6-D.js → gitGraphDiagram-PVQCEYII-CQxhwPOU.js} +1 -1
- package/web-shell/assets/index-Bckpjr-I.css +5 -0
- package/web-shell/assets/{index-BXqw-nGq.js → index-CF4wApWp.js} +1 -1
- package/web-shell/assets/index-DwEr9HEW.js +1768 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-DVgTMLvj.js → infoDiagram-5YYISTIA-BnFrD0bq.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-uT-KepvK.js → ishikawaDiagram-YF4QCWOH-Bf9zK5NK.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-Vg_XadQf.js → journeyDiagram-JHISSGLW-CyGAhsxi.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-Dyv1ESBE.js → kanban-definition-UN3LZRKU-CbsK5akB.js} +1 -1
- package/web-shell/assets/{linear-BMIepYX3.js → linear-cQsF4P8D.js} +1 -1
- package/web-shell/assets/{mermaid.core-zA8pJ9ag.js → mermaid.core-Z4HVqrKY.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-BCW_BZ_5.js → mindmap-definition-RKZ34NQL-CYnrBo_f.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-DseNEGp2.js → pieDiagram-4H26LBE5-CBzOfhrs.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-6Z7wr1Fi.js → quadrantDiagram-W4KKPZXB-D4LK1Ebn.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CVOlCRPf.js → requirementDiagram-4Y6WPE33-Bzti2Lcj.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-CGhgrUJZ.js → sankeyDiagram-5OEKKPKP-yTBw5Z2s.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-dlqmpLuQ.js → sequenceDiagram-3UESZ5HK-D07UVRiZ.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-B9EW10Xb.js → stateDiagram-AJRCARHV-UE_lHsTn.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-DC6xgXjX.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-BBRh0mgZ.js → timeline-definition-PNZ67QCA-DRvYdiTs.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-B8Gs-REP.js → vennDiagram-CIIHVFJN-CQLIXs0u.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-D_y80Ur7.js → wardley-L42UT6IY-JZz_Xqse.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-D-CNfHJ-.js → wardleyDiagram-YWT4CUSO--i7BiJwB.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-DQ5CvELo.js → xychartDiagram-2RQKCTM6-Bkc-bW0S.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-6PEXNQTX.js +0 -68
- package/chunks/chunk-IUFV6FYU.js +0 -81
- package/web-shell/assets/channel-Cu8qd6OB.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BI3KrXhq.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BI3KrXhq.js +0 -1
- package/web-shell/assets/index-QQlUCJGg.css +0 -5
- package/web-shell/assets/index-hcgjV7vS.js +0 -1768
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CJTZJJ5X.js +0 -1
- package/chunks/{anthropicContentGenerator-DTMVEL5M.js → anthropicContentGenerator-SSFE2753.js} +9 -9
|
@@ -14,8 +14,9 @@ import {
|
|
|
14
14
|
ChannelBase,
|
|
15
15
|
ChannelProactiveDeliveryError,
|
|
16
16
|
isChannelProactiveDeliveryError,
|
|
17
|
-
isTerminalTaskLifecycleType
|
|
18
|
-
|
|
17
|
+
isTerminalTaskLifecycleType,
|
|
18
|
+
sanitizeSenderName
|
|
19
|
+
} from "./chunk-DIWZNWZT.js";
|
|
19
20
|
import "./chunk-UDXSXLER.js";
|
|
20
21
|
import "./chunk-H6XPXXMH.js";
|
|
21
22
|
import {
|
|
@@ -88996,8 +88997,443 @@ async function downloadMedia(messageId, fileKey, resourceType, accessToken) {
|
|
|
88996
88997
|
}
|
|
88997
88998
|
__name(downloadMedia, "downloadMedia");
|
|
88998
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
|
+
|
|
88999
89434
|
// packages/channels/feishu/dist/FeishuAdapter.js
|
|
89000
89435
|
var DEDUP_TTL_MS = 5 * 60 * 1e3;
|
|
89436
|
+
var OBSERVED_LABEL_CACHE_LIMIT = 500;
|
|
89001
89437
|
var CARD_UPDATE_INTERVAL_MS = 1500;
|
|
89002
89438
|
var FEISHU_RUNNING_STATUS_LABEL = "\u8FD0\u884C\u4E2D...";
|
|
89003
89439
|
var FEISHU_STOPPED_STATUS_LABEL = "\u5DF2\u505C\u6B62\u751F\u6210";
|
|
@@ -89023,6 +89459,17 @@ var FEISHU_STATUS_LABELS = `(?:${FEISHU_STATUS_STRINGS.map(escapeRegExp).join("|
|
|
|
89023
89459
|
var FEISHU_STATUS_BLOCK_RE = new RegExp(`(?:^|\\n)---\\n\\*${FEISHU_STATUS_LABELS}\\*(?=\\n|$)`, "g");
|
|
89024
89460
|
var BASE_URL2 = "https://open.feishu.cn/open-apis";
|
|
89025
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
|
+
};
|
|
89026
89473
|
var FeishuChannel = class extends ChannelBase {
|
|
89027
89474
|
static {
|
|
89028
89475
|
__name(this, "FeishuChannel");
|
|
@@ -89047,6 +89494,16 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89047
89494
|
botOpenId;
|
|
89048
89495
|
tokenCache;
|
|
89049
89496
|
tokenRefreshPromise;
|
|
89497
|
+
questionCardController;
|
|
89498
|
+
// Core (non-silent) callers waiting on the shared token refresh, so a
|
|
89499
|
+
// silent-initiated refresh still logs token errors for them.
|
|
89500
|
+
tokenRefreshHasCoreWaiters = false;
|
|
89501
|
+
observedUserNames = /* @__PURE__ */ new Map();
|
|
89502
|
+
observedChatNames = /* @__PURE__ */ new Map();
|
|
89503
|
+
observedUserLookups = /* @__PURE__ */ new Map();
|
|
89504
|
+
observedChatLookups = /* @__PURE__ */ new Map();
|
|
89505
|
+
observedContactWrites = /* @__PURE__ */ new Map();
|
|
89506
|
+
hydratedObservedNames = false;
|
|
89050
89507
|
collapsible;
|
|
89051
89508
|
collapsibleThreshold;
|
|
89052
89509
|
constructor(name, config, bridge, options) {
|
|
@@ -89057,6 +89514,16 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89057
89514
|
const feishuCfg = config;
|
|
89058
89515
|
this.collapsible = feishuCfg["collapsible"] || false;
|
|
89059
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
|
+
});
|
|
89060
89527
|
}
|
|
89061
89528
|
supportsProactiveSend() {
|
|
89062
89529
|
return true;
|
|
@@ -89072,6 +89539,19 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89072
89539
|
"card.action.trigger": /* @__PURE__ */ __name((data) => {
|
|
89073
89540
|
const payload = data;
|
|
89074
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
|
+
}
|
|
89075
89555
|
const stopped = this.onCardAction(payload);
|
|
89076
89556
|
if (stopped) {
|
|
89077
89557
|
return { toast: { type: "info", content: "\u5DF2\u505C\u6B62" } };
|
|
@@ -89385,10 +89865,12 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89385
89865
|
text = text.replace(/^好的,<at[^>]*><\/at>\s*\n*/, "");
|
|
89386
89866
|
return text.trim() || void 0;
|
|
89387
89867
|
}
|
|
89388
|
-
async getTenantAccessToken() {
|
|
89868
|
+
async getTenantAccessToken(options) {
|
|
89389
89869
|
if (this.tokenCache && Date.now() < this.tokenCache.expiresAt) {
|
|
89390
89870
|
return this.tokenCache.token;
|
|
89391
89871
|
}
|
|
89872
|
+
if (!options?.silent)
|
|
89873
|
+
this.tokenRefreshHasCoreWaiters = true;
|
|
89392
89874
|
if (this.tokenRefreshPromise)
|
|
89393
89875
|
return this.tokenRefreshPromise;
|
|
89394
89876
|
this.tokenRefreshPromise = this.refreshToken();
|
|
@@ -89396,6 +89878,7 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89396
89878
|
return await this.tokenRefreshPromise;
|
|
89397
89879
|
} finally {
|
|
89398
89880
|
this.tokenRefreshPromise = void 0;
|
|
89881
|
+
this.tokenRefreshHasCoreWaiters = false;
|
|
89399
89882
|
}
|
|
89400
89883
|
}
|
|
89401
89884
|
async refreshToken() {
|
|
@@ -89410,8 +89893,10 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89410
89893
|
signal: AbortSignal.timeout(15e3)
|
|
89411
89894
|
});
|
|
89412
89895
|
if (!resp.ok) {
|
|
89413
|
-
|
|
89896
|
+
if (this.tokenRefreshHasCoreWaiters) {
|
|
89897
|
+
process.stderr.write(`[Feishu:${this.name}] getTenantAccessToken failed: HTTP ${resp.status}
|
|
89414
89898
|
`);
|
|
89899
|
+
}
|
|
89415
89900
|
if (resp.status === 401)
|
|
89416
89901
|
this.tokenCache = void 0;
|
|
89417
89902
|
return void 0;
|
|
@@ -89424,11 +89909,172 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89424
89909
|
};
|
|
89425
89910
|
return this.tokenCache.token;
|
|
89426
89911
|
} catch (err) {
|
|
89427
|
-
|
|
89912
|
+
if (this.tokenRefreshHasCoreWaiters) {
|
|
89913
|
+
process.stderr.write(`[Feishu:${this.name}] getTenantAccessToken error: ${err}
|
|
89428
89914
|
`);
|
|
89915
|
+
}
|
|
89429
89916
|
return void 0;
|
|
89430
89917
|
}
|
|
89431
89918
|
}
|
|
89919
|
+
hydrateObservedNames() {
|
|
89920
|
+
if (this.hydratedObservedNames)
|
|
89921
|
+
return;
|
|
89922
|
+
this.hydratedObservedNames = true;
|
|
89923
|
+
const graph = this.persistedObservedContacts();
|
|
89924
|
+
if (!graph)
|
|
89925
|
+
return;
|
|
89926
|
+
const newestUser = /* @__PURE__ */ new Map();
|
|
89927
|
+
const newestChat = /* @__PURE__ */ new Map();
|
|
89928
|
+
const consider = /* @__PURE__ */ __name((best, id, label, at) => {
|
|
89929
|
+
if (label === id)
|
|
89930
|
+
return;
|
|
89931
|
+
const current = best.get(id);
|
|
89932
|
+
if (!current || at >= current.at)
|
|
89933
|
+
best.set(id, { label, at });
|
|
89934
|
+
}, "consider");
|
|
89935
|
+
for (const user of graph.users) {
|
|
89936
|
+
consider(newestUser, user.id, user.label, user.lastObservedAt);
|
|
89937
|
+
}
|
|
89938
|
+
for (const group of graph.groups) {
|
|
89939
|
+
consider(newestChat, group.id, group.label, group.lastObservedAt);
|
|
89940
|
+
for (const member of group.users) {
|
|
89941
|
+
consider(newestUser, member.id, member.label, member.lastObservedAt);
|
|
89942
|
+
}
|
|
89943
|
+
}
|
|
89944
|
+
for (const [id, entry] of newestUser) {
|
|
89945
|
+
this.observedUserNames.set(id, entry.label);
|
|
89946
|
+
}
|
|
89947
|
+
for (const [id, entry] of newestChat) {
|
|
89948
|
+
this.observedChatNames.set(id, entry.label);
|
|
89949
|
+
}
|
|
89950
|
+
this.capObservedCache(this.observedUserNames);
|
|
89951
|
+
this.capObservedCache(this.observedChatNames);
|
|
89952
|
+
}
|
|
89953
|
+
/** Evicts the oldest-inserted entries once a runtime cache exceeds the cap. */
|
|
89954
|
+
capObservedCache(cache) {
|
|
89955
|
+
let evicted = false;
|
|
89956
|
+
while (cache.size > OBSERVED_LABEL_CACHE_LIMIT) {
|
|
89957
|
+
const oldest = cache.keys().next();
|
|
89958
|
+
if (oldest.done)
|
|
89959
|
+
break;
|
|
89960
|
+
cache.delete(oldest.value);
|
|
89961
|
+
evicted = true;
|
|
89962
|
+
}
|
|
89963
|
+
return evicted;
|
|
89964
|
+
}
|
|
89965
|
+
observedUserName(userId) {
|
|
89966
|
+
const userIdType = userId.startsWith("ou_") ? "open_id" : userId.startsWith("on_") ? "union_id" : "user_id";
|
|
89967
|
+
return this.observedNameLookup({
|
|
89968
|
+
lookups: this.observedUserLookups,
|
|
89969
|
+
names: this.observedUserNames,
|
|
89970
|
+
id: userId,
|
|
89971
|
+
request: /* @__PURE__ */ __name((token) => fetch(`${BASE_URL2}/contact/v3/users/basic_batch?user_id_type=${userIdType}`, {
|
|
89972
|
+
method: "POST",
|
|
89973
|
+
headers: {
|
|
89974
|
+
Authorization: `Bearer ${token}`,
|
|
89975
|
+
"Content-Type": "application/json"
|
|
89976
|
+
},
|
|
89977
|
+
body: JSON.stringify({ user_ids: [userId] }),
|
|
89978
|
+
signal: AbortSignal.timeout(15e3)
|
|
89979
|
+
}), "request"),
|
|
89980
|
+
extractName: /* @__PURE__ */ __name((body) => {
|
|
89981
|
+
const data = body;
|
|
89982
|
+
return data.code === 0 ? data.data?.users?.[0]?.name : void 0;
|
|
89983
|
+
}, "extractName")
|
|
89984
|
+
});
|
|
89985
|
+
}
|
|
89986
|
+
observedChatName(chatId) {
|
|
89987
|
+
return this.observedNameLookup({
|
|
89988
|
+
lookups: this.observedChatLookups,
|
|
89989
|
+
names: this.observedChatNames,
|
|
89990
|
+
id: chatId,
|
|
89991
|
+
request: /* @__PURE__ */ __name((token) => fetch(`${BASE_URL2}/im/v1/chats/${encodeURIComponent(chatId)}`, {
|
|
89992
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
89993
|
+
signal: AbortSignal.timeout(15e3)
|
|
89994
|
+
}), "request"),
|
|
89995
|
+
extractName: /* @__PURE__ */ __name((body) => {
|
|
89996
|
+
const data = body;
|
|
89997
|
+
return data.code === 0 ? data.data?.name : void 0;
|
|
89998
|
+
}, "extractName")
|
|
89999
|
+
});
|
|
90000
|
+
}
|
|
90001
|
+
observedNameLookup(options) {
|
|
90002
|
+
const cached = options.names.get(options.id);
|
|
90003
|
+
if (cached)
|
|
90004
|
+
return Promise.resolve(cached);
|
|
90005
|
+
const existing = options.lookups.get(options.id);
|
|
90006
|
+
if (existing)
|
|
90007
|
+
return existing;
|
|
90008
|
+
const lookup = (async () => {
|
|
90009
|
+
try {
|
|
90010
|
+
const token = await this.getTenantAccessToken({ silent: true });
|
|
90011
|
+
if (!token) {
|
|
90012
|
+
options.lookups.delete(options.id);
|
|
90013
|
+
return void 0;
|
|
90014
|
+
}
|
|
90015
|
+
const response = await options.request(token);
|
|
90016
|
+
if (!response.ok) {
|
|
90017
|
+
if (response.status === 401) {
|
|
90018
|
+
this.tokenCache = void 0;
|
|
90019
|
+
options.lookups.delete(options.id);
|
|
90020
|
+
}
|
|
90021
|
+
return void 0;
|
|
90022
|
+
}
|
|
90023
|
+
const name = options.extractName(await response.json())?.trim();
|
|
90024
|
+
if (!name)
|
|
90025
|
+
return void 0;
|
|
90026
|
+
const label = sanitizeSenderName(name);
|
|
90027
|
+
if (label === "unknown")
|
|
90028
|
+
return void 0;
|
|
90029
|
+
options.names.set(options.id, label);
|
|
90030
|
+
if (this.capObservedCache(options.names)) {
|
|
90031
|
+
this.hydratedObservedNames = false;
|
|
90032
|
+
}
|
|
90033
|
+
return label;
|
|
90034
|
+
} catch {
|
|
90035
|
+
return void 0;
|
|
90036
|
+
}
|
|
90037
|
+
})();
|
|
90038
|
+
options.lookups.set(options.id, lookup);
|
|
90039
|
+
this.capObservedCache(options.lookups);
|
|
90040
|
+
return lookup;
|
|
90041
|
+
}
|
|
90042
|
+
onObservedContact(envelope) {
|
|
90043
|
+
this.observedContactWrites.set(this.observedContactKey(envelope), {
|
|
90044
|
+
senderName: envelope.senderName,
|
|
90045
|
+
chatName: envelope.chatName
|
|
90046
|
+
});
|
|
90047
|
+
this.capObservedCache(this.observedContactWrites);
|
|
90048
|
+
void this.enrichObservedContact(envelope).catch(() => {
|
|
90049
|
+
});
|
|
90050
|
+
}
|
|
90051
|
+
observedContactKey(envelope) {
|
|
90052
|
+
return envelope.isGroup ? `${envelope.senderId}\0${envelope.chatId}\0${envelope.threadId ?? ""}` : envelope.senderId;
|
|
90053
|
+
}
|
|
90054
|
+
async enrichObservedContact(envelope) {
|
|
90055
|
+
const [senderName, chatName] = await Promise.all([
|
|
90056
|
+
this.observedUserName(envelope.senderId),
|
|
90057
|
+
envelope.isGroup ? this.observedChatName(envelope.chatId) : Promise.resolve(void 0)
|
|
90058
|
+
]);
|
|
90059
|
+
if (!senderName && !chatName)
|
|
90060
|
+
return;
|
|
90061
|
+
const key = this.observedContactKey(envelope);
|
|
90062
|
+
const nextLabels = {
|
|
90063
|
+
senderName: senderName ?? envelope.senderName,
|
|
90064
|
+
chatName: chatName ?? envelope.chatName
|
|
90065
|
+
};
|
|
90066
|
+
const persistedLabels = this.observedContactWrites.get(key);
|
|
90067
|
+
if (persistedLabels && persistedLabels.senderName === nextLabels.senderName && persistedLabels.chatName === nextLabels.chatName) {
|
|
90068
|
+
return;
|
|
90069
|
+
}
|
|
90070
|
+
this.observedContactWrites.set(key, nextLabels);
|
|
90071
|
+
this.capObservedCache(this.observedContactWrites);
|
|
90072
|
+
await this.recordObservedContact({
|
|
90073
|
+
...envelope,
|
|
90074
|
+
...senderName ? { senderName } : {},
|
|
90075
|
+
...chatName ? { chatName } : {}
|
|
90076
|
+
});
|
|
90077
|
+
}
|
|
89432
90078
|
async sendMessage(chatId, text) {
|
|
89433
90079
|
await this.sendMessageInternal(chatId, text, false);
|
|
89434
90080
|
}
|
|
@@ -89502,65 +90148,40 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89502
90148
|
}
|
|
89503
90149
|
}
|
|
89504
90150
|
// ----- Interactive Card Streaming -----
|
|
89505
|
-
async
|
|
90151
|
+
async sendInteractiveCard(chatId, card) {
|
|
89506
90152
|
const token = await this.getTenantAccessToken();
|
|
89507
90153
|
if (!token)
|
|
89508
|
-
|
|
89509
|
-
const
|
|
89510
|
-
|
|
89511
|
-
|
|
89512
|
-
|
|
89513
|
-
|
|
89514
|
-
|
|
89515
|
-
|
|
89516
|
-
|
|
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)
|
|
89517
90167
|
});
|
|
89518
|
-
|
|
89519
|
-
|
|
89520
|
-
|
|
89521
|
-
|
|
89522
|
-
|
|
89523
|
-
|
|
89524
|
-
|
|
89525
|
-
|
|
89526
|
-
|
|
89527
|
-
|
|
89528
|
-
|
|
89529
|
-
},
|
|
89530
|
-
body: JSON.stringify(body),
|
|
89531
|
-
signal: AbortSignal.timeout(15e3)
|
|
89532
|
-
});
|
|
89533
|
-
if (!resp.ok) {
|
|
89534
|
-
if (resp.status === 401)
|
|
89535
|
-
this.tokenCache = void 0;
|
|
89536
|
-
const detail = await resp.text().catch(() => "");
|
|
89537
|
-
process.stderr.write(`[Feishu:${this.name}] createStreamingCard failed: HTTP ${resp.status} ${detail}
|
|
89538
|
-
`);
|
|
89539
|
-
return { messageId: "", success: false };
|
|
89540
|
-
}
|
|
89541
|
-
const data = await resp.json();
|
|
89542
|
-
const messageId = data.data?.message_id || "";
|
|
89543
|
-
return { messageId, success: !!messageId };
|
|
89544
|
-
} catch (err) {
|
|
89545
|
-
process.stderr.write(`[Feishu:${this.name}] createStreamingCard error: ${err}
|
|
89546
|
-
`);
|
|
89547
|
-
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");
|
|
89548
90179
|
}
|
|
90180
|
+
return messageId;
|
|
89549
90181
|
}
|
|
89550
|
-
async
|
|
90182
|
+
async patchInteractiveCard(messageId, card) {
|
|
89551
90183
|
const token = await this.getTenantAccessToken();
|
|
89552
|
-
if (!token)
|
|
89553
|
-
return false;
|
|
89554
|
-
const cardTitle = inboundMsgId ? this.msgToQuestion.get(inboundMsgId) || "Qwen" : "Qwen";
|
|
89555
|
-
const card = buildCardContent(text, {
|
|
89556
|
-
title: cardTitle,
|
|
89557
|
-
showStopButton: !finished,
|
|
89558
|
-
isStreaming: !finished,
|
|
89559
|
-
statusLabel: statusLabel ?? (!finished ? this.statusLabelFor() : void 0),
|
|
89560
|
-
collapsible: this.collapsible,
|
|
89561
|
-
collapsibleThreshold: this.collapsibleThreshold
|
|
89562
|
-
});
|
|
89563
|
-
if (!FEISHU_ID_RE2.test(messageId))
|
|
90184
|
+
if (!token || !FEISHU_ID_RE2.test(messageId))
|
|
89564
90185
|
return false;
|
|
89565
90186
|
try {
|
|
89566
90187
|
const resp = await fetch(`${BASE_URL2}/im/v1/messages/${messageId}`, {
|
|
@@ -89590,6 +90211,52 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89590
90211
|
return false;
|
|
89591
90212
|
}
|
|
89592
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
|
+
}
|
|
89593
90260
|
/** Delete a card message from Feishu to prevent orphaned "思考中..." cards. */
|
|
89594
90261
|
async deleteCard(messageId) {
|
|
89595
90262
|
const token = await this.getTenantAccessToken();
|
|
@@ -89641,6 +90308,7 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89641
90308
|
}
|
|
89642
90309
|
if (cardState.stopped)
|
|
89643
90310
|
return;
|
|
90311
|
+
cardState.boundaryText = void 0;
|
|
89644
90312
|
const MAX_ACCUMULATE = 25e3;
|
|
89645
90313
|
cardState.accumulatedText += chunk;
|
|
89646
90314
|
if (cardState.accumulatedText.length > MAX_ACCUMULATE) {
|
|
@@ -89650,12 +90318,14 @@ var FeishuChannel = class extends ChannelBase {
|
|
|
89650
90318
|
return;
|
|
89651
90319
|
if (!cardState.created && !cardState.cardCreationFailed) {
|
|
89652
90320
|
cardState.creating = true;
|
|
90321
|
+
cardState.lastUpdateAt = Date.now();
|
|
89653
90322
|
const cs = cardState;
|
|
89654
90323
|
cardState.creationTimer = setTimeout(async () => {
|
|
89655
90324
|
try {
|
|
89656
90325
|
if (cs.stopped || this.stoppedMessages.has(inboundMsgId)) {
|
|
89657
90326
|
cs.creating = false;
|
|
89658
|
-
|
|
90327
|
+
if (!cs.abandoned)
|
|
90328
|
+
this.cleanupCard(inboundMsgId);
|
|
89659
90329
|
return;
|
|
89660
90330
|
}
|
|
89661
90331
|
const atPrefix = this.msgToSenderName.get(inboundMsgId);
|
|
@@ -89702,36 +90372,50 @@ ${cs.accumulatedText}` : cs.accumulatedText;
|
|
|
89702
90372
|
const cs = cardState;
|
|
89703
90373
|
const elapsed = Date.now() - cardState.lastUpdateAt;
|
|
89704
90374
|
const delay = Math.max(0, CARD_UPDATE_INTERVAL_MS - elapsed);
|
|
89705
|
-
cardState.pendingUpdateTimer = setTimeout(
|
|
90375
|
+
cardState.pendingUpdateTimer = setTimeout(() => {
|
|
89706
90376
|
cs.pendingUpdateTimer = void 0;
|
|
89707
90377
|
if (cs.stopped || cs.finalizing)
|
|
89708
90378
|
return;
|
|
89709
90379
|
cs.lastUpdateAt = Date.now();
|
|
89710
|
-
|
|
89711
|
-
|
|
89712
|
-
|
|
89713
|
-
|
|
89714
|
-
|
|
89715
|
-
${cs.accumulatedText}` : cs.accumulatedText;
|
|
89716
|
-
if (displayContent.length > MAX_CARD_CHARS) {
|
|
89717
|
-
const marker = "\n\n_(\u5185\u5BB9\u8FC7\u957F\uFF0C\u5DF2\u622A\u65AD\u65E9\u671F\u5185\u5BB9)_";
|
|
89718
|
-
displayContent = displayContent.slice(-(MAX_CARD_CHARS - marker.length)) + marker;
|
|
89719
|
-
if (this.countFences(displayContent) % 2 === 1) {
|
|
89720
|
-
displayContent = "```\n" + displayContent;
|
|
89721
|
-
}
|
|
89722
|
-
}
|
|
89723
|
-
const ok = await this.updateCard(cs.messageId, displayContent, false, inboundMsgId);
|
|
89724
|
-
if (!ok) {
|
|
89725
|
-
const stripped = this.stripTables(displayContent, "(\u8868\u683C)");
|
|
89726
|
-
await this.updateCard(cs.messageId, stripped, false, inboundMsgId);
|
|
89727
|
-
}
|
|
89728
|
-
} catch (err) {
|
|
90380
|
+
if (cs.pendingUpdatePromise) {
|
|
90381
|
+
cs.updateQueued = true;
|
|
90382
|
+
return;
|
|
90383
|
+
}
|
|
90384
|
+
cs.pendingUpdatePromise = this.runThrottledCardUpdate(inboundMsgId, cs).catch((err) => {
|
|
89729
90385
|
process.stderr.write(`[Feishu:${this.name}] card update error: ${err}
|
|
89730
90386
|
`);
|
|
89731
|
-
}
|
|
90387
|
+
}).then(() => {
|
|
90388
|
+
cs.pendingUpdatePromise = void 0;
|
|
90389
|
+
});
|
|
89732
90390
|
}, delay);
|
|
89733
90391
|
}
|
|
89734
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
|
+
}
|
|
89735
90419
|
onResponseBoundary(_chatId, sessionId) {
|
|
89736
90420
|
if (this.config.blockStreaming === "on")
|
|
89737
90421
|
return;
|
|
@@ -89745,8 +90429,90 @@ ${cs.accumulatedText}` : cs.accumulatedText;
|
|
|
89745
90429
|
clearTimeout(cardState.pendingUpdateTimer);
|
|
89746
90430
|
cardState.pendingUpdateTimer = void 0;
|
|
89747
90431
|
}
|
|
90432
|
+
cardState.updateQueued = false;
|
|
90433
|
+
if (cardState.accumulatedText) {
|
|
90434
|
+
cardState.boundaryText = cardState.accumulatedText;
|
|
90435
|
+
}
|
|
89748
90436
|
cardState.accumulatedText = "";
|
|
89749
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
|
+
}
|
|
89750
90516
|
isKnownInboundMessageId(messageId) {
|
|
89751
90517
|
return this.msgToQuestion.has(messageId) || this.msgToSenderName.has(messageId) || this.msgToSenderId.has(messageId) || this.cardSessions.has(messageId) || this.stoppedMessages.has(messageId);
|
|
89752
90518
|
}
|
|
@@ -89791,6 +90557,9 @@ ${contentPart}` : contentPart;
|
|
|
89791
90557
|
if (!isTerminalTaskLifecycleType(event.type)) {
|
|
89792
90558
|
return;
|
|
89793
90559
|
}
|
|
90560
|
+
if (event.runId) {
|
|
90561
|
+
this.questionCardController.cancelRun(event.runId, event.type === "cancelled" && (event.reason === "cancel_command" || event.reason === "clear") ? "cancelled" : "expired");
|
|
90562
|
+
}
|
|
89794
90563
|
const inboundMsgId = this.knownInboundMessageId(event.sessionId, event.messageId);
|
|
89795
90564
|
if (!inboundMsgId)
|
|
89796
90565
|
return;
|
|
@@ -89820,34 +90589,22 @@ ${contentPart}` : contentPart;
|
|
|
89820
90589
|
return;
|
|
89821
90590
|
}
|
|
89822
90591
|
const atSender = this.msgToSenderName.get(inboundMsgId);
|
|
89823
|
-
let displayText = atSender ? `${atSender}
|
|
89824
|
-
|
|
89825
|
-
${fullText}` : fullText;
|
|
89826
90592
|
const completedLabel = this.statusLabelFor("completed");
|
|
89827
90593
|
const completedSuffix = `
|
|
89828
90594
|
|
|
89829
90595
|
---
|
|
89830
90596
|
*${completedLabel}*`;
|
|
89831
|
-
const
|
|
89832
|
-
if (displayText.length + completedSuffix.length > MAX_FINAL_CARD_CHARS) {
|
|
89833
|
-
const prefix = atSender ? `${atSender}
|
|
90597
|
+
const atPrefix = atSender ? `${atSender}
|
|
89834
90598
|
|
|
89835
90599
|
` : "";
|
|
89836
|
-
|
|
89837
|
-
const fenceReserve = 4;
|
|
89838
|
-
const maxBody = MAX_FINAL_CARD_CHARS - prefix.length - suffix.length - completedSuffix.length - fenceReserve;
|
|
89839
|
-
displayText = prefix + fullText.slice(-maxBody) + suffix;
|
|
89840
|
-
if (this.countFences(displayText) % 2 === 1) {
|
|
89841
|
-
displayText = "```\n" + displayText;
|
|
89842
|
-
}
|
|
89843
|
-
}
|
|
90600
|
+
const displayText = atPrefix + this.truncateCardText(fullText, atPrefix.length + completedSuffix.length);
|
|
89844
90601
|
if (cardState)
|
|
89845
90602
|
cardState.finalizing = true;
|
|
89846
90603
|
if (cardState?.pendingUpdateTimer) {
|
|
89847
90604
|
clearTimeout(cardState.pendingUpdateTimer);
|
|
89848
90605
|
}
|
|
89849
|
-
if (cardState?.
|
|
89850
|
-
|
|
90606
|
+
if (cardState?.pendingUpdatePromise) {
|
|
90607
|
+
await cardState.pendingUpdatePromise;
|
|
89851
90608
|
}
|
|
89852
90609
|
if (cardState?.creating) {
|
|
89853
90610
|
await new Promise((resolve) => {
|
|
@@ -89922,60 +90679,20 @@ ${fullText}` : fullText);
|
|
|
89922
90679
|
|
|
89923
90680
|
${fullText}` : fullText);
|
|
89924
90681
|
}
|
|
89925
|
-
onPromptStart(
|
|
90682
|
+
onPromptStart(_chatId, sessionId, messageId) {
|
|
89926
90683
|
const inboundMsgId = messageId && this.isKnownInboundMessageId(messageId) ? messageId : void 0;
|
|
89927
90684
|
if (inboundMsgId) {
|
|
89928
90685
|
this.sessionToInboundMsg.set(sessionId, inboundMsgId);
|
|
89929
90686
|
this.addReaction(inboundMsgId, "OnIt").catch(() => {
|
|
89930
90687
|
});
|
|
89931
|
-
if (this.config.blockStreaming
|
|
89932
|
-
|
|
89933
|
-
if (!this.cardSessions.has(inboundMsgId)) {
|
|
89934
|
-
const atSender = this.msgToSenderName.get(inboundMsgId) || "";
|
|
89935
|
-
const placeholderText = atSender ? `${atSender}\uFF0C\u601D\u8003\u4E2D...` : "\u601D\u8003\u4E2D...";
|
|
89936
|
-
const cardState = {
|
|
90688
|
+
if (this.config.blockStreaming !== "on" && !this.cardSessions.has(inboundMsgId)) {
|
|
90689
|
+
this.cardSessions.set(inboundMsgId, {
|
|
89937
90690
|
messageId: "",
|
|
89938
90691
|
created: false,
|
|
89939
|
-
creating:
|
|
90692
|
+
creating: false,
|
|
89940
90693
|
stopped: false,
|
|
89941
90694
|
accumulatedText: "",
|
|
89942
90695
|
lastUpdateAt: Date.now()
|
|
89943
|
-
};
|
|
89944
|
-
this.cardSessions.set(inboundMsgId, cardState);
|
|
89945
|
-
this.createStreamingCard(chatId, placeholderText, void 0, inboundMsgId).then((result) => {
|
|
89946
|
-
if (cardState.stopped || this.stoppedMessages.has(inboundMsgId)) {
|
|
89947
|
-
if (cardState.abandoned) {
|
|
89948
|
-
if (result.success) {
|
|
89949
|
-
this.deleteCard(result.messageId).catch((err) => {
|
|
89950
|
-
process.stderr.write(`[Feishu:${this.name}] ORPHANED CARD: failed to delete abandoned card msg=${result.messageId}: ${err instanceof Error ? err.message : err}
|
|
89951
|
-
`);
|
|
89952
|
-
});
|
|
89953
|
-
}
|
|
89954
|
-
cardState.creating = false;
|
|
89955
|
-
return;
|
|
89956
|
-
}
|
|
89957
|
-
if (result.success) {
|
|
89958
|
-
const prefix = cardState.atPrefix || this.msgToSenderName.get(inboundMsgId) || "";
|
|
89959
|
-
this.updateCard(result.messageId, prefix, true, inboundMsgId, this.stopLabelFor(cardState.terminalStatus, cardState.userStopped ?? false)).catch(() => {
|
|
89960
|
-
});
|
|
89961
|
-
}
|
|
89962
|
-
cardState.creating = false;
|
|
89963
|
-
this.cleanupCard(inboundMsgId);
|
|
89964
|
-
return;
|
|
89965
|
-
}
|
|
89966
|
-
if (result.success) {
|
|
89967
|
-
cardState.messageId = result.messageId;
|
|
89968
|
-
cardState.created = true;
|
|
89969
|
-
cardState.lastUpdateAt = Date.now();
|
|
89970
|
-
} else {
|
|
89971
|
-
cardState.cardCreationFailed = true;
|
|
89972
|
-
}
|
|
89973
|
-
cardState.creating = false;
|
|
89974
|
-
}).catch((err) => {
|
|
89975
|
-
process.stderr.write(`[Feishu:${this.name}] Processing card error: ${err}
|
|
89976
|
-
`);
|
|
89977
|
-
cardState.creating = false;
|
|
89978
|
-
this.cleanupCard(inboundMsgId);
|
|
89979
90696
|
});
|
|
89980
90697
|
}
|
|
89981
90698
|
}
|
|
@@ -89991,6 +90708,14 @@ ${fullText}` : fullText);
|
|
|
89991
90708
|
cs.stopped = true;
|
|
89992
90709
|
} else if (cs.created) {
|
|
89993
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
|
+
}
|
|
89994
90719
|
const atPrefix = this.msgToSenderName.get(inboundMsgId) || "";
|
|
89995
90720
|
const terminalStatus = cs.terminalStatus ?? (cs.cancelling ? "cancelled" : "failed");
|
|
89996
90721
|
const terminalLabel = this.stopLabelFor(terminalStatus, cs.userStopped ?? false);
|
|
@@ -90008,7 +90733,7 @@ ${cs.accumulatedText}` : cs.accumulatedText : atPrefix || "";
|
|
|
90008
90733
|
${cs.accumulatedText}` : cs.accumulatedText;
|
|
90009
90734
|
this.sendMessage(_chatId, fallbackText).catch(() => {
|
|
90010
90735
|
});
|
|
90011
|
-
} else {
|
|
90736
|
+
} else if (cs.terminalStatus !== "completed") {
|
|
90012
90737
|
const atPrefix = this.msgToSenderName.get(inboundMsgId) || "";
|
|
90013
90738
|
const fallbackLabel = cs.terminalStatus ? this.statusLabelFor(cs.terminalStatus) : "\u51FA\u9519\u4E86\uFF0C\u8BF7\u91CD\u8BD5";
|
|
90014
90739
|
const errorText = atPrefix ? `${atPrefix}
|
|
@@ -90148,6 +90873,13 @@ ${cs.accumulatedText}` : cs.accumulatedText;
|
|
|
90148
90873
|
}
|
|
90149
90874
|
if (cardState.finalizing)
|
|
90150
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
|
+
}
|
|
90151
90883
|
if (cardState.created && cardState.messageId) {
|
|
90152
90884
|
const prefix = cardState.atPrefix || this.msgToSenderName.get(inboundId) || "";
|
|
90153
90885
|
const stopLabel = cancelSucceeded ? this.stopLabelFor(cardState.terminalStatus, wasUserStop) : FEISHU_STOP_FAILED_STATUS_LABEL;
|
|
@@ -90178,6 +90910,7 @@ ${contentPart}` : prefix : contentPart;
|
|
|
90178
90910
|
}
|
|
90179
90911
|
}
|
|
90180
90912
|
disconnect() {
|
|
90913
|
+
this.questionCardController.dispose();
|
|
90181
90914
|
if (this.dedupTimer) {
|
|
90182
90915
|
clearInterval(this.dedupTimer);
|
|
90183
90916
|
this.dedupTimer = void 0;
|
|
@@ -90252,6 +90985,21 @@ ${contentPart}` : prefix : contentPart;
|
|
|
90252
90985
|
}
|
|
90253
90986
|
return result.join("\n");
|
|
90254
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
|
+
}
|
|
90255
91003
|
cleanupCard(inboundMsgId) {
|
|
90256
91004
|
const cardState = this.cardSessions.get(inboundMsgId);
|
|
90257
91005
|
if (cardState?.pendingUpdateTimer) {
|
|
@@ -90272,6 +91020,30 @@ ${contentPart}` : prefix : contentPart;
|
|
|
90272
91020
|
}
|
|
90273
91021
|
}
|
|
90274
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
|
+
}
|
|
90275
91047
|
// ----- Message handling -----
|
|
90276
91048
|
onMessage(data) {
|
|
90277
91049
|
try {
|
|
@@ -90286,6 +91058,9 @@ ${contentPart}` : prefix : contentPart;
|
|
|
90286
91058
|
const isGroup = msg.chat_type === "group";
|
|
90287
91059
|
const chatId = msg.chat_id;
|
|
90288
91060
|
const senderId = sender.sender_id?.open_id || sender.sender_id?.user_id || sender.sender_id?.union_id || "";
|
|
91061
|
+
this.hydrateObservedNames();
|
|
91062
|
+
const senderName = this.observedUserNames.get(senderId) || senderId;
|
|
91063
|
+
const chatName = isGroup ? this.observedChatNames.get(chatId) : void 0;
|
|
90289
91064
|
const content = this.extractContent(msg.message_type, msg.content);
|
|
90290
91065
|
let isMentioned = false;
|
|
90291
91066
|
let cleanText = content.text;
|
|
@@ -90315,8 +91090,9 @@ ${contentPart}` : prefix : contentPart;
|
|
|
90315
91090
|
const envelope = {
|
|
90316
91091
|
channelName: this.name,
|
|
90317
91092
|
senderId,
|
|
90318
|
-
senderName
|
|
91093
|
+
senderName,
|
|
90319
91094
|
chatId,
|
|
91095
|
+
...chatName ? { chatName } : {},
|
|
90320
91096
|
text: cleanText,
|
|
90321
91097
|
messageId: msgId,
|
|
90322
91098
|
threadId: msg.root_id || void 0,
|