@qwen-code/qwen-code 0.21.2 → 0.21.3-nightly.20260803.e1e5b42ce
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/settings.md +53 -38
- package/bundled/qc-helper/docs/features/channels/github.md +16 -5
- package/bundled/qc-helper/docs/features/channels/gitlab.md +6 -0
- package/bundled/qc-helper/docs/features/code-review.md +92 -24
- package/bundled/qc-helper/docs/features/commands.md +46 -38
- package/bundled/qc-helper/docs/features/hooks.md +115 -18
- package/bundled/qc-helper/docs/features/memory.md +27 -0
- package/bundled/qc-helper/docs/features/skills.md +46 -1
- package/bundled/qc-helper/docs/features/sub-agents.md +42 -9
- package/bundled/qc-helper/docs/features/tool-use-summaries.md +7 -7
- package/bundled/qc-helper/docs/qwen-serve.md +46 -25
- package/bundled/qc-helper/docs/reference/keyboard-shortcuts.md +62 -31
- package/bundled/qc-helper/docs/support/troubleshooting.md +6 -1
- package/bundled/review/DESIGN.md +167 -32
- package/bundled/review/SKILL.md +207 -38
- package/chunks/{MaxSizedBox-TQBQ247P.js → MaxSizedBox-FCEK5P5K.js} +41 -38
- package/chunks/{StandaloneSessionPicker-2HPTKCLX.js → StandaloneSessionPicker-AT77J3PM.js} +63 -59
- package/chunks/{acp-startup-profiler-2C4A5ZTJ.js → acp-startup-profiler-3RICG2YW.js} +2 -2
- package/chunks/{acpAgent-PS6EDGH3.js → acpAgent-PBMKZ5KH.js} +664 -560
- package/chunks/{agent-VDOUB35F.js → agent-55W5BPK3.js} +37 -34
- package/chunks/{agent-headless-EO53EFS2.js → agent-headless-I7VMHI22.js} +37 -34
- package/chunks/{anthropicContentGenerator-OFHSZJBF.js → anthropicContentGenerator-3CAHEZBM.js} +341 -29
- package/chunks/{artifact-tool-RDN2W7ND.js → artifact-tool-TBOYEKTY.js} +2 -2
- package/chunks/{askUserQuestion-OZERWH5R.js → askUserQuestion-23Y5WZFJ.js} +2 -2
- package/chunks/{bridge-W7AZSRZQ.js → bridge-XNAWEDAN.js} +43 -40
- package/chunks/{ca-6W3SK7OQ.js → ca-NYKNH222.js} +50 -5
- package/chunks/{channel-management-service-5S7YCWX5.js → channel-management-service-UHX56NBO.js} +7 -7
- package/chunks/{channel-settings-store-JFVRSNER.js → channel-settings-store-7P6RJSSF.js} +44 -41
- package/chunks/{channel-worker-group-OVWGYMZS.js → channel-worker-group-NDG4WOOZ.js} +8 -8
- package/chunks/{channel-worker-manager-H55GKOQA.js → channel-worker-manager-ZCW6UW34.js} +8 -8
- package/chunks/{channel-worker-supervisor-CABBXYHK.js → channel-worker-supervisor-ATGFTZRN.js} +4 -4
- package/chunks/{chunk-6MPDY6ZG.js → chunk-24ER7UV4.js} +1 -1
- package/chunks/{chunk-QDK4F2N5.js → chunk-2DNKEBXY.js} +1 -1
- package/chunks/{chunk-AUOULH6Q.js → chunk-2GF3IDEK.js} +1610 -2196
- package/chunks/{chunk-JYBU6YUE.js → chunk-2M5N3DHY.js} +1 -1
- package/chunks/{chunk-LHKCY7DY.js → chunk-2UISUFHQ.js} +3 -3
- package/chunks/{chunk-BBIQAX4V.js → chunk-2ZCYE3F2.js} +30 -18
- package/chunks/{chunk-GJ2GBPBD.js → chunk-332FMXSD.js} +5 -5
- package/chunks/{chunk-JXVC2PL3.js → chunk-33FNCQSY.js} +2 -2
- package/chunks/{chunk-P755N4CS.js → chunk-3GALLNII.js} +6 -6
- package/chunks/{chunk-YANIWTRZ.js → chunk-3ICGQSVO.js} +1 -1
- package/chunks/{chunk-NBD76HUW.js → chunk-3LGZEYOF.js} +2 -2
- package/chunks/{chunk-E2BHWIDT.js → chunk-3RXUYQJI.js} +6 -2
- package/chunks/{chunk-E5Z2AVNV.js → chunk-3SH53ANB.js} +0 -11
- package/chunks/{chunk-N4ACHWNH.js → chunk-432XCUHF.js} +1 -1
- package/chunks/{chunk-JLZ3RBQG.js → chunk-44EJDGMS.js} +144 -11
- package/chunks/{chunk-KR32NIAN.js → chunk-4JP34TZ6.js} +10 -10
- package/chunks/{chunk-L2E5GFAG.js → chunk-4LKVQFHM.js} +2 -2
- package/chunks/{chunk-YDLJGZHL.js → chunk-4NFY2S7N.js} +0 -33
- package/chunks/{chunk-NHFEMWAZ.js → chunk-5WY5QEM6.js} +1 -1
- package/chunks/{chunk-56Z7QEAQ.js → chunk-6BUPGI3J.js} +16 -16
- package/chunks/{chunk-H6I4PGRV.js → chunk-6DNHLK7F.js} +4 -4
- package/chunks/{chunk-XQK4XXTN.js → chunk-6O5DVH27.js} +1 -1
- package/chunks/{chunk-2RFKHEXL.js → chunk-6PLDPT2C.js} +1 -1
- package/chunks/{chunk-Q5WZTTWE.js → chunk-7UPJXZLD.js} +6 -8
- package/chunks/{chunk-CBBP4BMC.js → chunk-7UXI6P72.js} +82 -207
- package/chunks/{chunk-6CQWRWUC.js → chunk-7XLPYF6B.js} +3 -3
- package/chunks/{chunk-VEMNQMHA.js → chunk-7ZH55K26.js} +5 -13
- package/chunks/{chunk-JJPKFJBT.js → chunk-A2FOI762.js} +3 -3
- package/chunks/{chunk-LYI2PZDK.js → chunk-A5LNZGJB.js} +2 -2
- package/chunks/{chunk-3APUUXRF.js → chunk-A5YZ3FA2.js} +2 -1
- package/chunks/{chunk-SHN4KHDK.js → chunk-A6SX5TAH.js} +3 -3
- package/chunks/{chunk-QCXGC7QB.js → chunk-A7PONO5G.js} +3 -3
- package/chunks/{chunk-SZ3KHTDR.js → chunk-AKA24BGO.js} +1 -1
- package/chunks/{chunk-RSVPYAGK.js → chunk-B4HXOGF5.js} +5 -5
- package/chunks/{chunk-D6MDRSZ6.js → chunk-BBXSRVSN.js} +22 -11
- package/chunks/{chunk-Q3T5KA2V.js → chunk-BFHXDAR7.js} +1 -1
- package/chunks/{chunk-L55JWS76.js → chunk-BGXZBI5B.js} +1 -1
- package/chunks/{chunk-2KKCCLPT.js → chunk-C4IUDGPI.js} +1 -1
- package/chunks/{chunk-MM7TH7ZM.js → chunk-CFDR3GNL.js} +18 -3
- package/chunks/{chunk-3F2WDAV6.js → chunk-CFVFQWFB.js} +14 -14
- package/chunks/{chunk-E2FN6SM7.js → chunk-CIUUYB23.js} +5 -5
- package/chunks/{chunk-JCJ7LKNA.js → chunk-DIEFUBV6.js} +1644 -1570
- package/chunks/{chunk-KWHKHSIS.js → chunk-DTAPI453.js} +8 -8
- package/chunks/{chunk-WWCMSZII.js → chunk-DV2GAGR7.js} +71 -7
- package/chunks/{chunk-675H6PLP.js → chunk-DYA25Y7U.js} +1 -1
- package/chunks/{chunk-3I6DUGQD.js → chunk-E4WHKETF.js} +32 -4
- package/chunks/{chunk-QTERJVPZ.js → chunk-EKTCKZV5.js} +1 -0
- package/chunks/{chunk-HX6RLYUO.js → chunk-ENOHFX2M.js} +4 -4
- package/chunks/{chunk-VMX5RZQH.js → chunk-EZZJHMFK.js} +18 -9
- package/chunks/{chunk-KXDONCPU.js → chunk-FBDRTW3I.js} +4 -4
- package/chunks/{chunk-FCYYAB4S.js → chunk-FHPKHXHT.js} +3 -3
- package/chunks/{chunk-DQ2O5QOJ.js → chunk-FJZS2MXB.js} +1 -1
- package/chunks/{chunk-EQNUDTL6.js → chunk-FVLPZSKH.js} +3 -3
- package/chunks/{chunk-2LEOZTBT.js → chunk-FYMMZV5F.js} +111 -26
- package/chunks/{chunk-UV6KF7T3.js → chunk-GNZ7MX73.js} +3 -3
- package/chunks/chunk-GOFAQQZA.js +132 -0
- package/chunks/{chunk-YUFIEIWC.js → chunk-GTM6IHBB.js} +2 -2
- package/chunks/{chunk-W3UKBMSI.js → chunk-GU5B6IF3.js} +118 -9
- package/chunks/{chunk-PCK4B6LR.js → chunk-GU5XWZU2.js} +1 -1
- package/chunks/{chunk-DEEABGH2.js → chunk-H2EDCJIM.js} +5954 -1766
- package/chunks/{chunk-FJ5WUMUQ.js → chunk-H36SETQS.js} +1 -1
- package/chunks/{chunk-6FMJLI5M.js → chunk-HFVW54NL.js} +41 -6
- package/chunks/chunk-HGCQ5SE7.js +136 -0
- package/chunks/{chunk-OFZKFPYG.js → chunk-HR4CHEQS.js} +3 -3
- package/chunks/{chunk-CO2U743O.js → chunk-I3GX6LGS.js} +4 -4
- package/chunks/{chunk-5NNHICSA.js → chunk-I7JDGNG6.js} +3 -3
- package/chunks/{chunk-RDJOB6S3.js → chunk-IEBT6DXF.js} +1 -1
- package/chunks/{chunk-EU5TBFJI.js → chunk-IV7QPMC2.js} +2 -2
- package/chunks/{chunk-B4AJNNOL.js → chunk-J26HHFI5.js} +1 -1
- package/chunks/{chunk-CNTR4GR6.js → chunk-JELIWHXD.js} +1 -1
- package/chunks/{chunk-FNDXMN7I.js → chunk-JQFMW7BD.js} +936 -223
- package/chunks/{chunk-IGTHU3T4.js → chunk-KKN2IE7Q.js} +1 -1
- package/chunks/{chunk-TZTAV5RH.js → chunk-KVUBYJDM.js} +2 -2
- package/chunks/{chunk-DUNI4EBW.js → chunk-KZXSAQYV.js} +86 -52
- package/chunks/chunk-LBOVL47Y.js +29 -0
- package/chunks/{chunk-FS674JW4.js → chunk-LBWNSLJK.js} +3 -3
- package/chunks/{chunk-I5BT7ADR.js → chunk-LEZFUYPM.js} +4 -4
- package/chunks/chunk-LLMGP5IC.js +222 -0
- package/chunks/{chunk-44F4LBWZ.js → chunk-LVW7BHTW.js} +56 -18
- package/chunks/{chunk-YGE3IXJP.js → chunk-M744OFVE.js} +1 -1
- package/chunks/chunk-MISUEWB4.js +8749 -0
- package/chunks/{chunk-7SJN2IWT.js → chunk-MJ2SKNTY.js} +5 -5
- package/chunks/{chunk-JE2CEOBO.js → chunk-MNTXIO6T.js} +4 -4
- package/chunks/{chunk-TEGJSJDF.js → chunk-MOHAWIAW.js} +2 -2
- package/chunks/{chunk-54YCNSK5.js → chunk-MVMBE5EH.js} +4521 -10220
- package/chunks/{chunk-PZEXDV3H.js → chunk-NCY2CDDX.js} +71 -43
- package/chunks/{chunk-TTJZAIFP.js → chunk-NJELCSFL.js} +3 -3
- package/chunks/{chunk-A7Y5H4TX.js → chunk-NXDJEZCI.js} +7 -7
- package/chunks/{chunk-PQNHRFJC.js → chunk-NYX53SV4.js} +0 -2
- package/chunks/{chunk-QARJNL2V.js → chunk-O2ZYHG33.js} +5 -4
- package/chunks/{chunk-6PQPKTXP.js → chunk-OPMLL3B3.js} +1 -1
- package/chunks/{chunk-PVNQRENX.js → chunk-OUQGNGIU.js} +1 -1
- package/chunks/{chunk-V7RNNPGC.js → chunk-P5Y23G2L.js} +18 -1
- package/chunks/{chunk-GURGAJTX.js → chunk-PDDYAXL2.js} +4 -1
- package/chunks/chunk-PWCQRLM5.js +1170 -0
- package/chunks/{chunk-GL4JOZXU.js → chunk-Q43MIWDH.js} +4 -4
- package/chunks/{chunk-V4XNUDPE.js → chunk-QFIYH5KR.js} +28 -7
- package/chunks/chunk-QL4TN4HS.js +59 -0
- package/chunks/{chunk-E6CJ2SMM.js → chunk-QMBEW7EW.js} +2 -2
- package/chunks/{chunk-U4VTUMMK.js → chunk-QONSRAEV.js} +1 -1
- package/chunks/{chunk-LOY7RWQG.js → chunk-QYPT3QUD.js} +3 -3
- package/chunks/{chunk-RG64CDT2.js → chunk-RJAVNGJJ.js} +131 -48
- package/chunks/{chunk-Z3S5EMOW.js → chunk-RPYYTL7E.js} +60 -12
- package/chunks/{chunk-V25K5ID7.js → chunk-SWCEYR6T.js} +1 -1
- package/chunks/{chunk-77V3VIKL.js → chunk-SXGNNAMC.js} +9 -9
- package/chunks/{chunk-7KAXXBER.js → chunk-TNQ5BEEB.js} +3 -3
- package/chunks/{chunk-R2XWGR75.js → chunk-TYERNYH4.js} +2 -2
- package/chunks/{chunk-45IOTAUS.js → chunk-U25CMJYY.js} +1 -1
- package/chunks/{chunk-7ULQIS27.js → chunk-UEJESCS7.js} +1 -1
- package/chunks/{chunk-HC45LTEN.js → chunk-UH7Z7Y45.js} +1 -1
- package/chunks/{chunk-P5VC5USY.js → chunk-UIKCPMID.js} +1 -1
- package/chunks/{chunk-CPZAH673.js → chunk-UKZEXS6K.js} +2 -0
- package/chunks/{chunk-HIVKI6O6.js → chunk-UO7AWUZJ.js} +9 -7
- package/chunks/{chunk-XP4L6KS3.js → chunk-URN76TKR.js} +2 -2
- package/chunks/{chunk-XUGZYLDH.js → chunk-UWSXFI6E.js} +1 -1
- package/chunks/{chunk-AOHY3QJ3.js → chunk-VA5NLVPT.js} +3 -3
- package/chunks/{chunk-FANRZEAJ.js → chunk-VWOVHOTT.js} +1 -1
- package/chunks/{chunk-NTDH4IML.js → chunk-W2K4OEW4.js} +7 -7
- package/chunks/{chunk-L32VV3ZJ.js → chunk-WH7W24EN.js} +12 -12
- package/chunks/{chunk-QTHQ6Z5X.js → chunk-WK4TJUEA.js} +1 -1
- package/chunks/{chunk-ZPZ7ZJEE.js → chunk-WUC6ZFXO.js} +1 -1
- package/chunks/{chunk-TIRRPCFS.js → chunk-X6QNZOTC.js} +1 -1
- package/chunks/{chunk-IIUGIWWY.js → chunk-XC2VAFVZ.js} +1 -1
- package/chunks/{chunk-D4HTUMGX.js → chunk-XC656O42.js} +3 -3
- package/chunks/{chunk-ZMOJ7ISP.js → chunk-XXOVLDZQ.js} +1 -1
- package/chunks/{chunk-THVU3RNH.js → chunk-YAVY33G4.js} +1 -1
- package/chunks/{chunk-PJOHNFIY.js → chunk-YIAC2OXH.js} +5 -5
- package/chunks/{chunk-CU47KXB5.js → chunk-YTSN63PD.js} +6 -6
- package/chunks/{chunk-DSFHVTWD.js → chunk-YXEVDA66.js} +2 -2
- package/chunks/{chunk-MB32MS4U.js → chunk-ZLJQIGCH.js} +260 -175
- package/chunks/{chunk-6TAASXWL.js → chunk-ZX6RZZFB.js} +3 -3
- package/chunks/{computer-use-5QWCFNKD.js → computer-use-BG2EHNJE.js} +37 -34
- package/chunks/{config-utils-WADIDWGG.js → config-utils-E3ZQTHGM.js} +4 -4
- package/chunks/{contextCommand-4Z7T7TUM.js → contextCommand-JAPYNKFC.js} +41 -38
- package/chunks/{core-runtime-6N4EFC2Q.js → core-runtime-2VCZN5QF.js} +37 -34
- package/chunks/{create-sub-session-AEREHZBQ.js → create-sub-session-52OUA2VU.js} +52 -43
- package/chunks/{create-sub-session-62YZWVAY.js → create-sub-session-J32WC64U.js} +2 -2
- package/chunks/{cron-create-6E7GIQTG.js → cron-create-HMFSHIAR.js} +4 -4
- package/chunks/{cron-delete-JD26XY3W.js → cron-delete-ZJFHOX57.js} +4 -4
- package/chunks/{cron-list-CUWFB44G.js → cron-list-ZEX2NBMN.js} +4 -4
- package/chunks/{daemon-PCNCI5YU.js → daemon-CCIX4BMG.js} +47 -6
- package/chunks/{daemon-status-provider-DDF7C5M7.js → daemon-status-provider-F2YGDKHR.js} +48 -45
- package/chunks/{daemon-trust-policy-Q4KSOJTR.js → daemon-trust-policy-XCY7JETR.js} +43 -40
- package/chunks/{daemon-trust-policy-monitor-V6FTE3IY.js → daemon-trust-policy-monitor-FBHB5GMQ.js} +43 -40
- package/chunks/{de-SY6O76BF.js → de-VL76CPLV.js} +50 -5
- package/chunks/{deferred-core-runtime-GHJ5GQHK.js → deferred-core-runtime-BBLJ4JUM.js} +37 -34
- package/chunks/display-image-2WOG27DY.js +184 -0
- package/chunks/{dist-ZHXOBXDN.js → dist-3BMEUGTG.js} +1 -1
- package/chunks/{dist-OAOC5OV4.js → dist-7JGAAQSC.js} +2 -2
- package/chunks/{dist-SL2LUMML.js → dist-A7H2KKUC.js} +1 -1
- package/chunks/{dist-ULIG4M5H.js → dist-C5U4LJKW.js} +162 -15
- package/chunks/{dist-2PERFI23.js → dist-DPPHJAVL.js} +3 -3
- package/chunks/{dist-PVEAFLHY.js → dist-HVBMEYWK.js} +1 -1
- package/chunks/{dist-26BIMQT6.js → dist-IKGVITP3.js} +676 -37
- package/chunks/{dist-WGMNT3JQ.js → dist-SFQ34F4M.js} +24 -6
- package/chunks/{earlyInputCapture-TQXLLISD.js → earlyInputCapture-ALVSMKP7.js} +38 -35
- package/chunks/{edit-FJEUV6KZ.js → edit-POB3CIHQ.js} +37 -34
- package/chunks/{en-NBK3JKCE.js → en-IRJ2WN5T.js} +61 -6
- package/chunks/{enter-worktree-7GE3TZ4P.js → enter-worktree-Q2N7UZWC.js} +37 -34
- package/chunks/{enterPlanMode-KR5TMPCJ.js → enterPlanMode-QGAH2GMP.js} +37 -34
- package/chunks/{environment-SWL3CMB3.js → environment-FE5AX2U5.js} +40 -37
- package/chunks/{errors-XQE7BGZV.js → errors-SLMCFLSC.js} +40 -37
- package/chunks/{exit-worktree-CHKTYNCV.js → exit-worktree-7WO2LPLF.js} +37 -34
- package/chunks/{exitPlanMode-QYAG6LWX.js → exitPlanMode-3PINWUTY.js} +37 -34
- package/chunks/{fast-path-Z2K7W6DC.js → fast-path-SVFFEL6U.js} +17 -4
- package/chunks/{fr-4KG5V7UT.js → fr-GK3HQYVB.js} +50 -5
- package/chunks/{gemini-YU4XKEDG.js → gemini-QECJNKNJ.js} +151 -90
- package/chunks/{geminiContentGenerator-ZZX6NBO4.js → geminiContentGenerator-ZFAZKT6R.js} +6 -6
- package/chunks/{glob-VYF5CXSX.js → glob-GXUNQYNR.js} +37 -34
- package/chunks/{goal-tools-HGO6VXPB.js → goal-tools-SPQ5M6D3.js} +3 -3
- package/chunks/{grep-5DP5ZUTW.js → grep-LVU5KBCV.js} +37 -34
- package/chunks/{handleAutoUpdate-UVBJ56DL.js → handleAutoUpdate-MPDHQY72.js} +43 -40
- package/chunks/{i18n-UQNYHEUD.js → i18n-LEYRN6RV.js} +39 -36
- package/chunks/{image-gen-WHPIZNWF.js → image-gen-4T2D4PTP.js} +9 -9
- package/chunks/{initializer-GMIICF4W.js → initializer-PQV2THBS.js} +44 -41
- package/chunks/{installationInfo-4MGG4WVI.js → installationInfo-XC3HXLTX.js} +38 -35
- package/chunks/{ja-F3GSQXMF.js → ja-3FA46IKD.js} +50 -5
- package/chunks/{keychain-token-storage-IKO4G53C.js → keychain-token-storage-7BT4TQ2A.js} +2 -2
- package/chunks/{kittyProtocolDetector-MBRTDRBK.js → kittyProtocolDetector-BFLAKYXH.js} +1 -1
- package/chunks/{list-CPN2W334.js → list-AQBTPZRG.js} +46 -43
- package/chunks/{list-agents-PXJ7ZUFB.js → list-agents-TWEGRJWO.js} +2 -2
- package/chunks/{loadedSettingsAdapter-ZQAV5NDO.js → loadedSettingsAdapter-EZYPDX2J.js} +43 -40
- package/chunks/{loggingContentGenerator-5E7W4IEP.js → loggingContentGenerator-WD6YWU7Q.js} +52 -37
- package/chunks/{loop-wakeup-Y26NQZ5I.js → loop-wakeup-6LLEOQYV.js} +5 -5
- package/chunks/{ls-ONQTTMQR.js → ls-H5WX22VK.js} +4 -4
- package/chunks/{lsp-YGHHRGMD.js → lsp-G6FXYEIS.js} +2 -2
- package/chunks/{managed-npm-update-MKKAXYXA.js → managed-npm-update-BMM57CHD.js} +40 -37
- package/chunks/{mcp-V5NTJF6X.js → mcp-FMI6NCWA.js} +43 -40
- package/chunks/{monitor-CO3ASY6E.js → monitor-PZJOYAA2.js} +37 -34
- package/chunks/nonInteractiveCli-QPX6R4LL.js +152 -0
- package/chunks/{notebook-edit-Z7AEE6FM.js → notebook-edit-GZF2SKTQ.js} +37 -34
- package/chunks/{openaiContentGenerator-CA3MQOP3.js → openaiContentGenerator-ZPLCFAAG.js} +18 -18
- package/chunks/{pidfile-NL7MKDRU.js → pidfile-PCADVJQW.js} +38 -35
- package/chunks/{processUtils-PB5K2DYH.js → processUtils-FKUVQVEU.js} +2 -2
- package/chunks/{pt-EQ33KWEN.js → pt-3AOBKPIJ.js} +50 -5
- package/chunks/{qwenContentGenerator-JYFNDCOS.js → qwenContentGenerator-2Y4R6YLB.js} +42 -40
- package/chunks/{qwenOAuth2-W2ALKQDD.js → qwenOAuth2-UCEHY3I2.js} +8 -8
- package/chunks/{read-file-IEOR5H5W.js → read-file-DYHDFVAS.js} +10 -10
- package/chunks/{read-mcp-resource-U2IJN5HM.js → read-mcp-resource-DRZSI3HE.js} +2 -2
- package/chunks/{record-artifact-MGPJ7EG4.js → record-artifact-IPIRWMFY.js} +3 -3
- package/chunks/{resumeHistoryUtils-BNBTP5AS.js → resumeHistoryUtils-5JS6R3AJ.js} +45 -42
- package/chunks/{ripGrep-UMQODKEB.js → ripGrep-2QOR3ZQT.js} +37 -34
- package/chunks/{ru-7OZAUKGG.js → ru-VJRAMC4W.js} +50 -5
- package/chunks/{run-qwen-serve-RN2R6QQW.js → run-qwen-serve-MTVRAUBR.js} +271 -60
- package/chunks/{runtime-QFJ2MJF5.js → runtime-DQGE2DYR.js} +50 -45
- package/chunks/{scheduler-AMYUFOZI.js → scheduler-BXIZQ4OO.js} +37 -34
- package/chunks/{sdk-exporters-http-4BQANSJ6.js → sdk-exporters-http-IKNWQJNV.js} +2 -2
- package/chunks/{sdk-impl-Z4VXWVFX.js → sdk-impl-7CUUMQDB.js} +2 -2
- package/chunks/{send-message-PMP4ATVM.js → send-message-LHJLVWFD.js} +5 -4
- package/chunks/{serve-EIIYJVX3.js → serve-D4GYHFLL.js} +44 -40
- package/chunks/{server-EP2LLAPD.js → server-S22MLWTJ.js} +618 -387
- package/chunks/{session-GMPZBLOW.js → session-AHNM6YXP.js} +151 -87
- package/chunks/{settings-LN7RNKBS.js → settings-77MDDUSX.js} +42 -39
- package/chunks/{shell-EM2OWU5X.js → shell-DLD2VQTQ.js} +37 -34
- package/chunks/{skill-T5VPSK73.js → skill-3B2PAQE4.js} +27 -14
- package/chunks/{skill-settings-GMR3GMNY.js → skill-settings-STR5NF4B.js} +42 -39
- package/chunks/{spawnChannel-YPCU62DI.js → spawnChannel-TOWYOVDZ.js} +39 -36
- package/chunks/{standalone-update-JAKIM2NF.js → standalone-update-F6ZWABD7.js} +40 -37
- package/chunks/{startInteractiveUI-YETQWGYF.js → startInteractiveUI-QR7MHDX7.js} +1829 -1036
- package/chunks/{syntheticOutput-D7E6ZFKR.js → syntheticOutput-EYL7DWO7.js} +3 -3
- package/chunks/{task-create-NFCYD43L.js → task-create-4ALZMGP5.js} +10 -9
- package/chunks/{task-list-TAVMGEVD.js → task-list-6CVQPORX.js} +6 -6
- package/chunks/{task-stop-ZDF2UJRM.js → task-stop-Y5ZTFVRX.js} +2 -2
- package/chunks/{task-update-6L7LHGEX.js → task-update-IKCEEWJ6.js} +10 -9
- package/chunks/{team-create-LFJ6HGNY.js → team-create-LQVIAVRF.js} +37 -34
- package/chunks/{team-delete-DPGGRQBU.js → team-delete-CE7DC53R.js} +6 -6
- package/chunks/{team-plan-approval-C2KLSDGO.js → team-plan-approval-G5PUNI52.js} +37 -34
- package/chunks/terminal-image-renderer-33GSM55L.js +90 -0
- package/chunks/{theme-manager-JQ3ZGBP5.js → theme-manager-DBFM5QOG.js} +38 -35
- package/chunks/{todoWrite-2UO5G6G6.js → todoWrite-FTZWQRZH.js} +108 -36
- package/chunks/{tool-search-FAZBFRJZ.js → tool-search-RGG7BBC4.js} +13 -12
- package/chunks/{total-session-admission-5CALIVYO.js → total-session-admission-LY3RMXXI.js} +44 -41
- package/chunks/{trustedFolders-KOPSP44S.js → trustedFolders-3M4IQ6K6.js} +39 -36
- package/chunks/{update-relaunch-6QL2TICS.js → update-relaunch-G3CMSX3M.js} +5 -5
- package/chunks/{updateCheck-4Q6RIKFW.js → updateCheck-ZKFGBDTG.js} +42 -39
- package/chunks/{useAutoAcceptIndicator-Q5BMKZV3.js → useAutoAcceptIndicator-7SAFZK5H.js} +47 -44
- package/chunks/{validateNonInterActiveAuth-GKOC5F6Z.js → validateNonInterActiveAuth-F2K6UGE4.js} +88 -84
- package/chunks/{version-VSATY2LD.js → version-KM6MYV2D.js} +1 -1
- package/chunks/{web-fetch-JCLKL6NL.js → web-fetch-SM4LZHRS.js} +13 -13
- package/chunks/{web-search-DSQTFUBX.js → web-search-OGKZNDAC.js} +8 -8
- package/chunks/{workflow-M6QAVKVJ.js → workflow-HU365RFR.js} +419 -304
- package/chunks/{workspace-providers-status-YKLTLMJA.js → workspace-providers-status-QKKXQHL7.js} +46 -43
- package/chunks/{workspace-registration-store-5DMGKU64.js → workspace-registration-store-7J7KOXFD.js} +2 -2
- package/chunks/{workspace-registry-PTYUSYXX.js → workspace-registry-KC66O6DH.js} +44 -41
- package/chunks/{workspace-service-25ML3T47.js → workspace-service-TEV5Q2AA.js} +51 -48
- package/chunks/{workspace-skills-status-YKZWOYRX.js → workspace-skills-status-VRL55OMU.js} +45 -42
- package/chunks/{workspace-trust-reconciler-5FI2S3OS.js → workspace-trust-reconciler-COC5M7CY.js} +50 -47
- package/chunks/{write-file-AY7VLP5X.js → write-file-3SO2BMNO.js} +37 -34
- package/chunks/{zh-H3YDK5QW.js → zh-ARWDLDLR.js} +58 -6
- package/chunks/{zh-TW-JYCP7XUA.js → zh-TW-Y4RGI3P7.js} +58 -6
- package/chunks/{zoom-image-S4LJZMD5.js → zoom-image-O3RWTVKV.js} +10 -10
- package/cli.js +32 -48
- package/locales/ca.js +68 -4
- package/locales/de.js +70 -4
- package/locales/en.js +84 -6
- package/locales/fr.js +72 -4
- package/locales/ja.js +69 -4
- package/locales/pt.js +68 -4
- package/locales/ru.js +71 -4
- package/locales/zh-TW.js +74 -6
- package/locales/zh.js +74 -6
- package/package.json +3 -3
- package/web-shell/assets/{arc-xjArKHU2.js → arc-KuwiZ67W.js} +1 -1
- package/web-shell/assets/{architectureDiagram-3BPJPVTR-BgrQDNYG.js → architectureDiagram-3BPJPVTR-Cppop6HB.js} +1 -1
- package/web-shell/assets/{blockDiagram-GPEHLZMM-CXxWC-1_.js → blockDiagram-GPEHLZMM-DQ6HT72s.js} +1 -1
- package/web-shell/assets/{c4Diagram-AAUBKEIU-Dx1tLm3v.js → c4Diagram-AAUBKEIU-B8TX_Mh-.js} +1 -1
- package/web-shell/assets/channel-BZd6Ile0.js +1 -0
- package/web-shell/assets/{chunk-2J33WTMH-CBxjogVR.js → chunk-2J33WTMH-B2WBUTp8.js} +1 -1
- package/web-shell/assets/{chunk-4BX2VUAB-izb-rY5W.js → chunk-4BX2VUAB-DXUsWC6O.js} +1 -1
- package/web-shell/assets/{chunk-55IACEB6-NzLyvSb8.js → chunk-55IACEB6-DtB-6cyk.js} +1 -1
- package/web-shell/assets/{chunk-727SXJPM-DVyKb0dl.js → chunk-727SXJPM-B-PhPyC3.js} +1 -1
- package/web-shell/assets/{chunk-AQP2D5EJ-BtqL7NzB.js → chunk-AQP2D5EJ-DNaTFMSC.js} +1 -1
- package/web-shell/assets/{chunk-FMBD7UC4-iNpdKIO0.js → chunk-FMBD7UC4-DZ345tFf.js} +1 -1
- package/web-shell/assets/{chunk-ND2GUHAM-DI7cbFmX.js → chunk-ND2GUHAM-BR_EpgzJ.js} +1 -1
- package/web-shell/assets/{chunk-QZHKN3VN-3Y_-xFYs.js → chunk-QZHKN3VN-BTU-0gDT.js} +1 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-B7c-TqtK.js +1 -0
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-B7c-TqtK.js +1 -0
- package/web-shell/assets/{cose-bilkent-S5V4N54A--raRatZn.js → cose-bilkent-S5V4N54A-BmsKBCNt.js} +1 -1
- package/web-shell/assets/{dagre-BM42HDAG-B8SU70mO.js → dagre-BM42HDAG-Ba8YWdDC.js} +1 -1
- package/web-shell/assets/{diagram-2AECGRRQ-ewgoakXo.js → diagram-2AECGRRQ-CCt2SnI6.js} +1 -1
- package/web-shell/assets/{diagram-5GNKFQAL-Bm_JLTnS.js → diagram-5GNKFQAL-BVTLXEU7.js} +1 -1
- package/web-shell/assets/{diagram-KO2AKTUF-DEIUjUy9.js → diagram-KO2AKTUF-DpDAVCYV.js} +1 -1
- package/web-shell/assets/{diagram-LMA3HP47-C2Wmrpj-.js → diagram-LMA3HP47-8ljXg-TB.js} +1 -1
- package/web-shell/assets/{diagram-OG6HWLK6-CtYe6bFx.js → diagram-OG6HWLK6-JAXfQSmd.js} +1 -1
- package/web-shell/assets/{erDiagram-TEJ5UH35-DfpHcWLV.js → erDiagram-TEJ5UH35-CUeakG6k.js} +1 -1
- package/web-shell/assets/{flowDiagram-I6XJVG4X-CAiUhio5.js → flowDiagram-I6XJVG4X-Cd4Wrdwv.js} +1 -1
- package/web-shell/assets/{ganttDiagram-6RSMTGT7-CYc7ezr4.js → ganttDiagram-6RSMTGT7-C0nMFvH_.js} +1 -1
- package/web-shell/assets/{gitGraphDiagram-PVQCEYII-70lbkcRS.js → gitGraphDiagram-PVQCEYII-uKk88n_L.js} +1 -1
- package/web-shell/assets/index-BXGtjHs5.js +1756 -0
- package/web-shell/assets/{index-Ww86nT9f.js → index-C1UWBJSX.js} +1 -1
- package/web-shell/assets/index-WxSvj2tI.css +5 -0
- package/web-shell/assets/{infoDiagram-5YYISTIA-C7e8DWPa.js → infoDiagram-5YYISTIA-GfPN17hR.js} +1 -1
- package/web-shell/assets/{ishikawaDiagram-YF4QCWOH-BYLr2op-.js → ishikawaDiagram-YF4QCWOH-CDbWTcGa.js} +1 -1
- package/web-shell/assets/{journeyDiagram-JHISSGLW-hEibAHKX.js → journeyDiagram-JHISSGLW-J8TvvVFz.js} +1 -1
- package/web-shell/assets/{kanban-definition-UN3LZRKU-F2rt8Uhp.js → kanban-definition-UN3LZRKU-Ds_ndLrs.js} +1 -1
- package/web-shell/assets/{linear-DPhyNezd.js → linear-DuL9O4i3.js} +1 -1
- package/web-shell/assets/{mermaid.core-ZUtnug0n.js → mermaid.core-DtK4PsQB.js} +5 -5
- package/web-shell/assets/{mindmap-definition-RKZ34NQL-DDWcMoi8.js → mindmap-definition-RKZ34NQL-DD0r7MS3.js} +1 -1
- package/web-shell/assets/{pieDiagram-4H26LBE5-CTRKzw1_.js → pieDiagram-4H26LBE5-CxGPZ8Q-.js} +1 -1
- package/web-shell/assets/{quadrantDiagram-W4KKPZXB-CAEwYG_z.js → quadrantDiagram-W4KKPZXB-Ds7Buxed.js} +1 -1
- package/web-shell/assets/{requirementDiagram-4Y6WPE33-CRjnH9D9.js → requirementDiagram-4Y6WPE33-DIx28ph5.js} +1 -1
- package/web-shell/assets/{sankeyDiagram-5OEKKPKP-LPQT_sOd.js → sankeyDiagram-5OEKKPKP-AxdAYcVX.js} +1 -1
- package/web-shell/assets/{sequenceDiagram-3UESZ5HK-Ht2Iqvb0.js → sequenceDiagram-3UESZ5HK-CojoXAZ5.js} +1 -1
- package/web-shell/assets/{stateDiagram-AJRCARHV-CIUdqOXu.js → stateDiagram-AJRCARHV-Dy1WN3mi.js} +1 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BaTNMz02.js +1 -0
- package/web-shell/assets/{timeline-definition-PNZ67QCA-BcilneZF.js → timeline-definition-PNZ67QCA-DeWe_43M.js} +1 -1
- package/web-shell/assets/{vennDiagram-CIIHVFJN-BljwiiH1.js → vennDiagram-CIIHVFJN-BN8PVlFq.js} +1 -1
- package/web-shell/assets/{wardley-L42UT6IY-DeKjkYjq.js → wardley-L42UT6IY-CbjV_1hf.js} +1 -1
- package/web-shell/assets/{wardleyDiagram-YWT4CUSO-L3U1H7KG.js → wardleyDiagram-YWT4CUSO-D2mw84_p.js} +1 -1
- package/web-shell/assets/{xychartDiagram-2RQKCTM6-IJnWsgMT.js → xychartDiagram-2RQKCTM6-er9CTQXi.js} +1 -1
- package/web-shell/index.html +2 -2
- package/chunks/chunk-4KP2F2TE.js +0 -82
- package/chunks/chunk-HGT6JR3U.js +0 -177
- package/chunks/nonInteractiveCli-ZJYEOO7U.js +0 -148
- package/web-shell/assets/channel-B1cyk94G.js +0 -1
- package/web-shell/assets/classDiagram-4FO5ZUOK-BpBYZoRE.js +0 -1
- package/web-shell/assets/classDiagram-v2-Q7XG4LA2-BpBYZoRE.js +0 -1
- package/web-shell/assets/index-C1k3PDuU.css +0 -5
- package/web-shell/assets/index-DZLIXILO.js +0 -1750
- package/web-shell/assets/insert-DmRbh9Rv.svg +0 -1
- package/web-shell/assets/stateDiagram-v2-BHNVJYJU-BmqqQZ6w.js +0 -1
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
import {
|
|
4
4
|
PollingChannelBase,
|
|
5
5
|
getGlobalQwenDir,
|
|
6
|
+
getWorkspaceScopeDirName,
|
|
6
7
|
sanitizeLogText
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-DIEFUBV6.js";
|
|
8
9
|
import "./chunk-UDXSXLER.js";
|
|
9
10
|
import "./chunk-H6XPXXMH.js";
|
|
10
11
|
import {
|
|
@@ -125,9 +126,9 @@ init_esbuild_shims();
|
|
|
125
126
|
|
|
126
127
|
// packages/channels/github/dist/GithubAdapter.js
|
|
127
128
|
init_esbuild_shims();
|
|
128
|
-
import { createHash } from "node:crypto";
|
|
129
|
-
import { appendFileSync, chmodSync, mkdirSync } from "node:fs";
|
|
130
|
-
import { join } from "node:path";
|
|
129
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
130
|
+
import { appendFileSync, chmodSync, existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
131
|
+
import { dirname, join } from "node:path";
|
|
131
132
|
import process2 from "node:process";
|
|
132
133
|
|
|
133
134
|
// node_modules/@octokit/rest/dist-src/index.js
|
|
@@ -3840,6 +3841,27 @@ function normalizeReasonFilter(config, channelName) {
|
|
|
3840
3841
|
return reasons.length > 0 ? new Set(reasons) : null;
|
|
3841
3842
|
}
|
|
3842
3843
|
__name(normalizeReasonFilter, "normalizeReasonFilter");
|
|
3844
|
+
var MAX_INBOUND_TASK_ATTEMPTS = 3;
|
|
3845
|
+
function isOptionalStringArray(value) {
|
|
3846
|
+
return value === void 0 || Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
3847
|
+
}
|
|
3848
|
+
__name(isOptionalStringArray, "isOptionalStringArray");
|
|
3849
|
+
function isInboundEnvelope(value) {
|
|
3850
|
+
if (value === void 0)
|
|
3851
|
+
return true;
|
|
3852
|
+
if (value === null || typeof value !== "object")
|
|
3853
|
+
return false;
|
|
3854
|
+
const envelope = value;
|
|
3855
|
+
return typeof envelope.channelName === "string" && typeof envelope.senderId === "string" && typeof envelope.senderName === "string" && typeof envelope.chatId === "string" && typeof envelope.text === "string" && typeof envelope.isGroup === "boolean" && typeof envelope.isMentioned === "boolean" && typeof envelope.isReplyToBot === "boolean" && (envelope.chatName === void 0 || typeof envelope.chatName === "string") && (envelope.threadId === void 0 || typeof envelope.threadId === "string") && (envelope.messageId === void 0 || typeof envelope.messageId === "string") && (envelope.referencedText === void 0 || typeof envelope.referencedText === "string") && (envelope.imageBase64 === void 0 || typeof envelope.imageBase64 === "string") && (envelope.imageMimeType === void 0 || typeof envelope.imageMimeType === "string") && (envelope.attachments === void 0 || Array.isArray(envelope.attachments)) && (envelope.metadata === void 0 || typeof envelope.metadata === "string") && (envelope.alreadyPrefixed === void 0 || envelope.alreadyPrefixed === true);
|
|
3856
|
+
}
|
|
3857
|
+
__name(isInboundEnvelope, "isInboundEnvelope");
|
|
3858
|
+
function isInboundTaskRecord(value) {
|
|
3859
|
+
if (value === null || typeof value !== "object")
|
|
3860
|
+
return false;
|
|
3861
|
+
const record = value;
|
|
3862
|
+
return record.version === 1 && typeof record.id === "string" && typeof record.createdAt === "string" && typeof record.updatedAt === "string" && ["accepted", "running", "reply_pending", "failed", "cancelled"].includes(record.state) && Number.isSafeInteger(record.issueNumber) && record.source !== null && typeof record.source === "object" && typeof record.source.chatId === "string" && (record.source.threadId === void 0 || typeof record.source.threadId === "string") && (record.source.messageId === void 0 || typeof record.source.messageId === "string") && isInboundEnvelope(record.envelope) && record.dedupe !== null && typeof record.dedupe === "object" && isOptionalStringArray(record.dedupe.dispatchedBodies) && isOptionalStringArray(record.dedupe.dispatchedComments) && isOptionalStringArray(record.dedupe.dispatchedEvents) && (record.attempts === void 0 || Number.isSafeInteger(record.attempts) && record.attempts >= 0) && (record.errorCommentPosted === void 0 || typeof record.errorCommentPosted === "boolean") && (record.error === void 0 || typeof record.error === "string");
|
|
3863
|
+
}
|
|
3864
|
+
__name(isInboundTaskRecord, "isInboundTaskRecord");
|
|
3843
3865
|
var FinalPublicationError = class extends Error {
|
|
3844
3866
|
static {
|
|
3845
3867
|
__name(this, "FinalPublicationError");
|
|
@@ -3863,8 +3885,7 @@ function isNoReplySentinel(text) {
|
|
|
3863
3885
|
__name(isNoReplySentinel, "isNoReplySentinel");
|
|
3864
3886
|
function isDefiniteNoWriteGithubError(err) {
|
|
3865
3887
|
const e = err;
|
|
3866
|
-
|
|
3867
|
-
return e.status === 429 || e.status === 403 && remaining === 0;
|
|
3888
|
+
return (e.status === 403 || e.status === 429) && Number(e.response?.headers?.["x-ratelimit-remaining"]) === 0;
|
|
3868
3889
|
}
|
|
3869
3890
|
__name(isDefiniteNoWriteGithubError, "isDefiniteNoWriteGithubError");
|
|
3870
3891
|
function parseTriggerKind(metadata) {
|
|
@@ -3881,6 +3902,11 @@ function buildTriggerGuidance(reason) {
|
|
|
3881
3902
|
return `For ${reason}, output exactly ${NO_REPLY_SENTINEL} when a public reply is unnecessary.`;
|
|
3882
3903
|
}
|
|
3883
3904
|
__name(buildTriggerGuidance, "buildTriggerGuidance");
|
|
3905
|
+
function isPendingFinalDelivery(value) {
|
|
3906
|
+
const item = value;
|
|
3907
|
+
return item !== null && typeof item === "object" && typeof item.id === "string" && typeof item.createdAt === "string" && typeof item.chatId === "string" && typeof item.threadId === "string" && typeof item.fullText === "string" && typeof item.sessionId === "string";
|
|
3908
|
+
}
|
|
3909
|
+
__name(isPendingFinalDelivery, "isPendingFinalDelivery");
|
|
3884
3910
|
var GithubChannel = class extends PollingChannelBase {
|
|
3885
3911
|
static {
|
|
3886
3912
|
__name(this, "GithubChannel");
|
|
@@ -3890,7 +3916,17 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
3890
3916
|
webOrigin = "https://github.com";
|
|
3891
3917
|
activeReactions = /* @__PURE__ */ new Map();
|
|
3892
3918
|
reactionsPendingRemoval = /* @__PURE__ */ new Set();
|
|
3919
|
+
pendingFinalDeliveryRetry;
|
|
3920
|
+
pendingFinalDeliveryRetryAbort;
|
|
3921
|
+
pendingFinalDeliveryRequestsActive = 0;
|
|
3922
|
+
pendingFinalDeliveryRetryStopRequested = false;
|
|
3893
3923
|
reasonFilter = null;
|
|
3924
|
+
inboundRecoveryPending = true;
|
|
3925
|
+
recoverableInboundTasks = 0;
|
|
3926
|
+
activeInboundTaskIdsByMessage = /* @__PURE__ */ new Map();
|
|
3927
|
+
cancelledInboundTaskIds = /* @__PURE__ */ new Set();
|
|
3928
|
+
pendingCursorUpdatedAt;
|
|
3929
|
+
inboundPersistenceBlocked = false;
|
|
3894
3930
|
constructor(name, config, bridge, options) {
|
|
3895
3931
|
config.blockStreaming = "off";
|
|
3896
3932
|
config.instructions = [
|
|
@@ -3949,10 +3985,40 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
3949
3985
|
`);
|
|
3950
3986
|
}
|
|
3951
3987
|
this.gate.replaceAllowedUsers(allowed);
|
|
3988
|
+
this.migrateLegacyPublicationState();
|
|
3989
|
+
this.inboundPersistenceBlocked = false;
|
|
3990
|
+
this.inboundRecoveryPending = true;
|
|
3991
|
+
try {
|
|
3992
|
+
this.recoverableInboundTasks = this.readInboundTasks().filter((record) => this.isRecoverableInboundTask(record)).length;
|
|
3993
|
+
} catch {
|
|
3994
|
+
this.recoverableInboundTasks = 0;
|
|
3995
|
+
}
|
|
3996
|
+
this.pendingFinalDeliveryRetryStopRequested = false;
|
|
3952
3997
|
this.startPollLoop();
|
|
3998
|
+
if (this.pendingFinalDeliveryRetry) {
|
|
3999
|
+
return;
|
|
4000
|
+
}
|
|
4001
|
+
const retryAbort = new AbortController();
|
|
4002
|
+
const retry = this.retryPendingFinalDeliveries(retryAbort.signal).catch((err) => {
|
|
4003
|
+
if (!retryAbort.signal.aborted) {
|
|
4004
|
+
process2.stderr.write(`[Channel:${this.name}] pending GitHub delivery retry failed: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
4005
|
+
`);
|
|
4006
|
+
}
|
|
4007
|
+
}).finally(() => {
|
|
4008
|
+
if (this.pendingFinalDeliveryRetry === retry) {
|
|
4009
|
+
this.pendingFinalDeliveryRetry = void 0;
|
|
4010
|
+
this.pendingFinalDeliveryRetryAbort = void 0;
|
|
4011
|
+
}
|
|
4012
|
+
});
|
|
4013
|
+
this.pendingFinalDeliveryRetryAbort = retryAbort;
|
|
4014
|
+
this.pendingFinalDeliveryRetry = retry;
|
|
3953
4015
|
}
|
|
3954
4016
|
disconnect() {
|
|
3955
4017
|
this.stopPollLoop();
|
|
4018
|
+
this.pendingFinalDeliveryRetryStopRequested = true;
|
|
4019
|
+
if (this.pendingFinalDeliveryRequestsActive === 0) {
|
|
4020
|
+
this.pendingFinalDeliveryRetryAbort?.abort();
|
|
4021
|
+
}
|
|
3956
4022
|
}
|
|
3957
4023
|
async sendMessage(_chatId, _text) {
|
|
3958
4024
|
throw new Error(`[Channel:${this.name}] sendMessage requires a threadId; use sendThreadMessage`);
|
|
@@ -3966,18 +4032,15 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
3966
4032
|
async publishFinalResponse(chatId, threadId, fullText, sessionId) {
|
|
3967
4033
|
const threadMatch = threadId?.match(/^(issue|pr):(\d+)$/);
|
|
3968
4034
|
const metadata = this.getResponseMetadata(sessionId);
|
|
3969
|
-
const auditBase = {
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
number: threadMatch ? Number(threadMatch[2]) : void 0,
|
|
4035
|
+
const auditBase = this.buildPublicationAuditBase({
|
|
4036
|
+
chatId,
|
|
4037
|
+
threadId,
|
|
4038
|
+
fullText,
|
|
3974
4039
|
sessionId,
|
|
3975
4040
|
sourceMessageId: this.getResponseMessageId(sessionId),
|
|
3976
4041
|
actor: this.getResponseSenderId(sessionId),
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
bodyChars: Array.from(fullText).length
|
|
3980
|
-
};
|
|
4042
|
+
metadata
|
|
4043
|
+
});
|
|
3981
4044
|
if (isNoReplySentinel(fullText)) {
|
|
3982
4045
|
this.recordPublicationAudit({
|
|
3983
4046
|
...auditBase,
|
|
@@ -3993,6 +4056,12 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
3993
4056
|
if (!threadMatch) {
|
|
3994
4057
|
throw new Error(`[Channel:${this.name}] invalid threadId format: ${threadId}`);
|
|
3995
4058
|
}
|
|
4059
|
+
this.recordPublicationAudit({
|
|
4060
|
+
...auditBase,
|
|
4061
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4062
|
+
type: "github_publication",
|
|
4063
|
+
outcome: "posting"
|
|
4064
|
+
});
|
|
3996
4065
|
try {
|
|
3997
4066
|
const comment = await this.createIssueComment(chatId, threadId, fullText, 3, isDefiniteNoWriteGithubError);
|
|
3998
4067
|
this.recordPublicationAudit({
|
|
@@ -4012,10 +4081,196 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
4012
4081
|
failurePhase: "delivery",
|
|
4013
4082
|
failureError: sanitizeLogText(err instanceof Error ? err.message : String(err), 200)
|
|
4014
4083
|
});
|
|
4084
|
+
if (threadId && isDefiniteNoWriteGithubError(err)) {
|
|
4085
|
+
try {
|
|
4086
|
+
this.enqueuePendingFinalDelivery({
|
|
4087
|
+
...auditBase,
|
|
4088
|
+
chatId,
|
|
4089
|
+
threadId,
|
|
4090
|
+
fullText
|
|
4091
|
+
});
|
|
4092
|
+
} catch (persistError) {
|
|
4093
|
+
throw new Error(`[Channel:${this.name}] failed to persist pending GitHub delivery: ${sanitizeLogText(persistError instanceof Error ? persistError.message : String(persistError), 200)}`, { cause: persistError });
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4015
4096
|
throw new FinalPublicationError(err instanceof Error ? err.message : String(err), { cause: err });
|
|
4016
4097
|
}
|
|
4017
4098
|
}
|
|
4018
|
-
|
|
4099
|
+
buildPublicationAuditBase(input) {
|
|
4100
|
+
const threadMatch = input.threadId?.match(/^(issue|pr):(\d+)$/);
|
|
4101
|
+
return {
|
|
4102
|
+
channel: this.name,
|
|
4103
|
+
triggerKind: parseTriggerKind(input.metadata),
|
|
4104
|
+
repository: input.chatId,
|
|
4105
|
+
number: threadMatch ? Number(threadMatch[2]) : void 0,
|
|
4106
|
+
sessionId: input.sessionId,
|
|
4107
|
+
sourceMessageId: input.sourceMessageId,
|
|
4108
|
+
actor: input.actor,
|
|
4109
|
+
threadId: input.threadId,
|
|
4110
|
+
bodySha256: createHash("sha256").update(input.fullText).digest("hex"),
|
|
4111
|
+
bodyChars: Array.from(input.fullText).length
|
|
4112
|
+
};
|
|
4113
|
+
}
|
|
4114
|
+
enqueuePendingFinalDelivery(input) {
|
|
4115
|
+
const record = {
|
|
4116
|
+
id: createHash("sha256").update(JSON.stringify([
|
|
4117
|
+
input.chatId,
|
|
4118
|
+
input.threadId,
|
|
4119
|
+
input.sessionId,
|
|
4120
|
+
input.sourceMessageId ?? randomUUID(),
|
|
4121
|
+
input.bodySha256
|
|
4122
|
+
])).digest("hex"),
|
|
4123
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4124
|
+
chatId: input.chatId,
|
|
4125
|
+
threadId: input.threadId,
|
|
4126
|
+
fullText: input.fullText,
|
|
4127
|
+
sessionId: input.sessionId,
|
|
4128
|
+
sourceMessageId: input.sourceMessageId,
|
|
4129
|
+
actor: input.actor,
|
|
4130
|
+
triggerKind: input.triggerKind
|
|
4131
|
+
};
|
|
4132
|
+
const pending = this.readPendingFinalDeliveries(true).filter((item) => item.id !== record.id);
|
|
4133
|
+
this.writePendingFinalDeliveries([...pending, record]);
|
|
4134
|
+
}
|
|
4135
|
+
async retryPendingFinalDeliveries(signal) {
|
|
4136
|
+
const pending = this.readPendingFinalDeliveries();
|
|
4137
|
+
for (const record of pending) {
|
|
4138
|
+
if (signal?.aborted)
|
|
4139
|
+
return;
|
|
4140
|
+
const auditBase = this.buildPublicationAuditBase({
|
|
4141
|
+
chatId: record.chatId,
|
|
4142
|
+
threadId: record.threadId,
|
|
4143
|
+
fullText: record.fullText,
|
|
4144
|
+
sessionId: record.sessionId,
|
|
4145
|
+
sourceMessageId: record.sourceMessageId,
|
|
4146
|
+
actor: record.actor,
|
|
4147
|
+
metadata: record.triggerKind ? `Trigger: ${record.triggerKind}.` : void 0
|
|
4148
|
+
});
|
|
4149
|
+
if (this.hasPostedPublicationAudit(record.id)) {
|
|
4150
|
+
process2.stderr.write(`[Channel:${this.name}] dropping pending GitHub delivery already recorded as posted: ${sanitizeLogText(record.id, 80)}
|
|
4151
|
+
`);
|
|
4152
|
+
if (this.updatePendingFinalDeliveries((current) => current.filter((item) => item.id !== record.id))) {
|
|
4153
|
+
this.removeReplyPendingInboundTask(record);
|
|
4154
|
+
}
|
|
4155
|
+
continue;
|
|
4156
|
+
}
|
|
4157
|
+
try {
|
|
4158
|
+
const comment = await this.createIssueComment(record.chatId, record.threadId, record.fullText, 3, isDefiniteNoWriteGithubError, signal);
|
|
4159
|
+
this.recordPublicationAudit({
|
|
4160
|
+
...auditBase,
|
|
4161
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4162
|
+
type: "github_publication",
|
|
4163
|
+
outcome: "posted",
|
|
4164
|
+
pendingId: record.id,
|
|
4165
|
+
commentId: comment.id,
|
|
4166
|
+
commentUrl: comment.html_url
|
|
4167
|
+
});
|
|
4168
|
+
if (!this.updatePendingFinalDeliveries((current) => current.filter((item) => item.id !== record.id))) {
|
|
4169
|
+
continue;
|
|
4170
|
+
}
|
|
4171
|
+
this.removeReplyPendingInboundTask(record);
|
|
4172
|
+
} catch (err) {
|
|
4173
|
+
if (signal?.aborted)
|
|
4174
|
+
return;
|
|
4175
|
+
if (isDefiniteNoWriteGithubError(err)) {
|
|
4176
|
+
continue;
|
|
4177
|
+
}
|
|
4178
|
+
this.recordPublicationAudit({
|
|
4179
|
+
...auditBase,
|
|
4180
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4181
|
+
type: "github_publication",
|
|
4182
|
+
outcome: "failed",
|
|
4183
|
+
failurePhase: "delivery",
|
|
4184
|
+
failureError: sanitizeLogText(err instanceof Error ? err.message : String(err), 200)
|
|
4185
|
+
});
|
|
4186
|
+
if (!this.updatePendingFinalDeliveries((current) => current.filter((item) => item.id !== record.id))) {
|
|
4187
|
+
continue;
|
|
4188
|
+
}
|
|
4189
|
+
this.removeReplyPendingInboundTask(record);
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
hasPostedPublicationAudit(pendingId) {
|
|
4194
|
+
try {
|
|
4195
|
+
return readFileSync(this.channelFilePath("github-audit.jsonl"), "utf-8").split("\n").some((line) => {
|
|
4196
|
+
if (!line)
|
|
4197
|
+
return false;
|
|
4198
|
+
let record;
|
|
4199
|
+
try {
|
|
4200
|
+
record = JSON.parse(line);
|
|
4201
|
+
} catch {
|
|
4202
|
+
return false;
|
|
4203
|
+
}
|
|
4204
|
+
return record.outcome === "posted" && record.pendingId === pendingId;
|
|
4205
|
+
});
|
|
4206
|
+
} catch {
|
|
4207
|
+
return false;
|
|
4208
|
+
}
|
|
4209
|
+
}
|
|
4210
|
+
updatePendingFinalDeliveries(update) {
|
|
4211
|
+
try {
|
|
4212
|
+
this.writePendingFinalDeliveries(update(this.readPendingFinalDeliveries(true)));
|
|
4213
|
+
return true;
|
|
4214
|
+
} catch (err) {
|
|
4215
|
+
process2.stderr.write(`[Channel:${this.name}] failed to update pending GitHub deliveries: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
4216
|
+
`);
|
|
4217
|
+
return false;
|
|
4218
|
+
}
|
|
4219
|
+
}
|
|
4220
|
+
removeReplyPendingInboundTask(delivery) {
|
|
4221
|
+
try {
|
|
4222
|
+
const tasks = this.readInboundTasks();
|
|
4223
|
+
const matching = tasks.filter((task) => task.state === "reply_pending" && task.source.chatId === delivery.chatId && task.source.threadId === delivery.threadId && task.source.messageId === delivery.sourceMessageId);
|
|
4224
|
+
for (const task of matching) {
|
|
4225
|
+
this.removeInboundTask(task.id);
|
|
4226
|
+
}
|
|
4227
|
+
} catch (cleanupErr) {
|
|
4228
|
+
process2.stderr.write(`[Channel:${this.name}] failed to clean up inbound task: ${sanitizeLogText(cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr), 200)}
|
|
4229
|
+
`);
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
pendingFinalDeliveriesPath() {
|
|
4233
|
+
return this.channelFilePath("github-pending-deliveries.json");
|
|
4234
|
+
}
|
|
4235
|
+
readPendingFinalDeliveries(strict = false) {
|
|
4236
|
+
try {
|
|
4237
|
+
const parsed = JSON.parse(readFileSync(this.pendingFinalDeliveriesPath(), "utf-8"));
|
|
4238
|
+
return Array.isArray(parsed) ? parsed.filter(isPendingFinalDelivery) : [];
|
|
4239
|
+
} catch (err) {
|
|
4240
|
+
if (err.code !== "ENOENT") {
|
|
4241
|
+
process2.stderr.write(`[Channel:${this.name}] failed to read pending GitHub deliveries: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
4242
|
+
`);
|
|
4243
|
+
if (strict)
|
|
4244
|
+
throw err;
|
|
4245
|
+
}
|
|
4246
|
+
return [];
|
|
4247
|
+
}
|
|
4248
|
+
}
|
|
4249
|
+
writePendingFinalDeliveries(records) {
|
|
4250
|
+
const path = this.pendingFinalDeliveriesPath();
|
|
4251
|
+
if (records.length === 0) {
|
|
4252
|
+
try {
|
|
4253
|
+
unlinkSync(path);
|
|
4254
|
+
} catch (err) {
|
|
4255
|
+
if (err.code !== "ENOENT")
|
|
4256
|
+
throw err;
|
|
4257
|
+
}
|
|
4258
|
+
return;
|
|
4259
|
+
}
|
|
4260
|
+
const dir = join(getGlobalQwenDir(), "channels", getWorkspaceScopeDirName(this.config.cwd));
|
|
4261
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4262
|
+
chmodSync(dir, 448);
|
|
4263
|
+
const tmpPath = `${path}.${process2.pid}.tmp`;
|
|
4264
|
+
writeFileSync(tmpPath, `${JSON.stringify(records)}
|
|
4265
|
+
`, {
|
|
4266
|
+
encoding: "utf-8",
|
|
4267
|
+
mode: 384
|
|
4268
|
+
});
|
|
4269
|
+
chmodSync(tmpPath, 384);
|
|
4270
|
+
renameSync(tmpPath, path);
|
|
4271
|
+
chmodSync(path, 384);
|
|
4272
|
+
}
|
|
4273
|
+
async createIssueComment(chatId, threadId, text, retries = 3, shouldRetry = () => true, signal) {
|
|
4019
4274
|
if (!threadId) {
|
|
4020
4275
|
throw new Error(`[Channel:${this.name}] createIssueComment requires a threadId`);
|
|
4021
4276
|
}
|
|
@@ -4025,12 +4280,23 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
4025
4280
|
}
|
|
4026
4281
|
const issueNumber = Number(match[1]);
|
|
4027
4282
|
const [owner, repo] = chatId.split("/");
|
|
4028
|
-
const response = await this.githubApi(() =>
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4283
|
+
const response = await this.githubApi(async () => {
|
|
4284
|
+
this.pendingFinalDeliveryRequestsActive += 1;
|
|
4285
|
+
try {
|
|
4286
|
+
return await this.octokit.rest.issues.createComment({
|
|
4287
|
+
owner,
|
|
4288
|
+
repo,
|
|
4289
|
+
issue_number: issueNumber,
|
|
4290
|
+
body: text,
|
|
4291
|
+
...signal ? { request: { signal } } : {}
|
|
4292
|
+
});
|
|
4293
|
+
} finally {
|
|
4294
|
+
this.pendingFinalDeliveryRequestsActive -= 1;
|
|
4295
|
+
if (this.pendingFinalDeliveryRequestsActive === 0 && this.pendingFinalDeliveryRetryStopRequested) {
|
|
4296
|
+
this.pendingFinalDeliveryRetryAbort?.abort();
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
}, `createComment(${threadId})`, retries, shouldRetry, signal);
|
|
4034
4300
|
return response.data;
|
|
4035
4301
|
}
|
|
4036
4302
|
/**
|
|
@@ -4099,15 +4365,25 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
4099
4365
|
});
|
|
4100
4366
|
}
|
|
4101
4367
|
async pollOnce() {
|
|
4368
|
+
this.inboundPersistenceBlocked = false;
|
|
4369
|
+
if (this.inboundRecoveryPending) {
|
|
4370
|
+
try {
|
|
4371
|
+
await this.recoverInboundTasks();
|
|
4372
|
+
} catch (err) {
|
|
4373
|
+
process2.stderr.write(`[Channel:${this.name}] inbound task recovery failed, will retry next poll: ${err}
|
|
4374
|
+
`);
|
|
4375
|
+
} finally {
|
|
4376
|
+
this.inboundRecoveryPending = false;
|
|
4377
|
+
}
|
|
4378
|
+
}
|
|
4102
4379
|
this.cursor.metaFloor ??= this.cursor.lastProcessedAt;
|
|
4103
4380
|
const since = new Date(new Date(this.cursor.lastProcessedAt).getTime() - 1e3).toISOString();
|
|
4104
4381
|
const notifications = await this.githubApi(() => this.octokit.paginate(this.octokit.rest.activity.listNotificationsForAuthenticatedUser, { since, per_page: 100 }), "listNotifications");
|
|
4105
4382
|
notifications.sort((a, b) => a.updated_at.localeCompare(b.updated_at));
|
|
4106
4383
|
const maxUpdatedAt = notifications.length > 0 ? notifications[notifications.length - 1].updated_at : this.cursor.lastProcessedAt;
|
|
4107
4384
|
const windowSince = this.cursor.lastProcessedAt;
|
|
4108
|
-
await this.markNotificationsAsRead(maxUpdatedAt);
|
|
4109
4385
|
if (maxUpdatedAt > this.cursor.lastProcessedAt) {
|
|
4110
|
-
this.
|
|
4386
|
+
this.pendingCursorUpdatedAt = !this.pendingCursorUpdatedAt || maxUpdatedAt > this.pendingCursorUpdatedAt ? maxUpdatedAt : this.pendingCursorUpdatedAt;
|
|
4111
4387
|
}
|
|
4112
4388
|
for (const notification of notifications) {
|
|
4113
4389
|
if (!notification.subject.url)
|
|
@@ -4171,6 +4447,17 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
4171
4447
|
continue;
|
|
4172
4448
|
}
|
|
4173
4449
|
}
|
|
4450
|
+
if (this.hasRecoverableInboundTasks()) {
|
|
4451
|
+
this.inboundRecoveryPending = true;
|
|
4452
|
+
}
|
|
4453
|
+
if (!this.inboundPersistenceBlocked && !this.hasRecoverableInboundTasks() && this.pendingCursorUpdatedAt) {
|
|
4454
|
+
const committedAt = this.pendingCursorUpdatedAt;
|
|
4455
|
+
await this.markNotificationsAsRead(committedAt);
|
|
4456
|
+
if (committedAt > this.cursor.lastProcessedAt) {
|
|
4457
|
+
this.cursor.lastProcessedAt = committedAt;
|
|
4458
|
+
}
|
|
4459
|
+
this.pendingCursorUpdatedAt = void 0;
|
|
4460
|
+
}
|
|
4174
4461
|
}
|
|
4175
4462
|
async processCommentLane(ctx, onlyMentioned, directed = false) {
|
|
4176
4463
|
const comments = await this.fetchNewComments(ctx);
|
|
@@ -4198,7 +4485,9 @@ var GithubChannel = class extends PollingChannelBase {
|
|
|
4198
4485
|
isReplyToBot: false,
|
|
4199
4486
|
metadata: this.buildRouteMetadata(ctx)
|
|
4200
4487
|
};
|
|
4201
|
-
if (!await this.dispatchEnvelope(envelope, ctx.issueNumber
|
|
4488
|
+
if (!await this.dispatchEnvelope(envelope, ctx.issueNumber, {
|
|
4489
|
+
dispatchedComments: [key]
|
|
4490
|
+
})) {
|
|
4202
4491
|
dispatched = true;
|
|
4203
4492
|
continue;
|
|
4204
4493
|
}
|
|
@@ -4238,7 +4527,9 @@ Trigger: ${reason}.
|
|
|
4238
4527
|
${buildTriggerGuidance(reason)}
|
|
4239
4528
|
${details}`
|
|
4240
4529
|
};
|
|
4241
|
-
await this.dispatchEnvelope(envelope, ctx.issueNumber
|
|
4530
|
+
await this.dispatchEnvelope(envelope, ctx.issueNumber, {
|
|
4531
|
+
dispatchedEvents: [trigger.key]
|
|
4532
|
+
});
|
|
4242
4533
|
this.recordDispatched("dispatchedEvents", trigger.key);
|
|
4243
4534
|
}
|
|
4244
4535
|
async processAggregateLane(ctx) {
|
|
@@ -4273,7 +4564,9 @@ ${summary}`,
|
|
|
4273
4564
|
isReplyToBot: false,
|
|
4274
4565
|
metadata: this.buildRouteMetadata(ctx)
|
|
4275
4566
|
};
|
|
4276
|
-
await this.dispatchEnvelope(envelope, ctx.issueNumber
|
|
4567
|
+
await this.dispatchEnvelope(envelope, ctx.issueNumber, {
|
|
4568
|
+
dispatchedComments: allComments.map((comment) => comment.node_id || String(comment.id))
|
|
4569
|
+
});
|
|
4277
4570
|
}
|
|
4278
4571
|
async findDirectTrigger(ctx, reason) {
|
|
4279
4572
|
const [owner, repo] = ctx.chatId.split("/");
|
|
@@ -4355,7 +4648,9 @@ ${summary}`,
|
|
|
4355
4648
|
isReplyToBot: false,
|
|
4356
4649
|
metadata: this.buildRouteMetadata(ctx)
|
|
4357
4650
|
};
|
|
4358
|
-
await this.dispatchEnvelope(envelope, issueNumber
|
|
4651
|
+
await this.dispatchEnvelope(envelope, issueNumber, {
|
|
4652
|
+
dispatchedBodies: [bodyKey]
|
|
4653
|
+
});
|
|
4359
4654
|
this.recordDispatchedBody(bodyKey);
|
|
4360
4655
|
} catch (err) {
|
|
4361
4656
|
process2.stderr.write(`[Channel:${this.name}] failed to fetch issue for first contact: ${err}
|
|
@@ -4374,24 +4669,235 @@ ${summary}`,
|
|
|
4374
4669
|
list.push(key);
|
|
4375
4670
|
this.cursor[field] = list.slice(-MAX_DISPATCHED);
|
|
4376
4671
|
}
|
|
4377
|
-
async dispatchEnvelope(envelope, issueNumber) {
|
|
4672
|
+
async dispatchEnvelope(envelope, issueNumber, dedupe = {}) {
|
|
4673
|
+
const task = this.claimInboundTask(envelope, issueNumber, dedupe);
|
|
4674
|
+
return this.runInboundTask(task);
|
|
4675
|
+
}
|
|
4676
|
+
claimInboundTask(envelope, issueNumber, dedupe) {
|
|
4677
|
+
const existing = this.readInboundTasks().find((record) => record.source.chatId === envelope.chatId && record.source.threadId === envelope.threadId && record.source.messageId === envelope.messageId);
|
|
4678
|
+
if (existing) {
|
|
4679
|
+
this.applyTaskDedupe(existing);
|
|
4680
|
+
return existing;
|
|
4681
|
+
}
|
|
4682
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4683
|
+
const task = {
|
|
4684
|
+
version: 1,
|
|
4685
|
+
id: randomUUID(),
|
|
4686
|
+
createdAt: now,
|
|
4687
|
+
updatedAt: now,
|
|
4688
|
+
state: "accepted",
|
|
4689
|
+
issueNumber,
|
|
4690
|
+
source: {
|
|
4691
|
+
chatId: envelope.chatId,
|
|
4692
|
+
threadId: envelope.threadId,
|
|
4693
|
+
messageId: envelope.messageId
|
|
4694
|
+
},
|
|
4695
|
+
envelope,
|
|
4696
|
+
dedupe,
|
|
4697
|
+
attempts: 0
|
|
4698
|
+
};
|
|
4699
|
+
this.updateInboundTasks((records) => [...records, task]);
|
|
4700
|
+
this.applyTaskDedupe(task);
|
|
4701
|
+
return task;
|
|
4702
|
+
}
|
|
4703
|
+
async runInboundTask(task) {
|
|
4704
|
+
if (!this.isRecoverableInboundTask(task))
|
|
4705
|
+
return true;
|
|
4706
|
+
const envelope = task.envelope;
|
|
4707
|
+
if (!envelope)
|
|
4708
|
+
return true;
|
|
4709
|
+
const attempts = (task.attempts ?? 0) + 1;
|
|
4710
|
+
this.activeInboundTaskIdsByMessage.set(this.inboundMessageKey(envelope.chatId, envelope.messageId), task.id);
|
|
4711
|
+
this.transitionInboundTask(task.id, "running", { attempts });
|
|
4712
|
+
let cancelled = false;
|
|
4378
4713
|
try {
|
|
4379
4714
|
await this.handleInbound(envelope);
|
|
4380
|
-
|
|
4715
|
+
cancelled = this.cancelledInboundTaskIds.has(task.id);
|
|
4381
4716
|
} catch (err) {
|
|
4717
|
+
const error = sanitizeLogText(err instanceof Error ? err.message : String(err), 200);
|
|
4382
4718
|
process2.stderr.write(`[Channel:${this.name}] handleInbound failed for ${envelope.messageId}: ${err}
|
|
4383
4719
|
`);
|
|
4384
|
-
if (
|
|
4385
|
-
|
|
4720
|
+
if (err instanceof FinalPublicationError) {
|
|
4721
|
+
if (this.cancelledInboundTaskIds.has(task.id)) {
|
|
4722
|
+
} else if (this.hasPendingFinalDeliveryForTask(task)) {
|
|
4723
|
+
this.transitionInboundTask(task.id, "reply_pending", {
|
|
4724
|
+
envelope: void 0,
|
|
4725
|
+
error
|
|
4726
|
+
});
|
|
4727
|
+
} else {
|
|
4728
|
+
this.removeInboundTask(task.id);
|
|
4729
|
+
}
|
|
4730
|
+
} else if (!this.cancelledInboundTaskIds.has(task.id)) {
|
|
4731
|
+
let posted = task.errorCommentPosted === true;
|
|
4732
|
+
if (!posted) {
|
|
4733
|
+
posted = await this.postErrorComment(envelope.chatId, task.issueNumber);
|
|
4734
|
+
}
|
|
4735
|
+
this.transitionInboundTask(task.id, "failed", {
|
|
4736
|
+
error,
|
|
4737
|
+
attempts,
|
|
4738
|
+
errorCommentPosted: posted
|
|
4739
|
+
});
|
|
4386
4740
|
}
|
|
4387
4741
|
return false;
|
|
4742
|
+
} finally {
|
|
4743
|
+
this.activeInboundTaskIdsByMessage.delete(this.inboundMessageKey(envelope.chatId, envelope.messageId));
|
|
4744
|
+
this.cancelledInboundTaskIds.delete(task.id);
|
|
4745
|
+
}
|
|
4746
|
+
if (cancelled)
|
|
4747
|
+
return true;
|
|
4748
|
+
if (this.hasPendingFinalDeliveryForTask(task)) {
|
|
4749
|
+
this.transitionInboundTask(task.id, "reply_pending", {
|
|
4750
|
+
envelope: void 0
|
|
4751
|
+
});
|
|
4752
|
+
} else {
|
|
4753
|
+
this.removeInboundTask(task.id);
|
|
4754
|
+
}
|
|
4755
|
+
return true;
|
|
4756
|
+
}
|
|
4757
|
+
async recoverInboundTasks() {
|
|
4758
|
+
const tasks = this.readInboundTasks().filter((task) => this.isRecoverableInboundTask(task));
|
|
4759
|
+
const pendingDeliveries = tasks.length ? this.readPendingFinalDeliveries(true) : [];
|
|
4760
|
+
const publicationAuditKeys = tasks.length ? this.readPublicationAuditKeys(true) : /* @__PURE__ */ new Set();
|
|
4761
|
+
for (const task of tasks) {
|
|
4762
|
+
if (!task.envelope)
|
|
4763
|
+
continue;
|
|
4764
|
+
this.applyTaskDedupe(task);
|
|
4765
|
+
if (pendingDeliveries.some((record) => record.chatId === task.source.chatId && record.threadId === task.source.threadId && record.sourceMessageId === task.source.messageId)) {
|
|
4766
|
+
this.transitionInboundTask(task.id, "reply_pending", {
|
|
4767
|
+
envelope: void 0
|
|
4768
|
+
});
|
|
4769
|
+
continue;
|
|
4770
|
+
}
|
|
4771
|
+
if (publicationAuditKeys.has(this.inboundTaskSourceKey(task))) {
|
|
4772
|
+
this.removeInboundTask(task.id);
|
|
4773
|
+
continue;
|
|
4774
|
+
}
|
|
4775
|
+
await this.runInboundTask(task);
|
|
4776
|
+
}
|
|
4777
|
+
}
|
|
4778
|
+
isRecoverableInboundTask(task) {
|
|
4779
|
+
return task.state === "accepted" || task.state === "running" || task.state === "failed" && (task.attempts ?? 0) < MAX_INBOUND_TASK_ATTEMPTS;
|
|
4780
|
+
}
|
|
4781
|
+
hasRecoverableInboundTasks() {
|
|
4782
|
+
return this.recoverableInboundTasks > 0;
|
|
4783
|
+
}
|
|
4784
|
+
hasPendingFinalDeliveryForTask(task) {
|
|
4785
|
+
return this.readPendingFinalDeliveries(true).some((record) => record.chatId === task.source.chatId && record.threadId === task.source.threadId && record.sourceMessageId === task.source.messageId);
|
|
4786
|
+
}
|
|
4787
|
+
inboundTaskSourceKey(task) {
|
|
4788
|
+
return `${task.source.chatId}|${task.source.threadId ?? ""}|${task.source.messageId ?? ""}`;
|
|
4789
|
+
}
|
|
4790
|
+
readPublicationAuditKeys(strict = false) {
|
|
4791
|
+
try {
|
|
4792
|
+
const keys = /* @__PURE__ */ new Set();
|
|
4793
|
+
for (const line of readFileSync(this.channelFilePath("github-audit.jsonl"), "utf-8").split("\n")) {
|
|
4794
|
+
if (!line)
|
|
4795
|
+
continue;
|
|
4796
|
+
try {
|
|
4797
|
+
const record = JSON.parse(line);
|
|
4798
|
+
if (record.outcome === "posted" || record.outcome === "suppressed" || record.outcome === "posting") {
|
|
4799
|
+
keys.add(`${record.repository}|${record.threadId ?? ""}|${record.sourceMessageId ?? ""}`);
|
|
4800
|
+
}
|
|
4801
|
+
} catch {
|
|
4802
|
+
continue;
|
|
4803
|
+
}
|
|
4804
|
+
}
|
|
4805
|
+
return keys;
|
|
4806
|
+
} catch (err) {
|
|
4807
|
+
if (err.code === "ENOENT")
|
|
4808
|
+
return /* @__PURE__ */ new Set();
|
|
4809
|
+
if (strict)
|
|
4810
|
+
throw err;
|
|
4811
|
+
return /* @__PURE__ */ new Set();
|
|
4812
|
+
}
|
|
4813
|
+
}
|
|
4814
|
+
applyTaskDedupe(task) {
|
|
4815
|
+
for (const [field, keys] of Object.entries(task.dedupe)) {
|
|
4816
|
+
for (const key of keys ?? []) {
|
|
4817
|
+
this.recordDispatched(field, key);
|
|
4818
|
+
}
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
transitionInboundTask(taskId, state, updates = {}) {
|
|
4822
|
+
this.updateInboundTasks((records) => records.map((record) => record.id === taskId ? {
|
|
4823
|
+
...record,
|
|
4824
|
+
...updates,
|
|
4825
|
+
state,
|
|
4826
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
4827
|
+
} : record));
|
|
4828
|
+
}
|
|
4829
|
+
removeInboundTask(taskId) {
|
|
4830
|
+
this.updateInboundTasks((records) => records.filter((record) => record.id !== taskId));
|
|
4831
|
+
}
|
|
4832
|
+
updateInboundTasks(update) {
|
|
4833
|
+
try {
|
|
4834
|
+
const records = update(this.readInboundTasks());
|
|
4835
|
+
this.writeInboundTasks(records);
|
|
4836
|
+
this.recoverableInboundTasks = records.filter((record) => this.isRecoverableInboundTask(record)).length;
|
|
4837
|
+
} catch (err) {
|
|
4838
|
+
this.inboundPersistenceBlocked = true;
|
|
4839
|
+
throw err;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
inboundTasksPath() {
|
|
4843
|
+
return this.channelFilePath("github-inbound-tasks.json");
|
|
4844
|
+
}
|
|
4845
|
+
readInboundTasks() {
|
|
4846
|
+
try {
|
|
4847
|
+
const parsed = JSON.parse(readFileSync(this.inboundTasksPath(), "utf-8"));
|
|
4848
|
+
if (!Array.isArray(parsed) || !parsed.every(isInboundTaskRecord)) {
|
|
4849
|
+
throw new Error("invalid GitHub inbound task state");
|
|
4850
|
+
}
|
|
4851
|
+
return parsed;
|
|
4852
|
+
} catch (err) {
|
|
4853
|
+
if (err.code === "ENOENT")
|
|
4854
|
+
return [];
|
|
4855
|
+
this.inboundPersistenceBlocked = true;
|
|
4856
|
+
process2.stderr.write(`[Channel:${this.name}] failed to read GitHub inbound tasks: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
4857
|
+
`);
|
|
4858
|
+
throw err;
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
writeInboundTasks(records) {
|
|
4862
|
+
const path = this.inboundTasksPath();
|
|
4863
|
+
if (records.length === 0) {
|
|
4864
|
+
try {
|
|
4865
|
+
unlinkSync(path);
|
|
4866
|
+
} catch (err) {
|
|
4867
|
+
if (err.code !== "ENOENT")
|
|
4868
|
+
throw err;
|
|
4869
|
+
}
|
|
4870
|
+
return;
|
|
4871
|
+
}
|
|
4872
|
+
const dir = dirname(path);
|
|
4873
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4874
|
+
chmodSync(dir, 448);
|
|
4875
|
+
const tmpPath = `${path}.${process2.pid}.${randomUUID()}.tmp`;
|
|
4876
|
+
writeFileSync(tmpPath, `${JSON.stringify(records)}
|
|
4877
|
+
`, {
|
|
4878
|
+
encoding: "utf-8",
|
|
4879
|
+
mode: 384
|
|
4880
|
+
});
|
|
4881
|
+
chmodSync(tmpPath, 384);
|
|
4882
|
+
renameSync(tmpPath, path);
|
|
4883
|
+
chmodSync(path, 384);
|
|
4884
|
+
}
|
|
4885
|
+
inboundMessageKey(chatId, messageId) {
|
|
4886
|
+
return `${chatId}|${messageId ?? ""}`;
|
|
4887
|
+
}
|
|
4888
|
+
onTaskLifecycle(event) {
|
|
4889
|
+
const taskId = this.activeInboundTaskIdsByMessage.get(this.inboundMessageKey(event.chatId, event.messageId));
|
|
4890
|
+
if (!taskId)
|
|
4891
|
+
return;
|
|
4892
|
+
if (event.type === "cancelled") {
|
|
4893
|
+
this.cancelledInboundTaskIds.add(taskId);
|
|
4894
|
+
this.transitionInboundTask(taskId, "cancelled");
|
|
4388
4895
|
}
|
|
4389
4896
|
}
|
|
4390
4897
|
recordPublicationAudit(record) {
|
|
4391
4898
|
try {
|
|
4392
|
-
const
|
|
4393
|
-
const
|
|
4394
|
-
const path = join(dir, `${encodedName}-github-audit.jsonl`);
|
|
4899
|
+
const dir = join(getGlobalQwenDir(), "channels", getWorkspaceScopeDirName(this.config.cwd));
|
|
4900
|
+
const path = this.channelFilePath("github-audit.jsonl");
|
|
4395
4901
|
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4396
4902
|
chmodSync(dir, 448);
|
|
4397
4903
|
appendFileSync(path, `${JSON.stringify(record)}
|
|
@@ -4405,6 +4911,35 @@ ${summary}`,
|
|
|
4405
4911
|
`);
|
|
4406
4912
|
}
|
|
4407
4913
|
}
|
|
4914
|
+
migrateLegacyPublicationState() {
|
|
4915
|
+
try {
|
|
4916
|
+
const channelsRoot = join(getGlobalQwenDir(), "channels");
|
|
4917
|
+
const encodedName = this.name.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 200);
|
|
4918
|
+
const sentinel = this.channelFilePath("github-state-migrated");
|
|
4919
|
+
if (existsSync(sentinel))
|
|
4920
|
+
return;
|
|
4921
|
+
mkdirSync(dirname(sentinel), { recursive: true, mode: 448 });
|
|
4922
|
+
for (const suffix of [
|
|
4923
|
+
"github-pending-deliveries.json",
|
|
4924
|
+
"github-audit.jsonl"
|
|
4925
|
+
]) {
|
|
4926
|
+
const legacyPath = join(channelsRoot, `${encodedName}-${suffix}`);
|
|
4927
|
+
const scopedPath = this.channelFilePath(suffix);
|
|
4928
|
+
if (!existsSync(scopedPath) && existsSync(legacyPath)) {
|
|
4929
|
+
renameSync(legacyPath, scopedPath);
|
|
4930
|
+
}
|
|
4931
|
+
}
|
|
4932
|
+
writeFileSync(sentinel, "", { mode: 384 });
|
|
4933
|
+
} catch (err) {
|
|
4934
|
+
process2.stderr.write(`[Channel:${this.name}] legacy GitHub state migration failed: ${sanitizeLogText(err instanceof Error ? err.message : String(err), 200)}
|
|
4935
|
+
`);
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
channelFilePath(suffix) {
|
|
4939
|
+
const encodedName = this.name.replace(/[^a-zA-Z0-9_-]/g, "_").slice(0, 200);
|
|
4940
|
+
const nameHash = createHash("sha256").update(this.name).digest("hex").slice(0, 16);
|
|
4941
|
+
return join(getGlobalQwenDir(), "channels", getWorkspaceScopeDirName(this.config.cwd), `${encodedName}-${nameHash}-${suffix}`);
|
|
4942
|
+
}
|
|
4408
4943
|
extractFromSubjectUrl(url) {
|
|
4409
4944
|
const match = url.match(/\/repos\/([^/]+\/[^/]+)\/(issues|pulls)\/(\d+)/);
|
|
4410
4945
|
if (!match)
|
|
@@ -4426,11 +4961,15 @@ ${GITHUB_PUBLICATION_INSTRUCTIONS}
|
|
|
4426
4961
|
Trigger: ${ctx.reason}.
|
|
4427
4962
|
${buildTriggerGuidance(ctx.reason)}`;
|
|
4428
4963
|
}
|
|
4429
|
-
async githubApi(fn, label, retries = 3, shouldRetry = () => true) {
|
|
4964
|
+
async githubApi(fn, label, retries = 3, shouldRetry = () => true, signal) {
|
|
4430
4965
|
for (let attempt = 1; attempt <= retries; attempt++) {
|
|
4966
|
+
if (signal?.aborted)
|
|
4967
|
+
throw new Error(`${label} aborted`);
|
|
4431
4968
|
try {
|
|
4432
4969
|
return await fn();
|
|
4433
4970
|
} catch (err) {
|
|
4971
|
+
if (signal?.aborted)
|
|
4972
|
+
throw err;
|
|
4434
4973
|
if (attempt === retries || !shouldRetry(err))
|
|
4435
4974
|
throw err;
|
|
4436
4975
|
const e = err;
|
|
@@ -4446,11 +4985,30 @@ ${buildTriggerGuidance(ctx.reason)}`;
|
|
|
4446
4985
|
}
|
|
4447
4986
|
process2.stderr.write(`[Channel:${this.name}] ${label} failed (attempt ${attempt}/${retries}, status=${e.status}), retrying in ${cooldown}ms: ${e.message}
|
|
4448
4987
|
`);
|
|
4449
|
-
await this.
|
|
4988
|
+
await this.sleepForRetry(cooldown, signal);
|
|
4450
4989
|
}
|
|
4451
4990
|
}
|
|
4452
4991
|
throw new Error("unreachable");
|
|
4453
4992
|
}
|
|
4993
|
+
sleepForRetry(ms, signal) {
|
|
4994
|
+
if (!signal)
|
|
4995
|
+
return this.abortableSleep(ms);
|
|
4996
|
+
return new Promise((resolve) => {
|
|
4997
|
+
if (signal.aborted) {
|
|
4998
|
+
resolve();
|
|
4999
|
+
return;
|
|
5000
|
+
}
|
|
5001
|
+
const timer = setTimeout(() => {
|
|
5002
|
+
signal.removeEventListener("abort", onAbort);
|
|
5003
|
+
resolve();
|
|
5004
|
+
}, ms);
|
|
5005
|
+
const onAbort = /* @__PURE__ */ __name(() => {
|
|
5006
|
+
clearTimeout(timer);
|
|
5007
|
+
resolve();
|
|
5008
|
+
}, "onAbort");
|
|
5009
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
5010
|
+
});
|
|
5011
|
+
}
|
|
4454
5012
|
async markNotificationsAsRead(lastReadAt) {
|
|
4455
5013
|
await this.githubApi(() => this.octokit.rest.activity.markNotificationsAsRead({
|
|
4456
5014
|
last_read_at: lastReadAt,
|
|
@@ -4465,9 +5023,11 @@ ${buildTriggerGuidance(ctx.reason)}`;
|
|
|
4465
5023
|
issue_number: issueNumber,
|
|
4466
5024
|
body: "\u26A0\uFE0F Failed to process this request. Please re-mention the bot to retry."
|
|
4467
5025
|
}), `postErrorComment(${chatId}#${issueNumber})`);
|
|
5026
|
+
return true;
|
|
4468
5027
|
} catch (err) {
|
|
4469
5028
|
process2.stderr.write(`[Channel:${this.name}] postErrorComment also failed for ${chatId}#${issueNumber}, user must re-mention manually: ${err}
|
|
4470
5029
|
`);
|
|
5030
|
+
return false;
|
|
4471
5031
|
}
|
|
4472
5032
|
}
|
|
4473
5033
|
};
|
|
@@ -4479,6 +5039,85 @@ var plugin = {
|
|
|
4479
5039
|
requiredConfigFields: ["token"],
|
|
4480
5040
|
envResolvableConfigFields: ["baseUrl"],
|
|
4481
5041
|
defaultSessionScope: "chat_thread",
|
|
5042
|
+
management: {
|
|
5043
|
+
fields: [
|
|
5044
|
+
{
|
|
5045
|
+
key: "token",
|
|
5046
|
+
label: "Personal Access Token",
|
|
5047
|
+
kind: "secret",
|
|
5048
|
+
required: true,
|
|
5049
|
+
envResolvable: true,
|
|
5050
|
+
description: 'Classic PAT with "notifications" scope'
|
|
5051
|
+
},
|
|
5052
|
+
{
|
|
5053
|
+
key: "baseUrl",
|
|
5054
|
+
label: "Base URL",
|
|
5055
|
+
kind: "string",
|
|
5056
|
+
envResolvable: true,
|
|
5057
|
+
description: "GitHub Enterprise API root (e.g. https://ghe.example.com/api/v3). Leave empty for github.com"
|
|
5058
|
+
},
|
|
5059
|
+
{
|
|
5060
|
+
key: "groupPolicy",
|
|
5061
|
+
label: "Group Policy",
|
|
5062
|
+
kind: "enum",
|
|
5063
|
+
required: true,
|
|
5064
|
+
description: 'Must be "Open" for notifications to flow',
|
|
5065
|
+
default: "open",
|
|
5066
|
+
options: [
|
|
5067
|
+
{ value: "open", label: "Open" },
|
|
5068
|
+
{ value: "allowlist", label: "Allowlist" },
|
|
5069
|
+
{ value: "disabled", label: "Disabled" }
|
|
5070
|
+
]
|
|
5071
|
+
},
|
|
5072
|
+
{
|
|
5073
|
+
key: "senderPolicy",
|
|
5074
|
+
label: "Sender Policy",
|
|
5075
|
+
kind: "enum",
|
|
5076
|
+
required: true,
|
|
5077
|
+
description: 'Use "Allowlist" with allowed users on public repos',
|
|
5078
|
+
options: [
|
|
5079
|
+
{ value: "allowlist", label: "Allowlist" },
|
|
5080
|
+
{ value: "pairing", label: "Pairing" },
|
|
5081
|
+
{ value: "open", label: "Open" }
|
|
5082
|
+
]
|
|
5083
|
+
},
|
|
5084
|
+
{
|
|
5085
|
+
key: "allowedUsers",
|
|
5086
|
+
label: "Allowed Users",
|
|
5087
|
+
kind: "string-list",
|
|
5088
|
+
description: "GitHub usernames, used by Allowlist and Pairing policies"
|
|
5089
|
+
},
|
|
5090
|
+
{
|
|
5091
|
+
key: "reasonFilter",
|
|
5092
|
+
label: "Reason Filter",
|
|
5093
|
+
kind: "string-list",
|
|
5094
|
+
description: "Optional. Comma-separated notification reasons to process. Leave empty to process all.",
|
|
5095
|
+
options: [
|
|
5096
|
+
{ value: "mention", label: "mention" },
|
|
5097
|
+
{ value: "review_requested", label: "review_requested" },
|
|
5098
|
+
{ value: "assign", label: "assign" },
|
|
5099
|
+
{ value: "author", label: "author" },
|
|
5100
|
+
{ value: "comment", label: "comment" },
|
|
5101
|
+
{ value: "ci_activity", label: "ci_activity" },
|
|
5102
|
+
{ value: "manual", label: "manual" },
|
|
5103
|
+
{ value: "state_change", label: "state_change" },
|
|
5104
|
+
{ value: "subscribed", label: "subscribed" },
|
|
5105
|
+
{ value: "team_mention", label: "team_mention" },
|
|
5106
|
+
{ value: "security_alert", label: "security_alert" },
|
|
5107
|
+
{ value: "approval_requested", label: "approval_requested" },
|
|
5108
|
+
{ value: "invitation", label: "invitation" },
|
|
5109
|
+
{
|
|
5110
|
+
value: "member_feature_requested",
|
|
5111
|
+
label: "member_feature_requested"
|
|
5112
|
+
},
|
|
5113
|
+
{
|
|
5114
|
+
value: "security_advisory_credit",
|
|
5115
|
+
label: "security_advisory_credit"
|
|
5116
|
+
}
|
|
5117
|
+
]
|
|
5118
|
+
}
|
|
5119
|
+
]
|
|
5120
|
+
},
|
|
4482
5121
|
createChannel: /* @__PURE__ */ __name((name, config, bridge, options) => new GithubChannel(name, config, bridge, options), "createChannel")
|
|
4483
5122
|
};
|
|
4484
5123
|
export {
|