@qwen-code/qwen-code 0.21.0 → 0.21.1
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/bundled/qc-helper/docs/configuration/model-providers.md +2 -0
- package/bundled/qc-helper/docs/configuration/settings.md +38 -28
- package/bundled/qc-helper/docs/features/channels/_meta.ts +1 -0
- package/bundled/qc-helper/docs/features/channels/github.md +107 -0
- package/bundled/qc-helper/docs/features/channels/overview.md +61 -6
- package/bundled/qc-helper/docs/features/code-review.md +1 -1
- package/bundled/qc-helper/docs/features/hooks.md +52 -15
- package/bundled/qc-helper/docs/features/mcp.md +9 -1
- package/bundled/qc-helper/docs/features/scheduled-tasks.md +3 -1
- package/bundled/qc-helper/docs/features/sub-agents.md +20 -0
- package/bundled/qc-helper/docs/qwen-serve.md +4 -2
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +2 -2
- package/bundled/qc-helper/docs/support/troubleshooting.md +2 -1
- package/bundled/review/DESIGN.md +19 -0
- package/bundled/review/SKILL.md +120 -61
- package/chunks/MaxSizedBox-VI3ROJJA.js +84 -0
- package/chunks/{StandaloneSessionPicker-BIRMPLRD.js → StandaloneSessionPicker-LYXKD2EV.js} +67 -68
- package/chunks/{acp-startup-profiler-RV3IV562.js → acp-startup-profiler-DFVPFQ6C.js} +2 -2
- package/chunks/{acpAgent-6J2U72PQ.js → acpAgent-WN5SRDQO.js} +1373 -553
- package/chunks/agent-K6ECSM64.js +80 -0
- package/chunks/agent-headless-NO4Y2HOE.js +74 -0
- package/chunks/{anthropicContentGenerator-75BKLTSP.js → anthropicContentGenerator-V2QOGVYD.js} +79 -27
- package/chunks/{artifact-tool-Y5T7GG7F.js → artifact-tool-6K6U7XYJ.js} +4 -4
- package/chunks/{askUserQuestion-2H6747FR.js → askUserQuestion-GD2IJJ7I.js} +4 -4
- package/chunks/bridge-3KJEWDNE.js +90 -0
- package/chunks/{build-RV63TIRH.js → build-S6DO7LMM.js} +1 -1
- package/chunks/{ca-25EDXPFZ.js → ca-6W3SK7OQ.js} +6 -1
- package/chunks/channel-management-service-XR7GZSWF.js +403 -0
- package/chunks/channel-settings-store-HW4FXXUA.js +87 -0
- package/chunks/{channel-worker-group-2ZD7TVAT.js → channel-worker-group-XDPTDWTX.js} +11 -6
- package/chunks/{channel-worker-manager-4OA4BCGB.js → channel-worker-manager-YYEHVRRE.js} +11 -6
- package/chunks/{channel-worker-supervisor-V7KCFJTS.js → channel-worker-supervisor-74HTWA2G.js} +7 -5
- package/chunks/{chunk-M5JM7OSF.js → chunk-2DN4J57Y.js} +2 -3
- package/chunks/{chunk-ETSW4KLJ.js → chunk-2FAK6PNM.js} +2 -2
- package/chunks/{chunk-BPJSQIJX.js → chunk-2J3OJGTL.js} +0 -2
- package/chunks/{chunk-EPDRMGT4.js → chunk-2LKVPASC.js} +4 -28
- package/chunks/{chunk-PWTZEM3C.js → chunk-2LQTH543.js} +3 -37
- package/chunks/{chunk-LH2BYDQ5.js → chunk-2N7CODY5.js} +18 -12
- package/chunks/{chunk-4WIZGAH3.js → chunk-2XSLTRFZ.js} +6 -58
- package/chunks/{chunk-FSITMZJH.js → chunk-3EFXSQCM.js} +18 -9
- package/chunks/{chunk-HIJQF5B5.js → chunk-3L2SPEBH.js} +1 -1
- package/chunks/{chunk-BIQWWWJN.js → chunk-4G2BISNC.js} +1 -1
- package/chunks/{chunk-PWVFN2LF.js → chunk-52ZSWYEG.js} +1 -1
- package/chunks/{chunk-ZJHVAS7M.js → chunk-5KTQXHPY.js} +4 -5
- package/chunks/{chunk-PC6JANNU.js → chunk-5MKRTI4T.js} +4 -4
- package/chunks/{chunk-DHHOYAPR.js → chunk-5TBMQLGG.js} +7 -7
- package/chunks/{chunk-A4UCTEB5.js → chunk-5WV5S2GT.js} +0 -1
- package/chunks/chunk-5YKDXHUY.js +463 -0
- package/chunks/chunk-5ZF5XXTS.js +363 -0
- package/chunks/{chunk-K4XWPEWB.js → chunk-64LQLPL7.js} +4 -33
- package/chunks/{chunk-YPE6A4GC.js → chunk-657BH7VM.js} +2 -2
- package/chunks/{chunk-R5AFZNQW.js → chunk-65PQENQP.js} +14 -7
- package/chunks/{chunk-RIBKPMRP.js → chunk-6PE7N3A4.js} +18 -7
- package/chunks/{chunk-JZA3JUDJ.js → chunk-6QIGFD5W.js} +1 -1
- package/chunks/{chunk-JVPM2ULZ.js → chunk-6RPMI2AB.js} +6 -6
- package/chunks/{chunk-OHNBB4XR.js → chunk-75GFAX4R.js} +1 -1
- package/chunks/{chunk-NIBLUX3Y.js → chunk-75MIQ3LV.js} +148 -21
- package/chunks/{chunk-U7M2DMGW.js → chunk-7AEJDLRA.js} +130 -5
- package/chunks/{chunk-TPRQ7RZH.js → chunk-7BAU433D.js} +2293 -945
- package/chunks/{chunk-M4FMGVY4.js → chunk-7DXQIJID.js} +3 -3
- package/chunks/{chunk-RWTEFFPU.js → chunk-7I5GTCT4.js} +620 -383
- package/chunks/{chunk-A5L3JMUA.js → chunk-7XATOOE7.js} +18 -4
- package/chunks/{chunk-Y34KJKDC.js → chunk-A2D5BAVP.js} +1 -1
- package/chunks/{chunk-5I2IWRSH.js → chunk-A3NDJ5SB.js} +2 -2
- package/chunks/{chunk-OFDOK3VM.js → chunk-A4COXFB3.js} +8 -13
- package/chunks/{chunk-JLU636DO.js → chunk-ALMR3E6Q.js} +1 -0
- package/chunks/{chunk-Q4M4MDQ4.js → chunk-AQIDMUGU.js} +1 -1
- package/chunks/{chunk-PJIZUQVC.js → chunk-AZQ3DT76.js} +2 -2
- package/chunks/{chunk-UH3WSE5L.js → chunk-B4AJNNOL.js} +1 -6
- package/chunks/{chunk-BJX6ZSUK.js → chunk-BCZFQXWK.js} +2 -2
- package/chunks/{chunk-MB4MZHMJ.js → chunk-BGTQCTQW.js} +211 -522
- package/chunks/{chunk-MZAXJAUM.js → chunk-BMFALVGQ.js} +1 -1
- package/chunks/{chunk-PSOO6YXD.js → chunk-BNWB5CYE.js} +9 -7
- package/chunks/{chunk-BKHWX6I2.js → chunk-BPZKP57P.js} +11 -3
- package/chunks/{chunk-H4SBPHSA.js → chunk-CAPPWD3X.js} +3 -3
- package/chunks/{chunk-LQIW3YFY.js → chunk-CQL64ESB.js} +7 -7
- package/chunks/{chunk-TOFQCPDC.js → chunk-CVHIL5IG.js} +4 -5
- package/chunks/{chunk-XVNQMZ2I.js → chunk-DGEIYUC3.js} +0 -1
- package/chunks/{chunk-BPZALHVR.js → chunk-DI35ZN7T.js} +1 -1
- package/chunks/chunk-DZLYR4U3.js +1252 -0
- package/chunks/{chunk-TEHGS6UP.js → chunk-EIF3FXTB.js} +117 -24
- package/chunks/{chunk-2SCDWPXI.js → chunk-EJGJIBRS.js} +5 -5
- package/chunks/{chunk-7MVVZO4N.js → chunk-EVKE2FZL.js} +4 -4
- package/chunks/{chunk-OKY7HXPG.js → chunk-FNMZK765.js} +2 -2
- package/chunks/{chunk-VIA5XA4U.js → chunk-FTD6DP4T.js} +3 -1
- package/chunks/chunk-FYJ7W2PI.js +194 -0
- package/chunks/{chunk-L5UHQJTJ.js → chunk-GATT5TKW.js} +1 -1
- package/chunks/{chunk-X5XDDSSH.js → chunk-GEBV2JGB.js} +28 -5
- package/chunks/{chunk-VAK25FTU.js → chunk-GKX7E4CO.js} +1 -1
- package/chunks/{chunk-LS77BEZP.js → chunk-GLCZKT5V.js} +1 -5
- package/chunks/{chunk-5NBDS5S6.js → chunk-GNR2RNMP.js} +162 -7
- package/chunks/{chunk-YH6G52F2.js → chunk-GXIJHV66.js} +4 -4
- package/chunks/chunk-GZ3RCT54.js +76 -0
- package/chunks/{chunk-2X55UKQE.js → chunk-HMRM2A3U.js} +3 -3
- package/chunks/chunk-HV26XH34.js +319 -0
- package/chunks/{chunk-LB6DUZ26.js → chunk-J7OACQDE.js} +229 -172
- package/chunks/{chunk-K36B6G2O.js → chunk-JFMA7Y5M.js} +5 -5
- package/chunks/{chunk-55DJUCI2.js → chunk-JHNRZMHI.js} +53 -43
- package/chunks/{chunk-63P4EL5V.js → chunk-JMONIXMJ.js} +1 -1
- package/chunks/{chunk-L26JL52R.js → chunk-JSD33JG6.js} +47 -64
- package/chunks/{chunk-YBL3QUDD.js → chunk-JTV5K7NH.js} +1 -1
- package/chunks/{chunk-RZIX2G32.js → chunk-JX27F6QS.js} +1 -1
- package/chunks/chunk-JYBU6YUE.js +378 -0
- package/chunks/{chunk-7JURR4JT.js → chunk-KAMYKP7E.js} +167 -81
- package/chunks/{chunk-KMQ33DO4.js → chunk-KCO4FLFJ.js} +4 -4
- package/chunks/{chunk-2W3OOD4W.js → chunk-L55JWS76.js} +6 -3
- package/chunks/{chunk-RHLZR4E5.js → chunk-LGAOC3ZS.js} +1 -1
- package/chunks/{chunk-EBJQ6AXW.js → chunk-LO4ROVP4.js} +262 -16
- package/chunks/{chunk-NH6KE4JX.js → chunk-LW3RFMG7.js} +3 -3
- package/chunks/{chunk-J56UI34H.js → chunk-M7OONWYU.js} +2 -2
- package/chunks/{chunk-2NH6DYI4.js → chunk-MHAIJPTD.js} +12 -12
- package/chunks/{chunk-FODK6UMO.js → chunk-MPHPFVKK.js} +0 -2
- package/chunks/{chunk-VRYUBFMC.js → chunk-MR5EAQ5M.js} +1 -1
- package/chunks/{chunk-JESCGQM3.js → chunk-NAVJD2PQ.js} +8 -7
- package/chunks/{chunk-H5FFA6TH.js → chunk-NOKIVHOL.js} +16 -3
- package/chunks/{chunk-6OUGMXDC.js → chunk-NWNEANAT.js} +7 -7
- package/chunks/{chunk-SQCQ4KO2.js → chunk-OCESJA77.js} +393 -330
- package/chunks/chunk-OCPBI7J5.js +18 -0
- package/chunks/{chunk-E5TUC6CA.js → chunk-OKF7JF3R.js} +3 -3
- package/chunks/{chunk-TGILQ3YH.js → chunk-P4WOAOJW.js} +141 -64
- package/chunks/{chunk-ZFDTEDCF.js → chunk-PB3MBFKG.js} +6 -6
- package/chunks/{chunk-3RN6GBKS.js → chunk-PLDQBIO6.js} +1 -1
- package/chunks/{chunk-FNQ6T3CV.js → chunk-PONHVBRT.js} +10 -7
- package/chunks/{chunk-CIKQ7KKO.js → chunk-PT722TDT.js} +271 -376
- package/chunks/chunk-Q43KPN7X.js +2196 -0
- package/chunks/{chunk-VDDGDZMA.js → chunk-QHWCP53L.js} +14 -7
- package/chunks/{chunk-MVSUYZDT.js → chunk-QIZKCVM3.js} +4 -4
- package/chunks/{chunk-QAF7NMK7.js → chunk-RCUQIPTN.js} +1 -1
- package/chunks/{chunk-6FGBXPWM.js → chunk-RPLGZJV2.js} +38 -44
- package/chunks/{chunk-GSN55ZRI.js → chunk-S4WJVPZW.js} +19 -7
- package/chunks/{chunk-6AM5D4ME.js → chunk-S6LOFUVP.js} +0 -12
- package/chunks/{chunk-BULDBTYC.js → chunk-S7W2GKIO.js} +1 -28
- package/chunks/{chunk-MUP3T3AD.js → chunk-SGFT55XI.js} +1 -35
- package/chunks/{chunk-VYPFXUCB.js → chunk-SZ3KHTDR.js} +1 -1
- package/chunks/chunk-T26EAKDL.js +13 -0
- package/chunks/{chunk-UDX5OBWR.js → chunk-T2QMKU3R.js} +80 -2
- package/chunks/{chunk-IKYJHJNF.js → chunk-T3O2B4XO.js} +3 -3
- package/chunks/{chunk-RF3EXIHJ.js → chunk-T4TXDL7G.js} +32 -21
- package/chunks/{chunk-J24WCGIN.js → chunk-TBBV36Y4.js} +4 -4
- package/chunks/{chunk-LKEJ26GS.js → chunk-TCIFAA7K.js} +16 -11
- package/chunks/{chunk-JXJFVC6E.js → chunk-TDL6LB4K.js} +46 -11
- package/chunks/{chunk-7ZCNENPP.js → chunk-TFRMVU6R.js} +1 -1
- package/chunks/{chunk-VULLI6WQ.js → chunk-TV64SXKD.js} +6 -6
- package/chunks/{chunk-FQK6JAFG.js → chunk-U3E3UQAA.js} +4 -4
- package/chunks/{chunk-LK7CHLVP.js → chunk-U4VTUMMK.js} +0 -60
- package/chunks/{chunk-ACY3A37B.js → chunk-UBEPNVDI.js} +23 -18
- package/chunks/{chunk-NL7LTRLR.js → chunk-UHUSJ6X7.js} +29 -68
- package/chunks/{chunk-ZOIFNCKL.js → chunk-UPUG4GXM.js} +3 -23
- package/chunks/{chunk-6GMVPFB2.js → chunk-UWMLWVCA.js} +19 -6
- package/chunks/{chunk-IKCX4CCL.js → chunk-VCPIZRYH.js} +118 -95
- package/chunks/{chunk-ZNAUOR2I.js → chunk-VWOOBLTY.js} +2 -2
- package/chunks/{chunk-YX324OPW.js → chunk-VYOXCEPJ.js} +1 -1
- package/chunks/{chunk-USTWD7QV.js → chunk-W4MIWP6M.js} +26 -16
- package/chunks/{chunk-HTR4WV6U.js → chunk-W4RQUHY3.js} +31 -1
- package/chunks/{chunk-DLWL3Z7A.js → chunk-WBSMNTSV.js} +3 -3
- package/chunks/{chunk-IO3IX5Q4.js → chunk-WUZ7H6DP.js} +1 -1
- package/chunks/{chunk-2JZBVYTU.js → chunk-WZRWHXFE.js} +1 -8
- package/chunks/{chunk-PHOF65IG.js → chunk-X5WNMMIA.js} +23553 -34321
- package/chunks/chunk-XBYYDKAZ.js +80 -0
- package/chunks/{chunk-COH43MRJ.js → chunk-XCGIMOLN.js} +27 -1
- package/chunks/{chunk-WCXCRJYB.js → chunk-XFZYFU3I.js} +1 -1
- package/chunks/{chunk-3QMGYBFN.js → chunk-XWWKIXVD.js} +1 -80
- package/chunks/{chunk-3SJ43L4W.js → chunk-XZC5VLBZ.js} +2 -0
- package/chunks/{chunk-UUUTRMI2.js → chunk-Y4IHBGBP.js} +1 -1
- package/chunks/{chunk-PR75REBZ.js → chunk-Y6AXW2OG.js} +12 -82
- package/chunks/{chunk-IPUUTYMV.js → chunk-YDLJGZHL.js} +1 -1
- package/chunks/{chunk-IJTOWOD7.js → chunk-YGF33UXG.js} +82 -8
- package/chunks/chunk-Z4X5MTRT.js +133 -0
- package/chunks/{chunk-UW5EOVUN.js → chunk-ZBVS26BY.js} +4 -4
- package/chunks/{chunk-ZD6UTE4A.js → chunk-ZHBO7WVX.js} +1 -1
- package/chunks/{chunk-HTO4JFDZ.js → chunk-ZPJWUGCS.js} +0 -1
- package/chunks/{chunk-KIM5GUMA.js → chunk-ZURDMIDR.js} +368 -156
- package/chunks/{computer-use-SOQ4E3VX.js → computer-use-ZTIDHMMA.js} +49 -50
- package/chunks/{config-utils-7V7GGIW6.js → config-utils-NYSXDMEQ.js} +4 -3
- package/chunks/contextCommand-2PIEU37Z.js +79 -0
- package/chunks/core-runtime-3XEYLQFK.js +133 -0
- package/chunks/{create-sub-session-QRJLW5BV.js → create-sub-session-R76FVXCI.js} +46 -47
- package/chunks/{create-sub-session-IWW2IZ2T.js → create-sub-session-SBYUMSSS.js} +3 -3
- package/chunks/{cron-create-YIID5XAW.js → cron-create-2QK6TCEC.js} +6 -6
- package/chunks/{cron-delete-ZVHYCEP2.js → cron-delete-FDCDFYMG.js} +5 -5
- package/chunks/{cron-list-XEGS463Q.js → cron-list-XN3WVBTP.js} +6 -6
- package/chunks/{daemon-YO6433NF.js → daemon-Q2AB5Z23.js} +356 -15
- package/chunks/daemon-status-provider-3XJI6CAL.js +89 -0
- package/chunks/daemon-trust-policy-ILUDTLHD.js +84 -0
- package/chunks/daemon-trust-policy-monitor-HS3PKKRO.js +171 -0
- package/chunks/{de-HGRCYDEJ.js → de-SY6O76BF.js} +6 -1
- package/chunks/deferred-core-runtime-X4QV662U.js +88 -0
- package/chunks/dist-BSTVRPMT.js +4227 -0
- package/chunks/{dist-46NQKLTW.js → dist-DOLYHMXE.js} +2 -2
- package/chunks/{dist-AIKFMUKK.js → dist-HVRQ2CFL.js} +271 -11
- package/chunks/{dist-WEAHOXDM.js → dist-IXQEQWRG.js} +2 -1
- package/chunks/{dist-BBLXMS3N.js → dist-SSU66DM4.js} +3 -3
- package/chunks/{dist-F6IBUDR4.js → dist-SV7Q3AWJ.js} +1 -1
- package/chunks/{dist-YFNEUWSE.js → dist-YGBBMK3Z.js} +1 -1
- package/chunks/earlyInputCapture-XKLZT7ZD.js +81 -0
- package/chunks/{edit-OBDSQURM.js → edit-HHGIOTQ2.js} +47 -48
- package/chunks/{en-MTWBNGDO.js → en-NBK3JKCE.js} +9 -1
- package/chunks/{enter-worktree-U6MRPQ2P.js → enter-worktree-ZN7PUQ46.js} +47 -48
- package/chunks/{enterPlanMode-BC5QUZZ2.js → enterPlanMode-EIFIDSIV.js} +47 -48
- package/chunks/{environment-W5UFC2CH.js → environment-XXQ75D2Q.js} +48 -49
- package/chunks/errors-4GMVU7CK.js +87 -0
- package/chunks/esm-K5FARBNI.js +5548 -0
- package/chunks/{exit-worktree-DGNYMECB.js → exit-worktree-GXMI4ATY.js} +47 -48
- package/chunks/exitPlanMode-34UVY7M6.js +72 -0
- package/chunks/{fast-path-JJZFJANL.js → fast-path-VPIVA7L6.js} +16 -6
- package/chunks/{fr-45RLL55O.js → fr-4KG5V7UT.js} +6 -1
- package/chunks/{gemini-QS36EBZV.js → gemini-4BWIK4WD.js} +102 -99
- package/chunks/{geminiContentGenerator-AG4KB6CV.js → geminiContentGenerator-3XVV5MSS.js} +40 -11
- package/chunks/{getMachineId-bsd-V7W3GODC.js → getMachineId-bsd-FG7IUY6U.js} +1 -1
- package/chunks/{getMachineId-darwin-TDO75DQP.js → getMachineId-darwin-GLCJI2RA.js} +1 -1
- package/chunks/{getMachineId-linux-TF43WQT2.js → getMachineId-linux-O6OPPAKO.js} +1 -1
- package/chunks/{getMachineId-unsupported-ZGUO3TXT.js → getMachineId-unsupported-S6CKYVGC.js} +1 -1
- package/chunks/{getMachineId-win-ECFYZZFQ.js → getMachineId-win-X5SRNEH7.js} +1 -1
- package/chunks/{glob-V7R3PSK3.js → glob-TZ2ABCJG.js} +47 -48
- package/chunks/{grep-QYPSK7OP.js → grep-BEF463NA.js} +49 -49
- package/chunks/handleAutoUpdate-L6ERF36Y.js +80 -0
- package/chunks/i18n-FMM5FDXR.js +96 -0
- package/chunks/{image-gen-Z3VPGKRC.js → image-gen-HHVLF7HS.js} +12 -12
- package/chunks/initializer-625TIAIO.js +85 -0
- package/chunks/installationInfo-6AM4I2Y3.js +79 -0
- package/chunks/{ja-B7DF7DFG.js → ja-F3GSQXMF.js} +6 -1
- package/chunks/{keychain-token-storage-MDTG3WRM.js → keychain-token-storage-72IYCAZV.js} +3 -3
- package/chunks/lib-RUF3WZA6.js +9 -0
- package/chunks/list-L2GA674Y.js +88 -0
- package/chunks/{list-agents-5KJJHR6I.js → list-agents-R6KDXQR3.js} +3 -3
- package/chunks/loadedSettingsAdapter-SPUTNKAV.js +82 -0
- package/chunks/{loggingContentGenerator-HS3S5H3Q.js → loggingContentGenerator-LKOF7XI7.js} +78 -113
- package/chunks/{loop-wakeup-FXKNNYSY.js → loop-wakeup-3IQKCYAH.js} +7 -7
- package/chunks/{ls-NTK6VOQJ.js → ls-DKZ37A7N.js} +5 -5
- package/chunks/{lsp-2JI24STP.js → lsp-QNWN7KN3.js} +3 -3
- package/chunks/{managed-npm-update-JYEMMXA3.js → managed-npm-update-ACQGGIN5.js} +47 -48
- package/chunks/mcp-SZLHKFJW.js +82 -0
- package/chunks/{monitor-R3ODH5U6.js → monitor-DF52UVHI.js} +47 -48
- package/chunks/nonInteractiveCli-5T7KYKLK.js +144 -0
- package/chunks/{notebook-edit-BNOK452R.js → notebook-edit-FCWS4XVN.js} +47 -48
- package/chunks/{openaiContentGenerator-WMCU3O2H.js → openaiContentGenerator-7LDK3DCJ.js} +26 -27
- package/chunks/pidfile-6ERW3DF4.js +85 -0
- package/chunks/process-registry-2CHQBXH5.js +157 -0
- package/chunks/{processUtils-RT7UNCC2.js → processUtils-COKZAMUP.js} +2 -2
- package/chunks/{pt-22Q3FP73.js → pt-EQ33KWEN.js} +6 -1
- package/chunks/{qwenContentGenerator-HHCRK4SX.js → qwenContentGenerator-TKWUMR7N.js} +52 -53
- package/chunks/{qwenOAuth2-OWLB5AKH.js → qwenOAuth2-7HMU47SF.js} +10 -10
- package/chunks/read-file-X6DRC574.js +29 -0
- package/chunks/{read-mcp-resource-4DKQWGHD.js → read-mcp-resource-GFTWYXMK.js} +4 -4
- package/chunks/{record-artifact-RQKFYO5B.js → record-artifact-XAMSFSW4.js} +3 -3
- package/chunks/resumeHistoryUtils-PFPM2GWM.js +90 -0
- package/chunks/ripGrep-OWV2IVJC.js +72 -0
- package/chunks/{ru-FZCNZHDC.js → ru-7OZAUKGG.js} +6 -1
- package/chunks/{run-qwen-serve-FU6HEM4J.js → run-qwen-serve-TSTCO4XE.js} +953 -249
- package/chunks/{runtime-XXRRTNP6.js → runtime-DAUPSUKI.js} +56 -56
- package/chunks/{scheduler-G2ZS2Z7E.js → scheduler-KMADMT26.js} +46 -47
- package/chunks/{sdk-exporters-grpc-AK3LGHNO.js → sdk-exporters-grpc-54L4LS5L.js} +4 -4
- package/chunks/{sdk-exporters-http-FYBSUCPD.js → sdk-exporters-http-WO556XNU.js} +7 -7
- package/chunks/{sdk-impl-GMVPB7NB.js → sdk-impl-LPAVACSF.js} +14 -14
- package/chunks/{send-message-Q6OOR6BR.js → send-message-SAWK4DZX.js} +6 -6
- package/chunks/serve-NNRWS6F4.js +88 -0
- package/chunks/{server-4UMH7OIZ.js → server-WEH7DVCH.js} +3691 -823
- package/chunks/{session-K3O3Q2SV.js → session-WXC56V2I.js} +98 -95
- package/chunks/{settings-CR2EWTBA.js → settings-DJDXFDZ3.js} +55 -56
- package/chunks/shell-JN5VRQXD.js +82 -0
- package/chunks/{skill-I3SDA4MB.js → skill-SGXPKJCS.js} +20 -21
- package/chunks/skill-settings-VJ5PDMZI.js +90 -0
- package/chunks/spawnChannel-ETMJW7YX.js +81 -0
- package/chunks/standalone-update-MK3Z7KBI.js +91 -0
- package/chunks/{startInteractiveUI-SLZGHRPH.js → startInteractiveUI-ZCGIXPGT.js} +724 -383
- package/chunks/{syntheticOutput-I3757IWH.js → syntheticOutput-355CB6CJ.js} +4 -4
- package/chunks/{task-create-N7WQSGYA.js → task-create-INGWNUG4.js} +10 -10
- package/chunks/{task-list-FOPULZEP.js → task-list-5XNNGTF4.js} +7 -7
- package/chunks/{task-stop-H6RHXFVQ.js → task-stop-4ROAOBXH.js} +3 -3
- package/chunks/{task-update-M57TFZJT.js → task-update-CRK5VWWZ.js} +10 -10
- package/chunks/{team-create-YJALH5D2.js → team-create-QQGAJG7P.js} +49 -50
- package/chunks/{team-delete-QE2UXJL7.js → team-delete-S2RCXA4P.js} +7 -7
- package/chunks/{team-plan-approval-34QFYKGN.js → team-plan-approval-RT7Q5R6O.js} +47 -48
- package/chunks/theme-manager-EEWIQJ7J.js +76 -0
- package/chunks/{todoWrite-VQ7FKOHL.js → todoWrite-7WM3VDMY.js} +7 -7
- package/chunks/{tool-search-NF7GB6LE.js → tool-search-Z3Z4AYKP.js} +19 -21
- package/chunks/total-session-admission-44JKRWQD.js +84 -0
- package/chunks/trustedFolders-X2JEIO57.js +94 -0
- package/chunks/{update-relaunch-WBUZJC5O.js → update-relaunch-VWNPYDIP.js} +5 -5
- package/chunks/updateCheck-KAQH67DV.js +91 -0
- package/chunks/useAutoAcceptIndicator-JH6BCF7S.js +92 -0
- package/chunks/{validateNonInterActiveAuth-3R223G3R.js → validateNonInterActiveAuth-GIUJ2UFS.js} +93 -90
- package/chunks/{version-HS7YSFHV.js → version-BGLYIJUY.js} +1 -1
- package/chunks/{web-fetch-NKCSG7ZE.js → web-fetch-OTDU4VQF.js} +19 -21
- package/chunks/{web-search-S62WAP4S.js → web-search-FP6SIHPR.js} +13 -13
- package/chunks/{workflow-QAGU5RU4.js → workflow-YCIVBYSB.js} +48 -49
- package/chunks/workspace-providers-status-S35YAIUS.js +85 -0
- package/chunks/{workspace-registration-store-24JMHDGF.js → workspace-registration-store-OTMS3H4C.js} +1 -1
- package/chunks/workspace-registry-O63R6IZ4.js +92 -0
- package/chunks/workspace-service-M6LLHKJ5.js +99 -0
- package/chunks/workspace-skills-status-C2V7BAIS.js +85 -0
- package/chunks/workspace-trust-reconciler-IBUPOUJN.js +345 -0
- package/chunks/write-file-3BZC3EAE.js +72 -0
- package/chunks/xterm-headless-NTYVIBT3.js +3475 -0
- package/chunks/{zh-LUIGBD55.js → zh-H3YDK5QW.js} +9 -1
- package/chunks/{zh-TW-F5KG2IYD.js → zh-TW-JYCP7XUA.js} +9 -1
- package/chunks/zoom-image-TZ6S2O57.js +351 -0
- package/cli.js +13 -13
- package/locales/ca.js +7 -2
- package/locales/de.js +7 -2
- package/locales/en.js +10 -2
- package/locales/fr.js +7 -2
- package/locales/ja.js +7 -2
- package/locales/pt.js +7 -2
- package/locales/ru.js +7 -2
- package/locales/zh-TW.js +10 -2
- package/locales/zh.js +10 -2
- package/package.json +5 -4
- package/web-shell/assets/{arc-DcbWnB9T.js → arc-75-Wdeo3.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-kMMF5sud.js → architectureDiagram-3BPJPVTR-FKeXQbyP.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-Htl9vTJS.js → blockDiagram-GPEHLZMM-CY0vc-A3.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-BnZnm0mQ.js → c4Diagram-AAUBKEIU-CNP-A-8u.js} +1 -1
- package/web-shell/assets/channel-DPYMT76A.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-DziB7kDG.js → chunk-2J33WTMH-GybS4Gii.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-CmkD8daw.js → chunk-4BX2VUAB-02H91V8v.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-CHAd9A_U.js → chunk-55IACEB6-D3M-2VT6.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-Dqaam3fE.js → chunk-727SXJPM-CCu29u4H.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-D_-saBYM.js → chunk-AQP2D5EJ-CaFKWgrn.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-B9r_veWD.js → chunk-FMBD7UC4-ZZpPqIwQ.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-B3EaCSpL.js → chunk-ND2GUHAM-D22DqGs8.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-CYq8x9mn.js → chunk-QZHKN3VN-Bu85S0fw.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK--JstsIgL.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2--JstsIgL.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A-D0ng4uiB.js → cose-bilkent-S5V4N54A-f1CK1Gwe.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-DCZollQv.js → dagre-BM42HDAG-D0Ow8F_n.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-Dfk2pWS0.js → diagram-2AECGRRQ-BPrmTWp8.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-kX38ltWR.js → diagram-5GNKFQAL-HccuFAzy.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-CJz2vsXh.js → diagram-KO2AKTUF-BrS76mbA.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-BvMLZm_7.js → diagram-LMA3HP47-V7T9lU-5.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-l7kfStkO.js → diagram-OG6HWLK6-DKidyJMR.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-BSVa8GGT.js → erDiagram-TEJ5UH35-DBadZIkp.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CoawKIXH.js → flowDiagram-I6XJVG4X-BymfqdNJ.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-DFUDH0zF.js → ganttDiagram-6RSMTGT7-DOw340jf.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-Y2pvpT4e.js → gitGraphDiagram-PVQCEYII-_8EiD8sl.js} +1 -1
- package/web-shell/assets/{index-D0GX0zZf.js → index-CKIadvET.js} +1 -1
- package/web-shell/assets/index-D1eXNRHe.js +1389 -0
- package/web-shell/assets/index-DVLD4CQq.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-CU8_zLiX.js → infoDiagram-5YYISTIA-D61KYQBu.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-AVQiV0DU.js → ishikawaDiagram-YF4QCWOH-CsiXSpNx.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-DQ0VSKa3.js → journeyDiagram-JHISSGLW-Sdfionyh.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-BqnWqsE_.js → kanban-definition-UN3LZRKU-C3WI3Cnl.js} +1 -1
- package/web-shell/assets/{linear-BkoihsaA.js → linear-Dpigcc62.js} +1 -1
- package/web-shell/assets/{mermaid.core-5RJs-31j.js → mermaid.core-Ct97pqgW.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-D33Bxnpd.js → mindmap-definition-RKZ34NQL-BzeaN0rB.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-BuEAw3BH.js → pieDiagram-4H26LBE5-CvjgcbVD.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-Kox_usEq.js → quadrantDiagram-W4KKPZXB-BUzgTNdH.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CNjeUif0.js → requirementDiagram-4Y6WPE33-B7zKlgUQ.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-BCd2OL_U.js → sankeyDiagram-5OEKKPKP-Bb9CQgrT.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-CF2ZTsz0.js → sequenceDiagram-3UESZ5HK-DJ6V7itG.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-qenSzHtm.js → stateDiagram-AJRCARHV-IImflERY.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-CYI_YoNR.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-B5DyWdgs.js → timeline-definition-PNZ67QCA-6Q_uWHKh.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-DqP4I_o_.js → vennDiagram-CIIHVFJN-TmyKyjwv.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-CJe2e4mg.js → wardley-L42UT6IY-CRh9uiPv.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-BMDSw-Rr.js → wardleyDiagram-YWT4CUSO-59TKAW8w.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-BTVZYkxD.js → xychartDiagram-2RQKCTM6-GCSUIK2L.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/MaxSizedBox-5DPPWPGT.js +0 -85
- package/chunks/agent-6ODUANDO.js +0 -81
- package/chunks/agent-headless-7BYQTMHW.js +0 -75
- package/chunks/bridge-ZUB64FAE.js +0 -90
- package/chunks/chunk-LEH5C7FV.js +0 -232
- package/chunks/chunk-SZRN75WQ.js +0 -29
- package/chunks/chunk-UGYMA4EI.js +0 -219
- package/chunks/chunk-Z2BC6UJ5.js +0 -8575
- package/chunks/contextCommand-JLHYA34Z.js +0 -80
- package/chunks/daemon-status-provider-2233Q37D.js +0 -89
- package/chunks/earlyInputCapture-A7NDU3PF.js +0 -82
- package/chunks/errors-M7CLORXH.js +0 -88
- package/chunks/exitPlanMode-GXTBWQAR.js +0 -403
- package/chunks/handleAutoUpdate-6DBEZYPV.js +0 -81
- package/chunks/i18n-VUJJZIMU.js +0 -97
- package/chunks/initializer-UWAK5U5O.js +0 -86
- package/chunks/installationInfo-6O2YAA52.js +0 -80
- package/chunks/list-GB4ESM3T.js +0 -89
- package/chunks/loadedSettingsAdapter-OT6JVQ7U.js +0 -83
- package/chunks/mcp-6DBDJPFU.js +0 -83
- package/chunks/nonInteractiveCli-MOYCYBBU.js +0 -141
- package/chunks/pidfile-TFRZZZIO.js +0 -86
- package/chunks/read-file-APMO3PSX.js +0 -31
- package/chunks/resumeHistoryUtils-6KRYEAWZ.js +0 -91
- package/chunks/ripGrep-BEJDEDXW.js +0 -73
- package/chunks/serve-7BSTXJ4T.js +0 -89
- package/chunks/shell-HH3PF3A2.js +0 -83
- package/chunks/spawnChannel-RWNDBXGA.js +0 -82
- package/chunks/src-GE4TTTML.js +0 -3147
- package/chunks/standalone-update-Q6WFRZZQ.js +0 -92
- package/chunks/theme-manager-SWRILQHI.js +0 -77
- package/chunks/total-session-admission-DLHHHLD3.js +0 -84
- package/chunks/trustedFolders-KHXHY6PY.js +0 -93
- package/chunks/updateCheck-RKL6M5XN.js +0 -92
- package/chunks/useAutoAcceptIndicator-CFQ5BUJL.js +0 -93
- package/chunks/workspace-providers-status-QSVZUETE.js +0 -86
- package/chunks/workspace-registry-UT4RBNBM.js +0 -88
- package/chunks/workspace-service-JFWRUS4V.js +0 -98
- package/chunks/workspace-skills-status-ZBBKJOI2.js +0 -85
- package/chunks/write-file-VHIXW5M7.js +0 -73
- package/web-shell/assets/channel-Cq7YKtfC.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-CQ9aC1Tg.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-CQ9aC1Tg.js +0 -1
- package/web-shell/assets/index-D9haPt0X.css +0 -5
- package/web-shell/assets/index-ckX9Pq5k.js +0 -1230
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-B7W4zlCr.js +0 -1
- package/chunks/{chunk-TARRHLLG.js → chunk-QUGAUQGJ.js} +25 -25
- package/chunks/{chunk-U7ZFW55U.js → chunk-VOQXFAY5.js} +977 -977
- /package/chunks/{chunk-LXXMOYPL.js → chunk-VXZBKKQR.js} +0 -0
|
@@ -12,90 +12,6 @@ import {
|
|
|
12
12
|
__name
|
|
13
13
|
} from "./chunk-J2S4EL5Y.js";
|
|
14
14
|
|
|
15
|
-
// packages/channels/base/dist/sanitize.js
|
|
16
|
-
init_esbuild_shims();
|
|
17
|
-
var PROMPT_UNSAFE_INVISIBLES = new RegExp("[\\u0080-\\u009f\\p{Cf}\\u2028\\u2029]|\\p{Variation_Selector}", "gu");
|
|
18
|
-
function truncateCodePoints(str, max) {
|
|
19
|
-
const cp = Array.from(str);
|
|
20
|
-
return cp.length > max ? cp.slice(0, max).join("") : str;
|
|
21
|
-
}
|
|
22
|
-
__name(truncateCodePoints, "truncateCodePoints");
|
|
23
|
-
function sanitizeSenderName(name) {
|
|
24
|
-
const cleaned = name.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/[[\]\r\n]/g, " ");
|
|
25
|
-
return truncateCodePoints(cleaned, 64).trim() || "unknown";
|
|
26
|
-
}
|
|
27
|
-
__name(sanitizeSenderName, "sanitizeSenderName");
|
|
28
|
-
function sanitizeQuotedText(text, maxLen) {
|
|
29
|
-
const cleaned = text.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/["[\]]/g, " ");
|
|
30
|
-
const cp = Array.from(cleaned);
|
|
31
|
-
return cp.length > maxLen ? cp.slice(0, maxLen - 1).join("") + "\u2026" : cleaned;
|
|
32
|
-
}
|
|
33
|
-
__name(sanitizeQuotedText, "sanitizeQuotedText");
|
|
34
|
-
function sanitizePromptText(text) {
|
|
35
|
-
return text.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/^([ \t]*)\[([^\]\r\n]{1,64})\](:?)/gm, "$1$2$3").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
36
|
-
}
|
|
37
|
-
__name(sanitizePromptText, "sanitizePromptText");
|
|
38
|
-
function sanitizePromptPath(path4) {
|
|
39
|
-
const cleaned = path4.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
40
|
-
return truncateCodePoints(cleaned, 1024);
|
|
41
|
-
}
|
|
42
|
-
__name(sanitizePromptPath, "sanitizePromptPath");
|
|
43
|
-
function sanitizeLogText(text, maxLen) {
|
|
44
|
-
return truncateCodePoints(text, maxLen).replace(/\n/g, "\\n").replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
45
|
-
}
|
|
46
|
-
__name(sanitizeLogText, "sanitizeLogText");
|
|
47
|
-
|
|
48
|
-
// packages/channels/base/dist/index.js
|
|
49
|
-
init_esbuild_shims();
|
|
50
|
-
|
|
51
|
-
// packages/channels/base/dist/paths.js
|
|
52
|
-
init_esbuild_shims();
|
|
53
|
-
import * as crypto from "node:crypto";
|
|
54
|
-
import * as fs from "node:fs";
|
|
55
|
-
import * as path from "node:path";
|
|
56
|
-
import * as os from "node:os";
|
|
57
|
-
function resolvePath(dir) {
|
|
58
|
-
let resolved = dir;
|
|
59
|
-
if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
60
|
-
const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
|
|
61
|
-
resolved = path.join(os.homedir(), ...relativeSegments);
|
|
62
|
-
}
|
|
63
|
-
return path.resolve(resolved);
|
|
64
|
-
}
|
|
65
|
-
__name(resolvePath, "resolvePath");
|
|
66
|
-
function getGlobalQwenDir() {
|
|
67
|
-
const envDir = process.env["QWEN_HOME"];
|
|
68
|
-
if (envDir) {
|
|
69
|
-
return resolvePath(envDir);
|
|
70
|
-
}
|
|
71
|
-
const homeDir = os.homedir();
|
|
72
|
-
return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
|
|
73
|
-
}
|
|
74
|
-
__name(getGlobalQwenDir, "getGlobalQwenDir");
|
|
75
|
-
function canonicalizeWorkspacePath(workspaceCwd) {
|
|
76
|
-
const resolved = resolvePath(workspaceCwd);
|
|
77
|
-
try {
|
|
78
|
-
return fs.realpathSync.native(resolved);
|
|
79
|
-
} catch {
|
|
80
|
-
return resolved;
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
__name(canonicalizeWorkspacePath, "canonicalizeWorkspacePath");
|
|
84
|
-
function getWorkspaceScopeDirName(workspaceCwd) {
|
|
85
|
-
const resolved = canonicalizeWorkspacePath(workspaceCwd);
|
|
86
|
-
const hash = crypto.createHash("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
87
|
-
const base = path.basename(resolved).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 32);
|
|
88
|
-
return base ? `${base}-${hash}` : hash;
|
|
89
|
-
}
|
|
90
|
-
__name(getWorkspaceScopeDirName, "getWorkspaceScopeDirName");
|
|
91
|
-
|
|
92
|
-
// packages/channels/base/dist/AcpBridge.js
|
|
93
|
-
init_esbuild_shims();
|
|
94
|
-
import { spawn } from "node:child_process";
|
|
95
|
-
import { randomUUID } from "node:crypto";
|
|
96
|
-
import { Readable, Writable } from "node:stream";
|
|
97
|
-
import { EventEmitter } from "node:events";
|
|
98
|
-
|
|
99
15
|
// packages/channels/base/dist/ChannelLoopTools.js
|
|
100
16
|
init_esbuild_shims();
|
|
101
17
|
var CHANNEL_LOOP_MCP_SERVER_NAME = "channel_loop";
|
|
@@ -253,8 +169,290 @@ function readId(args) {
|
|
|
253
169
|
}
|
|
254
170
|
__name(readId, "readId");
|
|
255
171
|
|
|
172
|
+
// packages/channels/base/dist/sanitize.js
|
|
173
|
+
init_esbuild_shims();
|
|
174
|
+
var PROMPT_UNSAFE_INVISIBLES = new RegExp("[\\u0080-\\u009f\\p{Cf}\\u2028\\u2029]|\\p{Variation_Selector}", "gu");
|
|
175
|
+
function truncateCodePoints(str, max) {
|
|
176
|
+
const cp = Array.from(str);
|
|
177
|
+
return cp.length > max ? cp.slice(0, max).join("") : str;
|
|
178
|
+
}
|
|
179
|
+
__name(truncateCodePoints, "truncateCodePoints");
|
|
180
|
+
function sanitizeSenderName(name) {
|
|
181
|
+
const cleaned = name.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/[[\]\r\n]/g, " ");
|
|
182
|
+
return truncateCodePoints(cleaned, 64).trim() || "unknown";
|
|
183
|
+
}
|
|
184
|
+
__name(sanitizeSenderName, "sanitizeSenderName");
|
|
185
|
+
function sanitizeQuotedText(text, maxLen) {
|
|
186
|
+
const cleaned = text.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ").replace(/["[\]]/g, " ");
|
|
187
|
+
const cp = Array.from(cleaned);
|
|
188
|
+
return cp.length > maxLen ? cp.slice(0, maxLen - 1).join("") + "\u2026" : cleaned;
|
|
189
|
+
}
|
|
190
|
+
__name(sanitizeQuotedText, "sanitizeQuotedText");
|
|
191
|
+
function sanitizePromptText(text) {
|
|
192
|
+
return text.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/^([ \t]*)\[([^\]\r\n]{1,64})\](:?)/gm, "$1$2$3").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
193
|
+
}
|
|
194
|
+
__name(sanitizePromptText, "sanitizePromptText");
|
|
195
|
+
function sanitizePromptPath(path4) {
|
|
196
|
+
const cleaned = path4.replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
197
|
+
return truncateCodePoints(cleaned, 1024);
|
|
198
|
+
}
|
|
199
|
+
__name(sanitizePromptPath, "sanitizePromptPath");
|
|
200
|
+
function sanitizeLogText(text, maxLen) {
|
|
201
|
+
return truncateCodePoints(text, maxLen).replace(/\n/g, "\\n").replace(PROMPT_UNSAFE_INVISIBLES, " ").replace(/[\u0000-\u001f\u007f]/g, " ");
|
|
202
|
+
}
|
|
203
|
+
__name(sanitizeLogText, "sanitizeLogText");
|
|
204
|
+
|
|
205
|
+
// packages/channels/base/dist/PairingStore.js
|
|
206
|
+
init_esbuild_shims();
|
|
207
|
+
import * as crypto2 from "node:crypto";
|
|
208
|
+
import * as fs2 from "node:fs";
|
|
209
|
+
import * as path2 from "node:path";
|
|
210
|
+
|
|
211
|
+
// packages/channels/base/dist/paths.js
|
|
212
|
+
init_esbuild_shims();
|
|
213
|
+
import * as crypto from "node:crypto";
|
|
214
|
+
import * as fs from "node:fs";
|
|
215
|
+
import * as path from "node:path";
|
|
216
|
+
import * as os from "node:os";
|
|
217
|
+
function resolvePath(dir) {
|
|
218
|
+
let resolved = dir;
|
|
219
|
+
if (resolved === "~" || resolved.startsWith("~/") || resolved.startsWith("~\\")) {
|
|
220
|
+
const relativeSegments = resolved === "~" ? [] : resolved.slice(2).split(/[/\\]+/).filter(Boolean);
|
|
221
|
+
resolved = path.join(os.homedir(), ...relativeSegments);
|
|
222
|
+
}
|
|
223
|
+
return path.resolve(resolved);
|
|
224
|
+
}
|
|
225
|
+
__name(resolvePath, "resolvePath");
|
|
226
|
+
function getGlobalQwenDir() {
|
|
227
|
+
const envDir = process.env["QWEN_HOME"];
|
|
228
|
+
if (envDir) {
|
|
229
|
+
return resolvePath(envDir);
|
|
230
|
+
}
|
|
231
|
+
const homeDir = os.homedir();
|
|
232
|
+
return homeDir ? path.join(homeDir, ".qwen") : path.join(os.tmpdir(), ".qwen");
|
|
233
|
+
}
|
|
234
|
+
__name(getGlobalQwenDir, "getGlobalQwenDir");
|
|
235
|
+
function canonicalizeWorkspacePath(workspaceCwd) {
|
|
236
|
+
const resolved = resolvePath(workspaceCwd);
|
|
237
|
+
try {
|
|
238
|
+
return fs.realpathSync.native(resolved);
|
|
239
|
+
} catch {
|
|
240
|
+
return resolved;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
__name(canonicalizeWorkspacePath, "canonicalizeWorkspacePath");
|
|
244
|
+
function getWorkspaceScopeDirName(workspaceCwd) {
|
|
245
|
+
const resolved = canonicalizeWorkspacePath(workspaceCwd);
|
|
246
|
+
const hash = crypto.createHash("sha256").update(resolved).digest("hex").slice(0, 12);
|
|
247
|
+
const base = path.basename(resolved).replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 32);
|
|
248
|
+
return base ? `${base}-${hash}` : hash;
|
|
249
|
+
}
|
|
250
|
+
__name(getWorkspaceScopeDirName, "getWorkspaceScopeDirName");
|
|
251
|
+
|
|
252
|
+
// packages/channels/base/dist/PairingStore.js
|
|
253
|
+
var SAFE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
254
|
+
var CODE_LENGTH = 8;
|
|
255
|
+
var EXPIRY_MS = 60 * 60 * 1e3;
|
|
256
|
+
var MAX_PENDING = 3;
|
|
257
|
+
var PairingStore = class {
|
|
258
|
+
static {
|
|
259
|
+
__name(this, "PairingStore");
|
|
260
|
+
}
|
|
261
|
+
dir;
|
|
262
|
+
pendingPath;
|
|
263
|
+
allowlistPath;
|
|
264
|
+
migratedSentinelPath;
|
|
265
|
+
/**
|
|
266
|
+
* @param channelName Channel name the state is keyed by.
|
|
267
|
+
* @param workspaceCwd Workspace working directory to scope the state to.
|
|
268
|
+
* When provided, files live under
|
|
269
|
+
* `<qwen-home>/channels/<workspace-scope>/` so two workspaces using the
|
|
270
|
+
* same channel name never share pairing requests or allowlist entries
|
|
271
|
+
* (see #7017 — sharing them is an authorization-boundary violation in
|
|
272
|
+
* multi-workspace daemon deployments). Omitting it preserves the legacy
|
|
273
|
+
* global layout (`<qwen-home>/channels/`).
|
|
274
|
+
*/
|
|
275
|
+
constructor(channelName, workspaceCwd) {
|
|
276
|
+
const channelsRoot = path2.join(getGlobalQwenDir(), "channels");
|
|
277
|
+
this.dir = workspaceCwd ? path2.join(channelsRoot, getWorkspaceScopeDirName(workspaceCwd)) : channelsRoot;
|
|
278
|
+
const safeChannelName = encodeURIComponent(channelName);
|
|
279
|
+
this.pendingPath = path2.join(this.dir, `${safeChannelName}-pairing.json`);
|
|
280
|
+
this.allowlistPath = path2.join(this.dir, `${safeChannelName}-allowlist.json`);
|
|
281
|
+
this.migratedSentinelPath = path2.join(this.dir, `${safeChannelName}.migrated`);
|
|
282
|
+
if (workspaceCwd) {
|
|
283
|
+
this.migrateLegacyState(channelsRoot, channelName);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* One-time grandfathering of pre-scoping state: the first time this
|
|
288
|
+
* (workspace, channel) pair is constructed, copy the legacy GLOBAL files in
|
|
289
|
+
* so senders that were already approved stay approved after upgrading.
|
|
290
|
+
*
|
|
291
|
+
* Gated by a per-channel sentinel file inside the scope directory — NOT by
|
|
292
|
+
* the directory itself: one workspace can start several channels in turn,
|
|
293
|
+
* and a directory-level gate would let only the first channel ever migrate.
|
|
294
|
+
* The sentinel is written even when there was nothing to copy, so a legacy
|
|
295
|
+
* file written later (e.g. by an older version still running concurrently)
|
|
296
|
+
* is never absorbed into a scope that already went through this decision.
|
|
297
|
+
*
|
|
298
|
+
* Each file is copied independently and best-effort (an unreadable pairing
|
|
299
|
+
* file must not block the allowlist, and vice versa), via a
|
|
300
|
+
* uniquely-named temp file + atomic rename so a crash mid-copy cannot
|
|
301
|
+
* leave a truncated scoped file behind the closed gate. A file the scoped
|
|
302
|
+
* store already has is never overwritten.
|
|
303
|
+
*
|
|
304
|
+
* Copy, not move: another workspace upgrading later must be able to
|
|
305
|
+
* grandfather the same baseline, and an older qwen version running
|
|
306
|
+
* concurrently still reads the global files.
|
|
307
|
+
*
|
|
308
|
+
* Revocation therefore means REMOVING ENTRIES from the scoped allowlist
|
|
309
|
+
* (and from the legacy global file, while it exists) — not deleting files.
|
|
310
|
+
*/
|
|
311
|
+
migrateLegacyState(channelsRoot, channelName) {
|
|
312
|
+
try {
|
|
313
|
+
if (fs2.existsSync(this.migratedSentinelPath)) {
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
const legacyPairs = [
|
|
317
|
+
[
|
|
318
|
+
path2.join(channelsRoot, `${channelName}-pairing.json`),
|
|
319
|
+
this.pendingPath
|
|
320
|
+
],
|
|
321
|
+
[
|
|
322
|
+
path2.join(channelsRoot, `${channelName}-allowlist.json`),
|
|
323
|
+
this.allowlistPath
|
|
324
|
+
]
|
|
325
|
+
];
|
|
326
|
+
this.ensureDir();
|
|
327
|
+
let allSucceeded = true;
|
|
328
|
+
for (const [legacyPath, scopedPath] of legacyPairs) {
|
|
329
|
+
try {
|
|
330
|
+
if (path2.dirname(path2.resolve(legacyPath)) !== channelsRoot) {
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (fs2.existsSync(scopedPath) || !fs2.existsSync(legacyPath)) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
const tmpPath = `${scopedPath}.${process.pid}.migrating`;
|
|
337
|
+
fs2.copyFileSync(legacyPath, tmpPath);
|
|
338
|
+
fs2.renameSync(tmpPath, scopedPath);
|
|
339
|
+
} catch (err) {
|
|
340
|
+
allSucceeded = false;
|
|
341
|
+
process.stderr.write(`[PairingStore] legacy migration of ${path2.basename(legacyPath)} failed for channel "${channelName}": ${err?.message}; will retry on next start
|
|
342
|
+
`);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (allSucceeded) {
|
|
346
|
+
fs2.writeFileSync(this.migratedSentinelPath, "");
|
|
347
|
+
}
|
|
348
|
+
} catch (err) {
|
|
349
|
+
process.stderr.write(`[PairingStore] legacy migration failed for channel "${channelName}": ${err?.message}; scoped store starts empty
|
|
350
|
+
`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
isApproved(senderId) {
|
|
354
|
+
const list = this.readAllowlist();
|
|
355
|
+
return list.includes(senderId);
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Create a pairing request for an unknown sender.
|
|
359
|
+
* Returns the code if created, or null if the pending cap is reached.
|
|
360
|
+
* If the sender already has a non-expired pending request, returns that code.
|
|
361
|
+
*/
|
|
362
|
+
createRequest(senderId, senderName) {
|
|
363
|
+
const pending = this.readPending();
|
|
364
|
+
const now = Date.now();
|
|
365
|
+
const active = pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
366
|
+
const existing = active.find((r) => r.senderId === senderId);
|
|
367
|
+
if (existing) {
|
|
368
|
+
return existing.code;
|
|
369
|
+
}
|
|
370
|
+
if (active.length >= MAX_PENDING) {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
const code = generateCode();
|
|
374
|
+
active.push({ senderId, senderName, code, createdAt: now });
|
|
375
|
+
this.writePending(active);
|
|
376
|
+
return code;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Approve a pairing request by code.
|
|
380
|
+
* Returns the sender ID if found, or null if not found / expired.
|
|
381
|
+
*/
|
|
382
|
+
approve(code) {
|
|
383
|
+
const pending = this.readPending();
|
|
384
|
+
const now = Date.now();
|
|
385
|
+
const idx = pending.findIndex((r) => r.code === code.toUpperCase() && now - r.createdAt < EXPIRY_MS);
|
|
386
|
+
if (idx === -1)
|
|
387
|
+
return null;
|
|
388
|
+
const request = pending[idx];
|
|
389
|
+
pending.splice(idx, 1);
|
|
390
|
+
this.writePending(pending);
|
|
391
|
+
const list = this.readAllowlist();
|
|
392
|
+
if (!list.includes(request.senderId)) {
|
|
393
|
+
list.push(request.senderId);
|
|
394
|
+
this.writeAllowlist(list);
|
|
395
|
+
}
|
|
396
|
+
return request;
|
|
397
|
+
}
|
|
398
|
+
listPending() {
|
|
399
|
+
const pending = this.readPending();
|
|
400
|
+
const now = Date.now();
|
|
401
|
+
return pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
402
|
+
}
|
|
403
|
+
getAllowlist() {
|
|
404
|
+
return this.readAllowlist();
|
|
405
|
+
}
|
|
406
|
+
ensureDir() {
|
|
407
|
+
if (!fs2.existsSync(this.dir)) {
|
|
408
|
+
fs2.mkdirSync(this.dir, { recursive: true });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
readPending() {
|
|
412
|
+
try {
|
|
413
|
+
const data = fs2.readFileSync(this.pendingPath, "utf-8");
|
|
414
|
+
return JSON.parse(data);
|
|
415
|
+
} catch {
|
|
416
|
+
return [];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
writePending(requests) {
|
|
420
|
+
this.ensureDir();
|
|
421
|
+
fs2.writeFileSync(this.pendingPath, JSON.stringify(requests, null, 2));
|
|
422
|
+
}
|
|
423
|
+
readAllowlist() {
|
|
424
|
+
try {
|
|
425
|
+
const data = fs2.readFileSync(this.allowlistPath, "utf-8");
|
|
426
|
+
return JSON.parse(data);
|
|
427
|
+
} catch {
|
|
428
|
+
return [];
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
writeAllowlist(list) {
|
|
432
|
+
this.ensureDir();
|
|
433
|
+
fs2.writeFileSync(this.allowlistPath, JSON.stringify(list, null, 2));
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
function generateCode() {
|
|
437
|
+
let code = "";
|
|
438
|
+
for (let i = 0; i < CODE_LENGTH; i++) {
|
|
439
|
+
code += SAFE_ALPHABET[crypto2.randomInt(SAFE_ALPHABET.length)];
|
|
440
|
+
}
|
|
441
|
+
return code;
|
|
442
|
+
}
|
|
443
|
+
__name(generateCode, "generateCode");
|
|
444
|
+
|
|
445
|
+
// packages/channels/base/dist/index.js
|
|
446
|
+
init_esbuild_shims();
|
|
447
|
+
|
|
256
448
|
// packages/channels/base/dist/AcpBridge.js
|
|
449
|
+
init_esbuild_shims();
|
|
450
|
+
import { spawn } from "node:child_process";
|
|
451
|
+
import { randomUUID } from "node:crypto";
|
|
452
|
+
import { Readable, Writable } from "node:stream";
|
|
453
|
+
import { EventEmitter } from "node:events";
|
|
257
454
|
var MID_TURN_QUEUE_DRAIN_METHOD = "craft/drainMidTurnQueue";
|
|
455
|
+
var TODO_STOP_GUARD_CONTINUATION_CLAIM_METHOD = "craft/claimTodoStopGuardContinuation";
|
|
258
456
|
var ACP_EVENT_LOOP_STALL_RESTART_MS = 5 * 60 * 1e3;
|
|
259
457
|
var ACP_PERMISSION_RESPONSE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
260
458
|
var ACP_EVENT_LOOP_STALL_RE = /^\[perf\] acp agent event loop stall: max=(\d+(?:\.\d+)?)ms/m;
|
|
@@ -281,6 +479,8 @@ var AcpBridge = class extends EventEmitter {
|
|
|
281
479
|
_availableCommands = [];
|
|
282
480
|
channelLoopMcpServer;
|
|
283
481
|
channelLoopToolHandlers = [];
|
|
482
|
+
knownSessionIds = /* @__PURE__ */ new Set();
|
|
483
|
+
sessionBindingTokens = /* @__PURE__ */ new Map();
|
|
284
484
|
channelLoopMcpRegistered = false;
|
|
285
485
|
channelLoopMcpRegistration = null;
|
|
286
486
|
pendingPermissions = /* @__PURE__ */ new Map();
|
|
@@ -319,6 +519,8 @@ var AcpBridge = class extends EventEmitter {
|
|
|
319
519
|
process.stderr.write(`[AcpBridge] Process exited (code=${code}, signal=${signal})
|
|
320
520
|
`);
|
|
321
521
|
this.resolvePendingPermissions();
|
|
522
|
+
this.knownSessionIds.clear();
|
|
523
|
+
this.sessionBindingTokens.clear();
|
|
322
524
|
this.connection = null;
|
|
323
525
|
this.child = null;
|
|
324
526
|
this.emit("disconnected", code, signal);
|
|
@@ -357,21 +559,25 @@ var AcpBridge = class extends EventEmitter {
|
|
|
357
559
|
});
|
|
358
560
|
void this.registerChannelLoopMcpServer();
|
|
359
561
|
}
|
|
360
|
-
async newSession(cwd) {
|
|
562
|
+
async newSession(cwd, _options, bindingToken) {
|
|
361
563
|
const conn = this.ensureConnection();
|
|
362
564
|
await this.registerChannelLoopMcpServer();
|
|
363
565
|
const response = await conn.newSession({ cwd, mcpServers: [] });
|
|
566
|
+
this.knownSessionIds.add(response.sessionId);
|
|
567
|
+
this.sessionBindingTokens.set(response.sessionId, bindingToken);
|
|
364
568
|
return response.sessionId;
|
|
365
569
|
}
|
|
366
|
-
async loadSession(sessionId, cwd) {
|
|
570
|
+
async loadSession(sessionId, cwd, _options, bindingToken) {
|
|
367
571
|
const conn = this.ensureConnection();
|
|
368
572
|
await this.registerChannelLoopMcpServer();
|
|
369
|
-
|
|
573
|
+
await conn.loadSession({
|
|
370
574
|
sessionId,
|
|
371
575
|
cwd,
|
|
372
576
|
mcpServers: []
|
|
373
577
|
});
|
|
374
|
-
|
|
578
|
+
this.knownSessionIds.add(sessionId);
|
|
579
|
+
this.sessionBindingTokens.set(sessionId, bindingToken);
|
|
580
|
+
return sessionId;
|
|
375
581
|
}
|
|
376
582
|
async prompt(sessionId, text, options) {
|
|
377
583
|
const conn = this.ensureConnection();
|
|
@@ -423,6 +629,19 @@ var AcpBridge = class extends EventEmitter {
|
|
|
423
629
|
this.resolvePendingPermissions(sessionId);
|
|
424
630
|
}
|
|
425
631
|
}
|
|
632
|
+
async discardSession(sessionId, expectedBindingToken) {
|
|
633
|
+
if (expectedBindingToken !== void 0 && this.sessionBindingTokens.get(sessionId) !== expectedBindingToken) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
if (!this.knownSessionIds.delete(sessionId))
|
|
637
|
+
return;
|
|
638
|
+
this.sessionBindingTokens.delete(sessionId);
|
|
639
|
+
this.resolvePendingPermissions(sessionId);
|
|
640
|
+
const conn = this.connection;
|
|
641
|
+
if (!conn || !this.isConnected)
|
|
642
|
+
return;
|
|
643
|
+
await conn.extMethod("qwen/control/session/close", { sessionId });
|
|
644
|
+
}
|
|
426
645
|
async respondToPermission(requestId, response) {
|
|
427
646
|
const pending = this.pendingPermissions.get(requestId);
|
|
428
647
|
if (!pending) {
|
|
@@ -439,6 +658,8 @@ var AcpBridge = class extends EventEmitter {
|
|
|
439
658
|
}
|
|
440
659
|
stop() {
|
|
441
660
|
this.resolvePendingPermissions();
|
|
661
|
+
this.knownSessionIds.clear();
|
|
662
|
+
this.sessionBindingTokens.clear();
|
|
442
663
|
if (this.child) {
|
|
443
664
|
this.child.kill();
|
|
444
665
|
this.child = null;
|
|
@@ -615,7 +836,14 @@ var AcpBridge = class extends EventEmitter {
|
|
|
615
836
|
return this.handleClientMcpMessage(params);
|
|
616
837
|
}
|
|
617
838
|
if (method === MID_TURN_QUEUE_DRAIN_METHOD) {
|
|
618
|
-
return { messages: [] };
|
|
839
|
+
return { messages: [], hasQueuedPrompt: false };
|
|
840
|
+
}
|
|
841
|
+
if (method === TODO_STOP_GUARD_CONTINUATION_CLAIM_METHOD) {
|
|
842
|
+
const sessionId = typeof params["sessionId"] === "string" ? params["sessionId"] : "";
|
|
843
|
+
return {
|
|
844
|
+
claimed: this.knownSessionIds.has(sessionId),
|
|
845
|
+
hasQueuedPrompt: false
|
|
846
|
+
};
|
|
619
847
|
}
|
|
620
848
|
throw new Error(`Method not found: ${method}`);
|
|
621
849
|
}
|
|
@@ -749,6 +977,10 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
749
977
|
activePromptControllers = /* @__PURE__ */ new Map();
|
|
750
978
|
availableCommandsBySession = /* @__PURE__ */ new Map();
|
|
751
979
|
turnBarriers = /* @__PURE__ */ new Map();
|
|
980
|
+
channelLoopToolHandlers = [];
|
|
981
|
+
registeredChannelLoopMcpSessions = /* @__PURE__ */ new Set();
|
|
982
|
+
channelLoopMcpRegistrations = /* @__PURE__ */ new Map();
|
|
983
|
+
channelLoopMcpServer;
|
|
752
984
|
connected = false;
|
|
753
985
|
lifecycleGeneration = 0;
|
|
754
986
|
latestAvailableCommandsSessionId;
|
|
@@ -799,6 +1031,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
799
1031
|
await this.rejectStaleSession(session);
|
|
800
1032
|
}
|
|
801
1033
|
this.attachSession(session, bindingToken);
|
|
1034
|
+
await this.registerChannelLoopMcpForSession(session.sessionId);
|
|
802
1035
|
return session.sessionId;
|
|
803
1036
|
}
|
|
804
1037
|
async loadSession(sessionId, cwd, options, bindingToken) {
|
|
@@ -820,8 +1053,22 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
820
1053
|
throw new Error(`Daemon returned session ${session.sessionId} while loading ${sessionId}`);
|
|
821
1054
|
}
|
|
822
1055
|
this.attachSession(session, bindingToken);
|
|
1056
|
+
await this.registerChannelLoopMcpForSession(session.sessionId);
|
|
823
1057
|
return session.sessionId;
|
|
824
1058
|
}
|
|
1059
|
+
registerChannelLoopToolHandler(handler) {
|
|
1060
|
+
if (!this.channelLoopToolHandlers.includes(handler)) {
|
|
1061
|
+
this.channelLoopToolHandlers.push(handler);
|
|
1062
|
+
}
|
|
1063
|
+
this.channelLoopMcpServer ??= new ChannelLoopMcpServer({
|
|
1064
|
+
create: /* @__PURE__ */ __name((sessionId, input) => this.resolveChannelLoopToolHandler(sessionId).create(sessionId, input), "create"),
|
|
1065
|
+
list: /* @__PURE__ */ __name((sessionId) => this.resolveChannelLoopToolHandler(sessionId).list(sessionId), "list"),
|
|
1066
|
+
cancel: /* @__PURE__ */ __name((sessionId, id) => this.resolveChannelLoopToolHandler(sessionId).cancel(sessionId, id), "cancel")
|
|
1067
|
+
});
|
|
1068
|
+
for (const sessionId of this.sessions.keys()) {
|
|
1069
|
+
void this.registerChannelLoopMcpForSession(sessionId);
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
825
1072
|
async prompt(sessionId, text, options) {
|
|
826
1073
|
const session = this.ensureSession(sessionId);
|
|
827
1074
|
if (this.activePrompts.has(sessionId)) {
|
|
@@ -978,7 +1225,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
978
1225
|
return this.connected;
|
|
979
1226
|
}
|
|
980
1227
|
attachSession(session, bindingToken) {
|
|
981
|
-
const replacedSession = this.removeSessionBinding(session.sessionId);
|
|
1228
|
+
const replacedSession = this.removeSessionBinding(session.sessionId, false);
|
|
982
1229
|
if (replacedSession) {
|
|
983
1230
|
void this.releaseSessionClient(replacedSession).catch((error) => {
|
|
984
1231
|
this.lastError = error;
|
|
@@ -1242,7 +1489,7 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1242
1489
|
}
|
|
1243
1490
|
this.emit("sessionDied", { sessionId, reason });
|
|
1244
1491
|
}
|
|
1245
|
-
removeSessionBinding(sessionId) {
|
|
1492
|
+
removeSessionBinding(sessionId, unregisterChannelLoopMcp = true) {
|
|
1246
1493
|
const session = this.sessions.get(sessionId);
|
|
1247
1494
|
if (!session)
|
|
1248
1495
|
return void 0;
|
|
@@ -1266,8 +1513,51 @@ var DaemonChannelBridge = class extends EventEmitter2 {
|
|
|
1266
1513
|
if (mappedSessionId === sessionId) {
|
|
1267
1514
|
this.respondedRequestToSession.delete(requestId);
|
|
1268
1515
|
}
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1516
|
+
}
|
|
1517
|
+
if (unregisterChannelLoopMcp) {
|
|
1518
|
+
this.unregisterChannelLoopMcpForSession(sessionId);
|
|
1519
|
+
}
|
|
1520
|
+
return session;
|
|
1521
|
+
}
|
|
1522
|
+
async registerChannelLoopMcpForSession(sessionId) {
|
|
1523
|
+
const host = this.options.channelLoopMcpHost;
|
|
1524
|
+
const server = this.channelLoopMcpServer;
|
|
1525
|
+
if (!host || !server || this.registeredChannelLoopMcpSessions.has(sessionId)) {
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
const pending = this.channelLoopMcpRegistrations.get(sessionId);
|
|
1529
|
+
if (pending) {
|
|
1530
|
+
await pending;
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
const registration = host.register(sessionId, (message) => server.handleMessage(message, { sessionId })).then(async () => {
|
|
1534
|
+
if (this.sessions.has(sessionId)) {
|
|
1535
|
+
this.registeredChannelLoopMcpSessions.add(sessionId);
|
|
1536
|
+
} else {
|
|
1537
|
+
await host.unregister(sessionId);
|
|
1538
|
+
}
|
|
1539
|
+
}).catch((error) => {
|
|
1540
|
+
this.lastError = error;
|
|
1541
|
+
}).finally(() => {
|
|
1542
|
+
if (this.channelLoopMcpRegistrations.get(sessionId) === registration) {
|
|
1543
|
+
this.channelLoopMcpRegistrations.delete(sessionId);
|
|
1544
|
+
}
|
|
1545
|
+
});
|
|
1546
|
+
this.channelLoopMcpRegistrations.set(sessionId, registration);
|
|
1547
|
+
await registration;
|
|
1548
|
+
}
|
|
1549
|
+
unregisterChannelLoopMcpForSession(sessionId) {
|
|
1550
|
+
if (!this.registeredChannelLoopMcpSessions.delete(sessionId))
|
|
1551
|
+
return;
|
|
1552
|
+
void this.options.channelLoopMcpHost?.unregister(sessionId).catch((error) => {
|
|
1553
|
+
this.lastError = error;
|
|
1554
|
+
});
|
|
1555
|
+
}
|
|
1556
|
+
resolveChannelLoopToolHandler(sessionId) {
|
|
1557
|
+
const handler = this.channelLoopToolHandlers.find((candidate) => candidate.canHandle?.(sessionId) === true || this.channelLoopToolHandlers.length === 1 && !candidate.canHandle);
|
|
1558
|
+
if (handler)
|
|
1559
|
+
return handler;
|
|
1560
|
+
throw new Error(`No channel loop handler matched session ${sessionId}.`);
|
|
1271
1561
|
}
|
|
1272
1562
|
getStringField(data, field, fallback) {
|
|
1273
1563
|
return isRecord(data) && typeof data[field] === "string" ? data[field] : fallback;
|
|
@@ -1515,8 +1805,8 @@ var DmGate = class {
|
|
|
1515
1805
|
|
|
1516
1806
|
// packages/channels/base/dist/group-history-store.js
|
|
1517
1807
|
init_esbuild_shims();
|
|
1518
|
-
import { appendFileSync, chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1519
|
-
import { dirname, join as
|
|
1808
|
+
import { appendFileSync, chmodSync, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
1809
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
1520
1810
|
var DEFAULT_MAX_KEYS = 1e3;
|
|
1521
1811
|
var DEFAULT_COMPACT_AFTER_RECORDS = 1e3;
|
|
1522
1812
|
var GroupHistoryStore = class {
|
|
@@ -1628,12 +1918,12 @@ var GroupHistoryStore = class {
|
|
|
1628
1918
|
};
|
|
1629
1919
|
}
|
|
1630
1920
|
readRecords() {
|
|
1631
|
-
if (!
|
|
1921
|
+
if (!existsSync2(this.filePath)) {
|
|
1632
1922
|
return { records: [], hadInvalidRecords: false };
|
|
1633
1923
|
}
|
|
1634
1924
|
let data;
|
|
1635
1925
|
try {
|
|
1636
|
-
data =
|
|
1926
|
+
data = readFileSync2(this.filePath, "utf-8");
|
|
1637
1927
|
} catch (err) {
|
|
1638
1928
|
if (isErrnoCode(err, "ENOENT")) {
|
|
1639
1929
|
return { records: [], hadInvalidRecords: false };
|
|
@@ -1660,8 +1950,8 @@ var GroupHistoryStore = class {
|
|
|
1660
1950
|
return { records, hadInvalidRecords };
|
|
1661
1951
|
}
|
|
1662
1952
|
append(record) {
|
|
1663
|
-
const dir =
|
|
1664
|
-
|
|
1953
|
+
const dir = dirname2(this.filePath);
|
|
1954
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
1665
1955
|
chmodPrivate(dir, 448);
|
|
1666
1956
|
appendFileSync(this.filePath, `${JSON.stringify(record)}
|
|
1667
1957
|
`, {
|
|
@@ -1671,8 +1961,8 @@ var GroupHistoryStore = class {
|
|
|
1671
1961
|
chmodPrivate(this.filePath, 384);
|
|
1672
1962
|
}
|
|
1673
1963
|
compact(state, limits) {
|
|
1674
|
-
const dir =
|
|
1675
|
-
|
|
1964
|
+
const dir = dirname2(this.filePath);
|
|
1965
|
+
mkdirSync2(dir, { recursive: true, mode: 448 });
|
|
1676
1966
|
chmodPrivate(dir, 448);
|
|
1677
1967
|
const records = [];
|
|
1678
1968
|
const recordedAt = Date.now();
|
|
@@ -1689,10 +1979,10 @@ var GroupHistoryStore = class {
|
|
|
1689
1979
|
}
|
|
1690
1980
|
const data = records.length > 0 ? `${records.map((record) => JSON.stringify(record)).join("\n")}
|
|
1691
1981
|
` : "";
|
|
1692
|
-
const tempPath =
|
|
1693
|
-
|
|
1982
|
+
const tempPath = join3(dir, `${Date.now()}-${process.pid}-${Math.random().toString(16).slice(2)}.tmp`);
|
|
1983
|
+
writeFileSync2(tempPath, data, { encoding: "utf-8", mode: 384 });
|
|
1694
1984
|
chmodPrivate(tempPath, 384);
|
|
1695
|
-
|
|
1985
|
+
renameSync2(tempPath, this.filePath);
|
|
1696
1986
|
chmodPrivate(this.filePath, 384);
|
|
1697
1987
|
}
|
|
1698
1988
|
};
|
|
@@ -1764,6 +2054,9 @@ var SenderGate = class {
|
|
|
1764
2054
|
this.allowedUsers = new Set(allowedUsers);
|
|
1765
2055
|
this.pairingStore = pairingStore || null;
|
|
1766
2056
|
}
|
|
2057
|
+
replaceAllowedUsers(users) {
|
|
2058
|
+
this.allowedUsers = new Set(users);
|
|
2059
|
+
}
|
|
1767
2060
|
isAllowed(senderId) {
|
|
1768
2061
|
switch (this.policy) {
|
|
1769
2062
|
case "open":
|
|
@@ -1798,203 +2091,6 @@ var SenderGate = class {
|
|
|
1798
2091
|
}
|
|
1799
2092
|
};
|
|
1800
2093
|
|
|
1801
|
-
// packages/channels/base/dist/PairingStore.js
|
|
1802
|
-
init_esbuild_shims();
|
|
1803
|
-
import * as crypto2 from "node:crypto";
|
|
1804
|
-
import * as fs2 from "node:fs";
|
|
1805
|
-
import * as path2 from "node:path";
|
|
1806
|
-
var SAFE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
1807
|
-
var CODE_LENGTH = 8;
|
|
1808
|
-
var EXPIRY_MS = 60 * 60 * 1e3;
|
|
1809
|
-
var MAX_PENDING = 3;
|
|
1810
|
-
var PairingStore = class {
|
|
1811
|
-
static {
|
|
1812
|
-
__name(this, "PairingStore");
|
|
1813
|
-
}
|
|
1814
|
-
dir;
|
|
1815
|
-
pendingPath;
|
|
1816
|
-
allowlistPath;
|
|
1817
|
-
migratedSentinelPath;
|
|
1818
|
-
/**
|
|
1819
|
-
* @param channelName Channel name the state is keyed by.
|
|
1820
|
-
* @param workspaceCwd Workspace working directory to scope the state to.
|
|
1821
|
-
* When provided, files live under
|
|
1822
|
-
* `<qwen-home>/channels/<workspace-scope>/` so two workspaces using the
|
|
1823
|
-
* same channel name never share pairing requests or allowlist entries
|
|
1824
|
-
* (see #7017 — sharing them is an authorization-boundary violation in
|
|
1825
|
-
* multi-workspace daemon deployments). Omitting it preserves the legacy
|
|
1826
|
-
* global layout (`<qwen-home>/channels/`).
|
|
1827
|
-
*/
|
|
1828
|
-
constructor(channelName, workspaceCwd) {
|
|
1829
|
-
const channelsRoot = path2.join(getGlobalQwenDir(), "channels");
|
|
1830
|
-
this.dir = workspaceCwd ? path2.join(channelsRoot, getWorkspaceScopeDirName(workspaceCwd)) : channelsRoot;
|
|
1831
|
-
const safeChannelName = encodeURIComponent(channelName);
|
|
1832
|
-
this.pendingPath = path2.join(this.dir, `${safeChannelName}-pairing.json`);
|
|
1833
|
-
this.allowlistPath = path2.join(this.dir, `${safeChannelName}-allowlist.json`);
|
|
1834
|
-
this.migratedSentinelPath = path2.join(this.dir, `${safeChannelName}.migrated`);
|
|
1835
|
-
if (workspaceCwd) {
|
|
1836
|
-
this.migrateLegacyState(channelsRoot, channelName);
|
|
1837
|
-
}
|
|
1838
|
-
}
|
|
1839
|
-
/**
|
|
1840
|
-
* One-time grandfathering of pre-scoping state: the first time this
|
|
1841
|
-
* (workspace, channel) pair is constructed, copy the legacy GLOBAL files in
|
|
1842
|
-
* so senders that were already approved stay approved after upgrading.
|
|
1843
|
-
*
|
|
1844
|
-
* Gated by a per-channel sentinel file inside the scope directory — NOT by
|
|
1845
|
-
* the directory itself: one workspace can start several channels in turn,
|
|
1846
|
-
* and a directory-level gate would let only the first channel ever migrate.
|
|
1847
|
-
* The sentinel is written even when there was nothing to copy, so a legacy
|
|
1848
|
-
* file written later (e.g. by an older version still running concurrently)
|
|
1849
|
-
* is never absorbed into a scope that already went through this decision.
|
|
1850
|
-
*
|
|
1851
|
-
* Each file is copied independently and best-effort (an unreadable pairing
|
|
1852
|
-
* file must not block the allowlist, and vice versa), via a
|
|
1853
|
-
* uniquely-named temp file + atomic rename so a crash mid-copy cannot
|
|
1854
|
-
* leave a truncated scoped file behind the closed gate. A file the scoped
|
|
1855
|
-
* store already has is never overwritten.
|
|
1856
|
-
*
|
|
1857
|
-
* Copy, not move: another workspace upgrading later must be able to
|
|
1858
|
-
* grandfather the same baseline, and an older qwen version running
|
|
1859
|
-
* concurrently still reads the global files.
|
|
1860
|
-
*
|
|
1861
|
-
* Revocation therefore means REMOVING ENTRIES from the scoped allowlist
|
|
1862
|
-
* (and from the legacy global file, while it exists) — not deleting files.
|
|
1863
|
-
*/
|
|
1864
|
-
migrateLegacyState(channelsRoot, channelName) {
|
|
1865
|
-
try {
|
|
1866
|
-
if (fs2.existsSync(this.migratedSentinelPath)) {
|
|
1867
|
-
return;
|
|
1868
|
-
}
|
|
1869
|
-
const legacyPairs = [
|
|
1870
|
-
[
|
|
1871
|
-
path2.join(channelsRoot, `${channelName}-pairing.json`),
|
|
1872
|
-
this.pendingPath
|
|
1873
|
-
],
|
|
1874
|
-
[
|
|
1875
|
-
path2.join(channelsRoot, `${channelName}-allowlist.json`),
|
|
1876
|
-
this.allowlistPath
|
|
1877
|
-
]
|
|
1878
|
-
];
|
|
1879
|
-
this.ensureDir();
|
|
1880
|
-
let allSucceeded = true;
|
|
1881
|
-
for (const [legacyPath, scopedPath] of legacyPairs) {
|
|
1882
|
-
try {
|
|
1883
|
-
if (path2.dirname(path2.resolve(legacyPath)) !== channelsRoot) {
|
|
1884
|
-
continue;
|
|
1885
|
-
}
|
|
1886
|
-
if (fs2.existsSync(scopedPath) || !fs2.existsSync(legacyPath)) {
|
|
1887
|
-
continue;
|
|
1888
|
-
}
|
|
1889
|
-
const tmpPath = `${scopedPath}.${process.pid}.migrating`;
|
|
1890
|
-
fs2.copyFileSync(legacyPath, tmpPath);
|
|
1891
|
-
fs2.renameSync(tmpPath, scopedPath);
|
|
1892
|
-
} catch (err) {
|
|
1893
|
-
allSucceeded = false;
|
|
1894
|
-
process.stderr.write(`[PairingStore] legacy migration of ${path2.basename(legacyPath)} failed for channel "${channelName}": ${err?.message}; will retry on next start
|
|
1895
|
-
`);
|
|
1896
|
-
}
|
|
1897
|
-
}
|
|
1898
|
-
if (allSucceeded) {
|
|
1899
|
-
fs2.writeFileSync(this.migratedSentinelPath, "");
|
|
1900
|
-
}
|
|
1901
|
-
} catch (err) {
|
|
1902
|
-
process.stderr.write(`[PairingStore] legacy migration failed for channel "${channelName}": ${err?.message}; scoped store starts empty
|
|
1903
|
-
`);
|
|
1904
|
-
}
|
|
1905
|
-
}
|
|
1906
|
-
isApproved(senderId) {
|
|
1907
|
-
const list = this.readAllowlist();
|
|
1908
|
-
return list.includes(senderId);
|
|
1909
|
-
}
|
|
1910
|
-
/**
|
|
1911
|
-
* Create a pairing request for an unknown sender.
|
|
1912
|
-
* Returns the code if created, or null if the pending cap is reached.
|
|
1913
|
-
* If the sender already has a non-expired pending request, returns that code.
|
|
1914
|
-
*/
|
|
1915
|
-
createRequest(senderId, senderName) {
|
|
1916
|
-
const pending = this.readPending();
|
|
1917
|
-
const now = Date.now();
|
|
1918
|
-
const active = pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
1919
|
-
const existing = active.find((r) => r.senderId === senderId);
|
|
1920
|
-
if (existing) {
|
|
1921
|
-
return existing.code;
|
|
1922
|
-
}
|
|
1923
|
-
if (active.length >= MAX_PENDING) {
|
|
1924
|
-
return null;
|
|
1925
|
-
}
|
|
1926
|
-
const code = generateCode();
|
|
1927
|
-
active.push({ senderId, senderName, code, createdAt: now });
|
|
1928
|
-
this.writePending(active);
|
|
1929
|
-
return code;
|
|
1930
|
-
}
|
|
1931
|
-
/**
|
|
1932
|
-
* Approve a pairing request by code.
|
|
1933
|
-
* Returns the sender ID if found, or null if not found / expired.
|
|
1934
|
-
*/
|
|
1935
|
-
approve(code) {
|
|
1936
|
-
const pending = this.readPending();
|
|
1937
|
-
const now = Date.now();
|
|
1938
|
-
const idx = pending.findIndex((r) => r.code === code.toUpperCase() && now - r.createdAt < EXPIRY_MS);
|
|
1939
|
-
if (idx === -1)
|
|
1940
|
-
return null;
|
|
1941
|
-
const request = pending[idx];
|
|
1942
|
-
pending.splice(idx, 1);
|
|
1943
|
-
this.writePending(pending);
|
|
1944
|
-
const list = this.readAllowlist();
|
|
1945
|
-
if (!list.includes(request.senderId)) {
|
|
1946
|
-
list.push(request.senderId);
|
|
1947
|
-
this.writeAllowlist(list);
|
|
1948
|
-
}
|
|
1949
|
-
return request;
|
|
1950
|
-
}
|
|
1951
|
-
listPending() {
|
|
1952
|
-
const pending = this.readPending();
|
|
1953
|
-
const now = Date.now();
|
|
1954
|
-
return pending.filter((r) => now - r.createdAt < EXPIRY_MS);
|
|
1955
|
-
}
|
|
1956
|
-
getAllowlist() {
|
|
1957
|
-
return this.readAllowlist();
|
|
1958
|
-
}
|
|
1959
|
-
ensureDir() {
|
|
1960
|
-
if (!fs2.existsSync(this.dir)) {
|
|
1961
|
-
fs2.mkdirSync(this.dir, { recursive: true });
|
|
1962
|
-
}
|
|
1963
|
-
}
|
|
1964
|
-
readPending() {
|
|
1965
|
-
try {
|
|
1966
|
-
const data = fs2.readFileSync(this.pendingPath, "utf-8");
|
|
1967
|
-
return JSON.parse(data);
|
|
1968
|
-
} catch {
|
|
1969
|
-
return [];
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
writePending(requests) {
|
|
1973
|
-
this.ensureDir();
|
|
1974
|
-
fs2.writeFileSync(this.pendingPath, JSON.stringify(requests, null, 2));
|
|
1975
|
-
}
|
|
1976
|
-
readAllowlist() {
|
|
1977
|
-
try {
|
|
1978
|
-
const data = fs2.readFileSync(this.allowlistPath, "utf-8");
|
|
1979
|
-
return JSON.parse(data);
|
|
1980
|
-
} catch {
|
|
1981
|
-
return [];
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
writeAllowlist(list) {
|
|
1985
|
-
this.ensureDir();
|
|
1986
|
-
fs2.writeFileSync(this.allowlistPath, JSON.stringify(list, null, 2));
|
|
1987
|
-
}
|
|
1988
|
-
};
|
|
1989
|
-
function generateCode() {
|
|
1990
|
-
let code = "";
|
|
1991
|
-
for (let i = 0; i < CODE_LENGTH; i++) {
|
|
1992
|
-
code += SAFE_ALPHABET[crypto2.randomInt(SAFE_ALPHABET.length)];
|
|
1993
|
-
}
|
|
1994
|
-
return code;
|
|
1995
|
-
}
|
|
1996
|
-
__name(generateCode, "generateCode");
|
|
1997
|
-
|
|
1998
2094
|
// packages/channels/base/dist/SessionRouter.js
|
|
1999
2095
|
init_esbuild_shims();
|
|
2000
2096
|
import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync3, rmSync, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
@@ -2049,6 +2145,8 @@ var SessionRouter = class {
|
|
|
2049
2145
|
switch (scope) {
|
|
2050
2146
|
case "thread":
|
|
2051
2147
|
return `${channelName}:${threadId || chatId}`;
|
|
2148
|
+
case "chat_thread":
|
|
2149
|
+
return threadId ? `${channelName}:${chatId}:${threadId}` : `${channelName}:${chatId}`;
|
|
2052
2150
|
case "single":
|
|
2053
2151
|
return `${channelName}:__single__`;
|
|
2054
2152
|
case "user":
|
|
@@ -3423,7 +3521,7 @@ var ChannelBase = class {
|
|
|
3423
3521
|
if (target.threadId !== void 0 && this.supportsProactiveSend() && this.supportsProactiveTarget(target)) {
|
|
3424
3522
|
await this.pushProactive(target, text);
|
|
3425
3523
|
} else {
|
|
3426
|
-
await this.
|
|
3524
|
+
await this.sendThreadMessage(target.chatId, target.threadId, text);
|
|
3427
3525
|
}
|
|
3428
3526
|
} catch (err) {
|
|
3429
3527
|
this.removePendingPermission(event.requestId);
|
|
@@ -3492,6 +3590,14 @@ var ChannelBase = class {
|
|
|
3492
3590
|
this.attachBridgeEvents(bridge);
|
|
3493
3591
|
}
|
|
3494
3592
|
}
|
|
3593
|
+
/**
|
|
3594
|
+
* Thread-targeted delivery. Polling adapters override this to post comments
|
|
3595
|
+
* on a specific issue/PR. The default falls through to sendMessage(chatId,
|
|
3596
|
+
* text), ignoring threadId — existing IM adapters are behaviorally unchanged.
|
|
3597
|
+
*/
|
|
3598
|
+
async sendThreadMessage(chatId, _threadId, text) {
|
|
3599
|
+
await this.sendMessage(chatId, text);
|
|
3600
|
+
}
|
|
3495
3601
|
/**
|
|
3496
3602
|
* Adapter hook for task lifecycle events — the canonical way to track task
|
|
3497
3603
|
* state (onPromptStart/onPromptEnd are retained for back-compat). The prompt
|
|
@@ -3622,7 +3728,7 @@ var ChannelBase = class {
|
|
|
3622
3728
|
if (target.threadId) {
|
|
3623
3729
|
throw new Error("Channel does not support proactive loop messages for threaded targets.");
|
|
3624
3730
|
}
|
|
3625
|
-
await this.
|
|
3731
|
+
await this.sendThreadMessage(target.chatId, target.threadId, text);
|
|
3626
3732
|
}
|
|
3627
3733
|
async pushProactiveDelivery(target, text) {
|
|
3628
3734
|
try {
|
|
@@ -3805,6 +3911,7 @@ var ChannelBase = class {
|
|
|
3805
3911
|
alreadyPrefixed: true,
|
|
3806
3912
|
referencedText: void 0,
|
|
3807
3913
|
attachments: void 0,
|
|
3914
|
+
metadata: void 0,
|
|
3808
3915
|
imageBase64: void 0,
|
|
3809
3916
|
imageMimeType: void 0
|
|
3810
3917
|
};
|
|
@@ -4272,6 +4379,7 @@ ${promptText}` : promptText;
|
|
|
4272
4379
|
this.router.removeSessionId(sessionId);
|
|
4273
4380
|
this.instructedSessions.delete(sessionId);
|
|
4274
4381
|
this.unattendedMemorySessions.delete(sessionId);
|
|
4382
|
+
this.discardRetiredSession(promptBridge, sessionId, `timed-out loop ${jobId}`);
|
|
4275
4383
|
process.stderr.write(`[${this.name}] retired timed out loop ${jobId} session ${sessionId} after cancel did not settle
|
|
4276
4384
|
`);
|
|
4277
4385
|
}
|
|
@@ -4282,6 +4390,19 @@ ${promptText}` : promptText;
|
|
|
4282
4390
|
clearTimeout(graceTimer);
|
|
4283
4391
|
}
|
|
4284
4392
|
}
|
|
4393
|
+
discardRetiredSession(promptBridge, sessionId, reason) {
|
|
4394
|
+
const safeSessionId = sanitizeLogText(sessionId, 64);
|
|
4395
|
+
const safeReason = sanitizeLogText(reason, 128);
|
|
4396
|
+
try {
|
|
4397
|
+
void promptBridge.discardSession?.(sessionId).catch((err) => {
|
|
4398
|
+
process.stderr.write(`[${this.name}] failed to discard ${safeReason} session ${safeSessionId}: ${this.lifecycleError(err)}
|
|
4399
|
+
`);
|
|
4400
|
+
});
|
|
4401
|
+
} catch (err) {
|
|
4402
|
+
process.stderr.write(`[${this.name}] failed to discard ${safeReason} session ${safeSessionId}: ${this.lifecycleError(err)}
|
|
4403
|
+
`);
|
|
4404
|
+
}
|
|
4405
|
+
}
|
|
4285
4406
|
requestActivePromptCancellation(sessionId, reason = "cancel_command") {
|
|
4286
4407
|
const active = this.activePrompts.get(sessionId);
|
|
4287
4408
|
if (!active) {
|
|
@@ -4420,8 +4541,11 @@ ${promptText}` : promptText;
|
|
|
4420
4541
|
*/
|
|
4421
4542
|
onResponseBoundary(_chatId, _sessionId) {
|
|
4422
4543
|
}
|
|
4423
|
-
async sendResponseMessage(chatId, text,
|
|
4424
|
-
|
|
4544
|
+
async sendResponseMessage(chatId, text, sessionId) {
|
|
4545
|
+
const active = this.activePrompts.get(sessionId);
|
|
4546
|
+
const target = this.router.getTarget(sessionId);
|
|
4547
|
+
const threadId = active?.threadId ?? target?.threadId;
|
|
4548
|
+
await this.sendThreadMessage(chatId, threadId, text);
|
|
4425
4549
|
}
|
|
4426
4550
|
/**
|
|
4427
4551
|
* Called when the agent's full response is ready.
|
|
@@ -4442,21 +4566,21 @@ ${promptText}` : promptText;
|
|
|
4442
4566
|
registerCancelCommand(name = "cancel") {
|
|
4443
4567
|
this.registerCommand(name, async (envelope) => {
|
|
4444
4568
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4445
|
-
await this.
|
|
4569
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can cancel requests in this shared session.");
|
|
4446
4570
|
return true;
|
|
4447
4571
|
}
|
|
4448
4572
|
const activeSessionId = this.findActiveSessionId(envelope);
|
|
4449
4573
|
if (!activeSessionId) {
|
|
4450
|
-
await this.
|
|
4574
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No request is currently running.");
|
|
4451
4575
|
return true;
|
|
4452
4576
|
}
|
|
4453
4577
|
const active = this.activePrompts.get(activeSessionId);
|
|
4454
4578
|
if (!active) {
|
|
4455
|
-
await this.
|
|
4579
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No request is currently running.");
|
|
4456
4580
|
return true;
|
|
4457
4581
|
}
|
|
4458
4582
|
const cancelSucceeded = await this.requestActivePromptCancellation(activeSessionId, "cancel_command");
|
|
4459
|
-
await this.
|
|
4583
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, cancelSucceeded ? "Cancelled current request." : "Failed to cancel current request.");
|
|
4460
4584
|
return true;
|
|
4461
4585
|
});
|
|
4462
4586
|
}
|
|
@@ -4588,7 +4712,7 @@ ${promptText}` : promptText;
|
|
|
4588
4712
|
}
|
|
4589
4713
|
async handlePermissionResponseCommand(envelope, args, decision) {
|
|
4590
4714
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4591
|
-
await this.
|
|
4715
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can answer permission requests in this shared session.");
|
|
4592
4716
|
return true;
|
|
4593
4717
|
}
|
|
4594
4718
|
const lookup = this.pendingPermissionForEnvelope(envelope, args);
|
|
@@ -4598,16 +4722,16 @@ ${promptText}` : promptText;
|
|
|
4598
4722
|
const title = pending2 ? `: ${sanitizeQuotedText(pending2.request.toolCall.title || "Tool use", 160)}` : "";
|
|
4599
4723
|
return `- ${sanitizeQuotedText(id, 128)}${title}`;
|
|
4600
4724
|
}).join("\n");
|
|
4601
|
-
await this.
|
|
4725
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Multiple permission requests are pending for this chat. Reply with /${decision} <request-id>.
|
|
4602
4726
|
${requestList}`);
|
|
4603
4727
|
return true;
|
|
4604
4728
|
}
|
|
4605
4729
|
if (lookup.kind === "none") {
|
|
4606
|
-
await this.
|
|
4730
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, lookup.explicit ? "No pending permission request with that id for this chat." : "No pending permission request for this chat.");
|
|
4607
4731
|
return true;
|
|
4608
4732
|
}
|
|
4609
4733
|
if (!this.bridge.respondToPermission) {
|
|
4610
|
-
await this.
|
|
4734
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Permission relay is not available for this session.");
|
|
4611
4735
|
return true;
|
|
4612
4736
|
}
|
|
4613
4737
|
const { pending } = lookup;
|
|
@@ -4619,7 +4743,7 @@ ${requestList}`);
|
|
|
4619
4743
|
return optionId ? { outcome: { outcome: "selected", optionId } } : void 0;
|
|
4620
4744
|
})();
|
|
4621
4745
|
if (!response) {
|
|
4622
|
-
await this.
|
|
4746
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, decision === "approve-always" ? "This permission request has no always-allow option." : "This permission request has no approvable option.");
|
|
4623
4747
|
return true;
|
|
4624
4748
|
}
|
|
4625
4749
|
let accepted;
|
|
@@ -4629,11 +4753,11 @@ ${requestList}`);
|
|
|
4629
4753
|
this.removePendingPermission(pending.requestId);
|
|
4630
4754
|
process.stderr.write(`[${this.name}] permission response failed for request ${sanitizeLogText(pending.requestId, 128)}: ${this.lifecycleError(err)}
|
|
4631
4755
|
`);
|
|
4632
|
-
await this.
|
|
4756
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Failed to answer the permission request.");
|
|
4633
4757
|
return true;
|
|
4634
4758
|
}
|
|
4635
4759
|
this.removePendingPermission(pending.requestId);
|
|
4636
|
-
await this.
|
|
4760
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, accepted ? decision === "approve" ? "Permission approved." : decision === "approve-always" ? "Permission approved always." : "Permission denied." : "Permission request is no longer pending.");
|
|
4637
4761
|
return true;
|
|
4638
4762
|
}
|
|
4639
4763
|
/** Register shared slash commands. Called from constructor. */
|
|
@@ -4683,19 +4807,20 @@ ${requestList}`);
|
|
|
4683
4807
|
} else {
|
|
4684
4808
|
this.sessionGenerations.delete(id);
|
|
4685
4809
|
}
|
|
4810
|
+
this.discardRetiredSession(this.bridge, id, "cleared");
|
|
4686
4811
|
}
|
|
4687
|
-
await this.
|
|
4812
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Session cleared. The next message starts a fresh conversation.");
|
|
4688
4813
|
} else {
|
|
4689
|
-
await this.
|
|
4814
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No active session to clear.");
|
|
4690
4815
|
}
|
|
4691
4816
|
}, "doClear");
|
|
4692
4817
|
const clearHandler = /* @__PURE__ */ __name(async (envelope, args) => {
|
|
4693
4818
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4694
|
-
await this.
|
|
4819
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can clear this shared session.");
|
|
4695
4820
|
return true;
|
|
4696
4821
|
}
|
|
4697
4822
|
if (this.isSharedSession(envelope) && args.toLowerCase() !== "confirm") {
|
|
4698
|
-
await this.
|
|
4823
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, 'This clears the shared session for everyone who shares it. Re-send with "confirm" (e.g. /clear confirm) to proceed.');
|
|
4699
4824
|
return true;
|
|
4700
4825
|
}
|
|
4701
4826
|
await doClear(envelope);
|
|
@@ -4709,12 +4834,12 @@ ${requestList}`);
|
|
|
4709
4834
|
this.registerCommand("deny", (envelope, args) => this.handlePermissionResponseCommand(envelope, args, "deny"));
|
|
4710
4835
|
this.registerCommand("who", async (envelope) => {
|
|
4711
4836
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4712
|
-
await this.
|
|
4837
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can view this shared session.");
|
|
4713
4838
|
return true;
|
|
4714
4839
|
}
|
|
4715
4840
|
const active = this.router.hasSession(this.name, envelope.senderId, envelope.chatId, envelope.threadId);
|
|
4716
4841
|
const scopeNote = this.config.sessionScope === "single" ? " (shared channel-wide)" : this.isSharedSession(envelope) ? envelope.isGroup ? " (shared by this group)" : "" : envelope.isGroup ? " (private to you)" : "";
|
|
4717
|
-
await this.
|
|
4842
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, [
|
|
4718
4843
|
`Channel: ${this.name}`,
|
|
4719
4844
|
// Identity/memory lines only for channels that opted in — keep
|
|
4720
4845
|
// unconfigured channels' output unchanged.
|
|
@@ -4768,12 +4893,12 @@ ${requestList}`);
|
|
|
4768
4893
|
}
|
|
4769
4894
|
}
|
|
4770
4895
|
lines.push("", "Send any text to chat with the agent.");
|
|
4771
|
-
await this.
|
|
4896
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, lines.join("\n"));
|
|
4772
4897
|
return true;
|
|
4773
4898
|
});
|
|
4774
4899
|
this.registerCommand("status", async (envelope) => {
|
|
4775
4900
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4776
|
-
await this.
|
|
4901
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can view this shared session.");
|
|
4777
4902
|
return true;
|
|
4778
4903
|
}
|
|
4779
4904
|
const hasSession = this.router.hasSession(this.name, envelope.senderId, envelope.chatId, envelope.threadId);
|
|
@@ -4787,18 +4912,18 @@ ${requestList}`);
|
|
|
4787
4912
|
`Memory: ${this.memoryScope.mode}`
|
|
4788
4913
|
] : []
|
|
4789
4914
|
];
|
|
4790
|
-
await this.
|
|
4915
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, lines.join("\n"));
|
|
4791
4916
|
return true;
|
|
4792
4917
|
});
|
|
4793
4918
|
this.registerCommand("loop", async (envelope, args) => this.handleLoopCommand(envelope, args));
|
|
4794
4919
|
}
|
|
4795
4920
|
async handleLoopCommand(envelope, args) {
|
|
4796
4921
|
if (!this.loopController) {
|
|
4797
|
-
await this.
|
|
4922
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Loops are not available.");
|
|
4798
4923
|
return true;
|
|
4799
4924
|
}
|
|
4800
4925
|
if (!this.isAuthorizedForSharedSession(envelope)) {
|
|
4801
|
-
await this.
|
|
4926
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Only authorized members can use loops in this shared session.");
|
|
4802
4927
|
return true;
|
|
4803
4928
|
}
|
|
4804
4929
|
const [subcommand = "", ...rest] = args.trim().split(/\s+/u);
|
|
@@ -4812,7 +4937,7 @@ ${requestList}`);
|
|
|
4812
4937
|
case "cancel":
|
|
4813
4938
|
return this.handleLoopCancel(envelope, rest[0]);
|
|
4814
4939
|
default:
|
|
4815
|
-
await this.
|
|
4940
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, 'Usage: /loop add "<cron>" <prompt> | /loop list | /loop inspect <id> | /loop cancel <id>');
|
|
4816
4941
|
return true;
|
|
4817
4942
|
}
|
|
4818
4943
|
}
|
|
@@ -4820,32 +4945,32 @@ ${requestList}`);
|
|
|
4820
4945
|
if (!this.loopController)
|
|
4821
4946
|
return true;
|
|
4822
4947
|
if (!this.supportsProactiveSend()) {
|
|
4823
|
-
await this.
|
|
4948
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "This channel does not support proactive loop messages.");
|
|
4824
4949
|
return true;
|
|
4825
4950
|
}
|
|
4826
4951
|
if (this.config.sessionScope === "single") {
|
|
4827
|
-
await this.
|
|
4952
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Loops are not supported when sessionScope is single.");
|
|
4828
4953
|
return true;
|
|
4829
4954
|
}
|
|
4830
4955
|
const parsed = parseLoopAddArgs(args);
|
|
4831
4956
|
if (!parsed) {
|
|
4832
|
-
await this.
|
|
4957
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, 'Usage: /loop add "<cron>" <prompt>');
|
|
4833
4958
|
return true;
|
|
4834
4959
|
}
|
|
4835
4960
|
try {
|
|
4836
4961
|
this.loopController.validateCron(parsed.cron);
|
|
4837
4962
|
} catch (err) {
|
|
4838
|
-
await this.
|
|
4963
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Invalid cron expression: ${err instanceof Error ? err.message : String(err)}`);
|
|
4839
4964
|
return true;
|
|
4840
4965
|
}
|
|
4841
4966
|
const target = this.loopTargetFromEnvelope(envelope);
|
|
4842
4967
|
if (!this.supportsProactiveTarget(target)) {
|
|
4843
|
-
await this.
|
|
4968
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "This channel does not support proactive loop messages for this chat target.");
|
|
4844
4969
|
return true;
|
|
4845
4970
|
}
|
|
4846
4971
|
const prompt = sanitizePromptText(parsed.prompt.trim());
|
|
4847
4972
|
if (Array.from(prompt).length > MAX_LOOP_PROMPT_CHARS) {
|
|
4848
|
-
await this.
|
|
4973
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Loop prompt is too long; keep it under ${MAX_LOOP_PROMPT_CHARS} characters.`);
|
|
4849
4974
|
return true;
|
|
4850
4975
|
}
|
|
4851
4976
|
const input = {
|
|
@@ -4868,10 +4993,10 @@ ${requestList}`);
|
|
|
4868
4993
|
}
|
|
4869
4994
|
}
|
|
4870
4995
|
if (!job) {
|
|
4871
|
-
await this.
|
|
4996
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Too many loops for this chat. Cancel an existing loop before adding another.`);
|
|
4872
4997
|
return true;
|
|
4873
4998
|
}
|
|
4874
|
-
await this.
|
|
4999
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Loop ${job.id}: ${job.cron}`);
|
|
4875
5000
|
return true;
|
|
4876
5001
|
}
|
|
4877
5002
|
async createLoopFromTool(sessionId, input) {
|
|
@@ -4973,23 +5098,23 @@ ${requestList}`);
|
|
|
4973
5098
|
return true;
|
|
4974
5099
|
const jobs = await this.loopController.listForTarget(this.name, this.loopTargetFromEnvelope(envelope));
|
|
4975
5100
|
if (jobs.length === 0) {
|
|
4976
|
-
await this.
|
|
5101
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No loops.");
|
|
4977
5102
|
return true;
|
|
4978
5103
|
}
|
|
4979
|
-
await this.
|
|
5104
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, jobs.map((job) => this.formatLoopListLine(job)).join("\n"));
|
|
4980
5105
|
return true;
|
|
4981
5106
|
}
|
|
4982
5107
|
async handleLoopInspect(envelope, id) {
|
|
4983
5108
|
if (!this.loopController)
|
|
4984
5109
|
return true;
|
|
4985
5110
|
if (!id) {
|
|
4986
|
-
await this.
|
|
5111
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Usage: /loop inspect <id>");
|
|
4987
5112
|
return true;
|
|
4988
5113
|
}
|
|
4989
5114
|
const jobs = await this.loopController.listForTarget(this.name, this.loopTargetFromEnvelope(envelope));
|
|
4990
5115
|
const job = jobs.find((candidate) => candidate.id === id);
|
|
4991
5116
|
if (!job) {
|
|
4992
|
-
await this.
|
|
5117
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `No loop ${id}.`);
|
|
4993
5118
|
return true;
|
|
4994
5119
|
}
|
|
4995
5120
|
const lines = [
|
|
@@ -5011,7 +5136,7 @@ ${requestList}`);
|
|
|
5011
5136
|
lines.push(`Last result: ${job.lastResultPreview}`);
|
|
5012
5137
|
}
|
|
5013
5138
|
lines.push(`Prompt: ${job.prompt}`);
|
|
5014
|
-
await this.
|
|
5139
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, lines.join("\n"));
|
|
5015
5140
|
return true;
|
|
5016
5141
|
}
|
|
5017
5142
|
formatLoopListLine(job) {
|
|
@@ -5043,17 +5168,17 @@ ${requestList}`);
|
|
|
5043
5168
|
if (!this.loopController)
|
|
5044
5169
|
return true;
|
|
5045
5170
|
if (!id) {
|
|
5046
|
-
await this.
|
|
5171
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Usage: /loop cancel <id>");
|
|
5047
5172
|
return true;
|
|
5048
5173
|
}
|
|
5049
5174
|
const jobs = await this.loopController.listForTarget(this.name, this.loopTargetFromEnvelope(envelope));
|
|
5050
5175
|
const match = jobs.find((job) => job.id === id);
|
|
5051
5176
|
if (!match) {
|
|
5052
|
-
await this.
|
|
5177
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `No loop ${id}.`);
|
|
5053
5178
|
return true;
|
|
5054
5179
|
}
|
|
5055
5180
|
const disabled = await this.loopController.disable(id);
|
|
5056
|
-
await this.
|
|
5181
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, disabled ? `Cancelled loop ${id}.` : `Failed to cancel loop ${id}.`);
|
|
5057
5182
|
return true;
|
|
5058
5183
|
}
|
|
5059
5184
|
loopTargetFromEnvelope(envelope) {
|
|
@@ -5170,7 +5295,7 @@ ${requestList}`);
|
|
|
5170
5295
|
}
|
|
5171
5296
|
async getChannelMemory(envelope) {
|
|
5172
5297
|
if (!this.channelMemory) {
|
|
5173
|
-
await this.
|
|
5298
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Channel memory is not configured for this channel.");
|
|
5174
5299
|
return void 0;
|
|
5175
5300
|
}
|
|
5176
5301
|
return this.channelMemory;
|
|
@@ -5188,7 +5313,7 @@ ${requestList}`);
|
|
|
5188
5313
|
}
|
|
5189
5314
|
async handleChannelMemoryIntent(envelope, intent, options = {}) {
|
|
5190
5315
|
if (intent.kind === "no_match") {
|
|
5191
|
-
await this.
|
|
5316
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No matching channel memory entry.");
|
|
5192
5317
|
return;
|
|
5193
5318
|
}
|
|
5194
5319
|
if (intent.kind === "ambiguous") {
|
|
@@ -5200,11 +5325,11 @@ ${requestList}`);
|
|
|
5200
5325
|
entries = await channelMemory2.listChannelMemoryEntries(this.channelMemoryTarget(envelope));
|
|
5201
5326
|
} catch (error) {
|
|
5202
5327
|
this.logChannelMemoryError("read", envelope, this.channelMemoryErrorMessage(error));
|
|
5203
|
-
await this.
|
|
5328
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to read channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5204
5329
|
return;
|
|
5205
5330
|
}
|
|
5206
5331
|
const selected = this.entriesForChannelMemoryIds(entries, intent.ids);
|
|
5207
|
-
await this.
|
|
5332
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, [
|
|
5208
5333
|
"Multiple channel memory entries match:",
|
|
5209
5334
|
...this.renderChannelMemoryCandidates(selected)
|
|
5210
5335
|
].join("\n"));
|
|
@@ -5219,11 +5344,11 @@ ${requestList}`);
|
|
|
5219
5344
|
entries = await channelMemory2.listChannelMemoryEntries(this.channelMemoryTarget(envelope));
|
|
5220
5345
|
} catch (error) {
|
|
5221
5346
|
this.logChannelMemoryError("read", envelope, this.channelMemoryErrorMessage(error));
|
|
5222
|
-
await this.
|
|
5347
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to read channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5223
5348
|
return;
|
|
5224
5349
|
}
|
|
5225
5350
|
const selected = this.entriesForChannelMemoryIds(entries, intent.ids);
|
|
5226
|
-
await this.
|
|
5351
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, [
|
|
5227
5352
|
"Channel memory (page 1/1):",
|
|
5228
5353
|
...this.renderChannelMemoryCandidates(selected)
|
|
5229
5354
|
].join("\n"));
|
|
@@ -5236,7 +5361,7 @@ ${requestList}`);
|
|
|
5236
5361
|
if (intent.kind === "update_confirm" || intent.kind === "remove_confirm") {
|
|
5237
5362
|
const pending = intent.kind === "update_confirm" ? this.takePendingChannelMemoryMutation(envelope, "update") : this.takePendingChannelMemoryMutation(envelope, "remove");
|
|
5238
5363
|
if (!pending) {
|
|
5239
|
-
await this.
|
|
5364
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, intent.kind === "update_confirm" ? "No pending channel memory update. Start a new update request first." : "No pending channel memory removal. Start a new removal request first.");
|
|
5240
5365
|
return;
|
|
5241
5366
|
}
|
|
5242
5367
|
const channelMemory2 = await this.getChannelMemory(envelope);
|
|
@@ -5260,15 +5385,15 @@ ${requestList}`);
|
|
|
5260
5385
|
} catch (error) {
|
|
5261
5386
|
const message = this.channelMemoryErrorMessage(error);
|
|
5262
5387
|
this.logChannelMemoryError(isUpdate ? "update" : "remove", envelope, message);
|
|
5263
|
-
await this.
|
|
5388
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, message === "Channel memory entry changed" ? "That channel memory entry changed since it was selected. View channel memory and start the operation again." : `Failed to ${isUpdate ? "update" : "remove"} channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5264
5389
|
return;
|
|
5265
5390
|
}
|
|
5266
5391
|
if (!changed) {
|
|
5267
|
-
await this.
|
|
5392
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `No channel memory entry ${pending.id}.`);
|
|
5268
5393
|
return;
|
|
5269
5394
|
}
|
|
5270
5395
|
this.invalidateUnattendedMemory(envelope);
|
|
5271
|
-
await this.
|
|
5396
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Channel memory ${pending.id} ${isUpdate ? "updated" : "removed"}.`);
|
|
5272
5397
|
return;
|
|
5273
5398
|
}
|
|
5274
5399
|
if (intent.kind === "natural_update") {
|
|
@@ -5308,7 +5433,7 @@ ${requestList}`);
|
|
|
5308
5433
|
} catch (error) {
|
|
5309
5434
|
const message = this.channelMemoryErrorMessage(error);
|
|
5310
5435
|
this.logChannelMemoryError("save", envelope, message);
|
|
5311
|
-
await this.
|
|
5436
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to save channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5312
5437
|
return;
|
|
5313
5438
|
}
|
|
5314
5439
|
if (result.changed) {
|
|
@@ -5319,11 +5444,11 @@ ${requestList}`);
|
|
|
5319
5444
|
}
|
|
5320
5445
|
if (result.added.length > 0) {
|
|
5321
5446
|
const ids = result.added.map((entry) => entry.id);
|
|
5322
|
-
await this.
|
|
5447
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, result.duplicateIds.length > 0 ? `Channel memory saved: ${ids.join(", ")}. Skipped duplicates: ${result.duplicateIds.join(", ")}.` : ids.length === 1 ? `Channel memory ${ids[0]} saved.` : `Channel memory saved: ${ids.join(", ")}.`);
|
|
5323
5448
|
} else if (result.duplicateIds.length > 0) {
|
|
5324
|
-
await this.
|
|
5449
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Channel memory already contains ${result.duplicateIds.join(", ")}.`);
|
|
5325
5450
|
} else {
|
|
5326
|
-
await this.
|
|
5451
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Channel memory updated.");
|
|
5327
5452
|
}
|
|
5328
5453
|
return;
|
|
5329
5454
|
}
|
|
@@ -5334,27 +5459,27 @@ ${requestList}`);
|
|
|
5334
5459
|
} catch (error) {
|
|
5335
5460
|
const message = this.channelMemoryErrorMessage(error);
|
|
5336
5461
|
this.logChannelMemoryError("read", envelope, message);
|
|
5337
|
-
await this.
|
|
5462
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to read channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5338
5463
|
return;
|
|
5339
5464
|
}
|
|
5340
5465
|
if (intent.kind === "inspect") {
|
|
5341
5466
|
const entry = entries.find((candidate) => candidate.id === intent.id);
|
|
5342
|
-
await this.
|
|
5467
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, entry ? `Channel memory ${entry.id}:
|
|
5343
5468
|
${sanitizePromptText(entry.text).trim()}` : `No channel memory entry ${intent.id}.`);
|
|
5344
5469
|
return;
|
|
5345
5470
|
}
|
|
5346
5471
|
const totalPages = Math.max(1, Math.ceil(entries.length / CHANNEL_MEMORY_PAGE_SIZE));
|
|
5347
5472
|
if (intent.page > totalPages) {
|
|
5348
|
-
await this.
|
|
5473
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Channel memory page ${intent.page} does not exist.`);
|
|
5349
5474
|
return;
|
|
5350
5475
|
}
|
|
5351
5476
|
if (entries.length === 0) {
|
|
5352
|
-
await this.
|
|
5477
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "No channel memory saved.");
|
|
5353
5478
|
return;
|
|
5354
5479
|
}
|
|
5355
5480
|
const pageStart = (intent.page - 1) * CHANNEL_MEMORY_PAGE_SIZE;
|
|
5356
5481
|
const lines = entries.slice(pageStart, pageStart + CHANNEL_MEMORY_PAGE_SIZE).map((entry) => this.renderChannelMemoryCandidate(entry));
|
|
5357
|
-
await this.
|
|
5482
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, [`Channel memory (page ${intent.page}/${totalPages}):`, ...lines].join("\n"));
|
|
5358
5483
|
return;
|
|
5359
5484
|
}
|
|
5360
5485
|
if (intent.kind === "update" || intent.kind === "remove") {
|
|
@@ -5370,21 +5495,21 @@ ${sanitizePromptText(entry.text).trim()}` : `No channel memory entry ${intent.id
|
|
|
5370
5495
|
} catch (error) {
|
|
5371
5496
|
const message = this.channelMemoryErrorMessage(error);
|
|
5372
5497
|
this.logChannelMemoryError(isUpdate ? "update" : "remove", envelope, message);
|
|
5373
|
-
await this.
|
|
5498
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to ${isUpdate ? "update" : "remove"} channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5374
5499
|
return;
|
|
5375
5500
|
}
|
|
5376
5501
|
if (!changed) {
|
|
5377
|
-
await this.
|
|
5502
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `No channel memory entry ${id}.`);
|
|
5378
5503
|
return;
|
|
5379
5504
|
}
|
|
5380
5505
|
this.invalidateUnattendedMemory(envelope);
|
|
5381
|
-
await this.
|
|
5506
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Channel memory ${id} ${isUpdate ? "updated" : "removed"}.`);
|
|
5382
5507
|
return;
|
|
5383
5508
|
}
|
|
5384
5509
|
if (intent.kind === "clear_confirm") {
|
|
5385
5510
|
const pending = this.takePendingChannelMemoryMutation(envelope, "clear");
|
|
5386
5511
|
if (!pending) {
|
|
5387
|
-
await this.
|
|
5512
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, 'No pending clear request. Say "\u6E05\u7A7A\u8BB0\u5FC6" first.');
|
|
5388
5513
|
return;
|
|
5389
5514
|
}
|
|
5390
5515
|
let result;
|
|
@@ -5393,13 +5518,13 @@ ${sanitizePromptText(entry.text).trim()}` : `No channel memory entry ${intent.id
|
|
|
5393
5518
|
} catch (error) {
|
|
5394
5519
|
const message = this.channelMemoryErrorMessage(error);
|
|
5395
5520
|
this.logChannelMemoryError("clear", envelope, message);
|
|
5396
|
-
await this.
|
|
5521
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Failed to clear channel memory: ${this.channelMemoryUserErrorMessage()}`);
|
|
5397
5522
|
return;
|
|
5398
5523
|
}
|
|
5399
5524
|
if (result.changed) {
|
|
5400
5525
|
this.invalidateUnattendedMemory(envelope);
|
|
5401
5526
|
}
|
|
5402
|
-
await this.
|
|
5527
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, result.changed ? "Channel memory cleared." : "No channel memory saved.");
|
|
5403
5528
|
return;
|
|
5404
5529
|
}
|
|
5405
5530
|
const unhandled = intent;
|
|
@@ -5428,7 +5553,7 @@ ${sanitizePromptText(entry.text).trim()}` : `No channel memory entry ${intent.id
|
|
|
5428
5553
|
const key = this.channelMemoryPendingKey(envelope);
|
|
5429
5554
|
this.pendingChannelMemoryMutationDeliveries.set(key, mutation);
|
|
5430
5555
|
try {
|
|
5431
|
-
await this.
|
|
5556
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, message);
|
|
5432
5557
|
} catch (error) {
|
|
5433
5558
|
if (this.pendingChannelMemoryMutationDeliveries.get(key) === mutation) {
|
|
5434
5559
|
this.pendingChannelMemoryMutationDeliveries.delete(key);
|
|
@@ -5582,15 +5707,17 @@ ${sanitizePromptText(entry.text).trim()}` : `No channel memory entry ${intent.id
|
|
|
5582
5707
|
* Whether the resolved session is SHARED across senders. `single` collapses
|
|
5583
5708
|
* the whole channel to one `__single__` session for EVERY sender — group OR
|
|
5584
5709
|
* DM — so it is ALWAYS shared (even a DM maps to `__single__`). `thread` is
|
|
5585
|
-
* shared only in a group (a DM maps to the lone caller's own chat).
|
|
5586
|
-
*
|
|
5587
|
-
*
|
|
5710
|
+
* shared only in a group (a DM maps to the lone caller's own chat).
|
|
5711
|
+
* `chat_thread` is always shared: it scopes by chat+thread, and a thread
|
|
5712
|
+
* (issue/PR discussion) can carry multiple participants even outside a
|
|
5713
|
+
* group. `user` is per-sender, never shared. Drives both the
|
|
5714
|
+
* destructive-/clear confirm gate and the host-shell (`!`) gate.
|
|
5588
5715
|
*/
|
|
5589
5716
|
isSharedSession(envelope) {
|
|
5590
5717
|
return this.isSharedSessionTarget(envelope);
|
|
5591
5718
|
}
|
|
5592
5719
|
isSharedSessionTarget(target) {
|
|
5593
|
-
return this.config.sessionScope === "single" || target.isGroup === true && this.config.sessionScope === "thread";
|
|
5720
|
+
return this.config.sessionScope === "single" || this.config.sessionScope === "chat_thread" || target.isGroup === true && this.config.sessionScope === "thread";
|
|
5594
5721
|
}
|
|
5595
5722
|
/**
|
|
5596
5723
|
* Whether `envelope.senderId` may act on the resolved session's destructive or
|
|
@@ -5847,7 +5974,7 @@ ${promptText}`;
|
|
|
5847
5974
|
if (!result.allowed) {
|
|
5848
5975
|
if (result.pairingCode !== void 0) {
|
|
5849
5976
|
this.logPreflightRejected("sender_pairing_required");
|
|
5850
|
-
return this.onPairingRequired(envelope.chatId, result.pairingCode).then(() => false).catch((err) => {
|
|
5977
|
+
return this.onPairingRequired(envelope.chatId, result.pairingCode, envelope.threadId).then(() => false).catch((err) => {
|
|
5851
5978
|
process.stderr.write(`[Channel:${this.name}] pairing notification failed: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
5852
5979
|
`);
|
|
5853
5980
|
return false;
|
|
@@ -5960,11 +6087,11 @@ ${promptText}`;
|
|
|
5960
6087
|
`);
|
|
5961
6088
|
}
|
|
5962
6089
|
if (envelope.isGroup) {
|
|
5963
|
-
await this.
|
|
6090
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Shell commands (`!`) are disabled in group chats.");
|
|
5964
6091
|
return;
|
|
5965
6092
|
}
|
|
5966
6093
|
if (this.isSharedSession(envelope)) {
|
|
5967
|
-
await this.
|
|
6094
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, "Shell commands (`!`) are disabled in shared sessions.");
|
|
5968
6095
|
return;
|
|
5969
6096
|
}
|
|
5970
6097
|
}
|
|
@@ -5982,10 +6109,10 @@ ${result.output}
|
|
|
5982
6109
|
${fence}` : "(no output)";
|
|
5983
6110
|
const exitLine = result.exitCode !== null && result.exitCode !== 0 ? `
|
|
5984
6111
|
Exit code: ${result.exitCode}` : "";
|
|
5985
|
-
await this.
|
|
6112
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `$ ${cmd}
|
|
5986
6113
|
${output}${exitLine}`);
|
|
5987
6114
|
} catch (error) {
|
|
5988
|
-
await this.
|
|
6115
|
+
await this.sendThreadMessage(envelope.chatId, envelope.threadId, `Shell command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
5989
6116
|
}
|
|
5990
6117
|
return;
|
|
5991
6118
|
}
|
|
@@ -6021,6 +6148,9 @@ ${promptText}`;
|
|
|
6021
6148
|
promptText = promptText + "\n\n" + filePaths.join("\n");
|
|
6022
6149
|
}
|
|
6023
6150
|
}
|
|
6151
|
+
if (envelope.metadata) {
|
|
6152
|
+
promptText = promptText + "\n\n" + sanitizePromptText(envelope.metadata);
|
|
6153
|
+
}
|
|
6024
6154
|
const groupCfg = envelope.isGroup ? this.config.groups[envelope.chatId] || this.config.groups["*"] : void 0;
|
|
6025
6155
|
const mode = groupCfg?.dispatchMode || this.config.dispatchMode || "steer";
|
|
6026
6156
|
const active = this.activePrompts.get(sessionId);
|
|
@@ -6298,6 +6428,7 @@ ${promptToSend}`;
|
|
|
6298
6428
|
// Clear attachments/references — already resolved in original text
|
|
6299
6429
|
referencedText: void 0,
|
|
6300
6430
|
attachments: void 0,
|
|
6431
|
+
metadata: void 0,
|
|
6301
6432
|
imageBase64: void 0,
|
|
6302
6433
|
imageMimeType: void 0
|
|
6303
6434
|
};
|
|
@@ -6313,14 +6444,14 @@ ${promptToSend}`;
|
|
|
6313
6444
|
}));
|
|
6314
6445
|
await current;
|
|
6315
6446
|
}
|
|
6316
|
-
async onPairingRequired(chatId, code) {
|
|
6447
|
+
async onPairingRequired(chatId, code, threadId) {
|
|
6317
6448
|
if (code) {
|
|
6318
|
-
await this.
|
|
6449
|
+
await this.sendThreadMessage(chatId, threadId, `Your pairing code is: ${code}
|
|
6319
6450
|
|
|
6320
6451
|
Ask the bot operator to approve you with:
|
|
6321
6452
|
qwen channel pairing approve ${this.name} ${code}`);
|
|
6322
6453
|
} else {
|
|
6323
|
-
await this.
|
|
6454
|
+
await this.sendThreadMessage(chatId, threadId, "Too many pending pairing requests. Please try again later.");
|
|
6324
6455
|
}
|
|
6325
6456
|
}
|
|
6326
6457
|
};
|
|
@@ -6533,9 +6664,114 @@ function isTerminalTaskLifecycleType(type) {
|
|
|
6533
6664
|
}
|
|
6534
6665
|
__name(isTerminalTaskLifecycleType, "isTerminalTaskLifecycleType");
|
|
6535
6666
|
|
|
6667
|
+
// packages/channels/base/dist/PollingChannelBase.js
|
|
6668
|
+
init_esbuild_shims();
|
|
6669
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
6670
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync4, renameSync as renameSync4, writeFileSync as writeFileSync4 } from "node:fs";
|
|
6671
|
+
import { join as join6 } from "node:path";
|
|
6672
|
+
import process3 from "node:process";
|
|
6673
|
+
var INITIAL_BACKOFF = 2e3;
|
|
6674
|
+
var MAX_BACKOFF = 3e4;
|
|
6675
|
+
var PollingChannelBase = class extends ChannelBase {
|
|
6676
|
+
static {
|
|
6677
|
+
__name(this, "PollingChannelBase");
|
|
6678
|
+
}
|
|
6679
|
+
cursor;
|
|
6680
|
+
abortController = new AbortController();
|
|
6681
|
+
running = false;
|
|
6682
|
+
consecutiveErrors = 0;
|
|
6683
|
+
abortableSleep(ms) {
|
|
6684
|
+
const signal = this.abortController.signal;
|
|
6685
|
+
return new Promise((resolve3) => {
|
|
6686
|
+
if (signal.aborted) {
|
|
6687
|
+
resolve3();
|
|
6688
|
+
return;
|
|
6689
|
+
}
|
|
6690
|
+
const timer = setTimeout(() => {
|
|
6691
|
+
signal.removeEventListener("abort", onAbort);
|
|
6692
|
+
resolve3();
|
|
6693
|
+
}, ms);
|
|
6694
|
+
const onAbort = /* @__PURE__ */ __name(() => {
|
|
6695
|
+
clearTimeout(timer);
|
|
6696
|
+
resolve3();
|
|
6697
|
+
}, "onAbort");
|
|
6698
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
6699
|
+
});
|
|
6700
|
+
}
|
|
6701
|
+
constructor(name, config, bridge, options) {
|
|
6702
|
+
super(name, config, bridge, options);
|
|
6703
|
+
this.cursor = this.loadCursorFromDisk() ?? this.createInitialCursor();
|
|
6704
|
+
}
|
|
6705
|
+
validateCursor(parsed) {
|
|
6706
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
6707
|
+
return null;
|
|
6708
|
+
return parsed;
|
|
6709
|
+
}
|
|
6710
|
+
get pollInterval() {
|
|
6711
|
+
const configured = this.config.pollInterval;
|
|
6712
|
+
if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) {
|
|
6713
|
+
return configured;
|
|
6714
|
+
}
|
|
6715
|
+
return 6e4;
|
|
6716
|
+
}
|
|
6717
|
+
saveCursor() {
|
|
6718
|
+
const path4 = this.cursorPath();
|
|
6719
|
+
mkdirSync4(join6(getGlobalQwenDir(), "channels"), { recursive: true });
|
|
6720
|
+
const tmp = `${path4}.tmp`;
|
|
6721
|
+
writeFileSync4(tmp, JSON.stringify(this.cursor) + "\n", "utf-8");
|
|
6722
|
+
renameSync4(tmp, path4);
|
|
6723
|
+
}
|
|
6724
|
+
startPollLoop() {
|
|
6725
|
+
if (this.running)
|
|
6726
|
+
return;
|
|
6727
|
+
this.running = true;
|
|
6728
|
+
this.consecutiveErrors = 0;
|
|
6729
|
+
this.abortController = new AbortController();
|
|
6730
|
+
this.runLoop();
|
|
6731
|
+
}
|
|
6732
|
+
stopPollLoop() {
|
|
6733
|
+
this.running = false;
|
|
6734
|
+
this.abortController.abort();
|
|
6735
|
+
}
|
|
6736
|
+
async runLoop() {
|
|
6737
|
+
const signal = this.abortController.signal;
|
|
6738
|
+
while (this.running && !signal.aborted) {
|
|
6739
|
+
try {
|
|
6740
|
+
await this.pollOnce();
|
|
6741
|
+
this.saveCursor();
|
|
6742
|
+
this.consecutiveErrors = 0;
|
|
6743
|
+
} catch (err) {
|
|
6744
|
+
this.consecutiveErrors++;
|
|
6745
|
+
const backoff = Math.min(INITIAL_BACKOFF * 2 ** (this.consecutiveErrors - 1), MAX_BACKOFF);
|
|
6746
|
+
process3.stderr.write(`[Channel:${this.name}] poll error (attempt ${this.consecutiveErrors}), backing off ${backoff}ms: ${err}
|
|
6747
|
+
`);
|
|
6748
|
+
await this.abortableSleep(backoff);
|
|
6749
|
+
continue;
|
|
6750
|
+
}
|
|
6751
|
+
await this.abortableSleep(this.pollInterval);
|
|
6752
|
+
}
|
|
6753
|
+
}
|
|
6754
|
+
loadCursorFromDisk() {
|
|
6755
|
+
try {
|
|
6756
|
+
const raw = readFileSync4(this.cursorPath(), "utf-8").trim();
|
|
6757
|
+
if (!raw)
|
|
6758
|
+
return null;
|
|
6759
|
+
return this.validateCursor(JSON.parse(raw));
|
|
6760
|
+
} catch {
|
|
6761
|
+
return null;
|
|
6762
|
+
}
|
|
6763
|
+
}
|
|
6764
|
+
cursorPath() {
|
|
6765
|
+
const encoded = this.name.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 200);
|
|
6766
|
+
const hash = createHash2("sha256").update(this.name).digest("hex").slice(0, 16);
|
|
6767
|
+
return join6(getGlobalQwenDir(), "channels", `${encoded}-${hash}-poll-cursor.json`);
|
|
6768
|
+
}
|
|
6769
|
+
};
|
|
6770
|
+
|
|
6536
6771
|
export {
|
|
6537
6772
|
resolvePath,
|
|
6538
6773
|
getGlobalQwenDir,
|
|
6774
|
+
CHANNEL_LOOP_MCP_SERVER_NAME,
|
|
6539
6775
|
sanitizeSenderName,
|
|
6540
6776
|
sanitizePromptText,
|
|
6541
6777
|
sanitizeLogText,
|
|
@@ -6548,7 +6784,8 @@ export {
|
|
|
6548
6784
|
ChannelLoopScheduler,
|
|
6549
6785
|
ChannelBase,
|
|
6550
6786
|
ChannelLoopStore,
|
|
6551
|
-
isTerminalTaskLifecycleType
|
|
6787
|
+
isTerminalTaskLifecycleType,
|
|
6788
|
+
PollingChannelBase
|
|
6552
6789
|
};
|
|
6553
6790
|
/**
|
|
6554
6791
|
* @license
|